Erlang系统原则

本文档主要说明一些Erlang系统相关的内容。

System Principles

启动一个系统

Erlang系统使用erl命令启动

1
2
3
4
Erlang/OTP 21 [erts-10.3.5.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Eshell V10.3.5.4 (abort with ^G)
1>

erl可以解析很多命令行参数,可以查看ERTS中的erl(1)手册。
应用程序可以通过调用函数init:get_argument(Key) 或 init:get_arguments() 来访问命令行参数的值。可以参考ERTS中init(3)。

重启和停止系统

通过调用halt/0,1来停止运行时系统。
模块init包含用于restarting, rebooting, 和 stopping运行时的系统。

1
2
3
init:restart()
init:reboot()
init:stop()

如果终止了Erlang shell,则运行时系统将终止。

Boot Scripts

运行时系统使用引导脚本启动。启动脚本包含有关加载哪些代码以及启动哪些进程和应用程序的指令。
启动脚本文件的扩展名是.script。运行时系统使用脚本的二进制版本。这个二进制启动脚本文件的扩展名是.boot
使用那个引导脚本由命令行标志-boot指定。扩展名.boot将被省略。例如,使用启动脚本start_all.boot:

1
% erl -boot start_all

如果没有指定引导脚本,它默认为ROOT/bin/start,可以查看Default Boot Scripts。
命令行标志-init_debug使init进程在解释启动脚本时写入一些调试信息:

1
2
3
4
5
6
7
% erl -init_debug
{progress,preloaded}
{progress,kernel_load_completed}
{progress,modules_loaded}
{start,heart}
{start,logger}
...

有关引导脚本的语法和内容的详细描述,可以参阅SASL中script(4)手册。

Default Boot Scripts

Erlang/OTP附带以下启动脚本:
start_clean.boot 引导-加载应用程序内核和STDLIB代码并启动它们。
start_sasl.boot 引导-加载应用程序内核、STDLIB和SASL的代码并启动它们)。
no_dot_erlang.boot 引导-加载应用程序内核和STDLIB的代码并启动它们。跳过加载file.erlang。适用于脚本和其他工具,它们的行为与用户的偏好无关。
在使用install 安装Erlang/OTP时,由用户决定默认使用start_clean和start_sasl中的那一个。用户会被问到“您是否希望使用最小的系统启动而不是SASL启动”。如果答案是肯定的,那么使用start_clean,否则使用start_sasl。生成所选启动脚本的副本,名为start。启动并放置在/ROOT/bin。

User-Defined Boot Scripts

有时创建用户定义的引导脚本是有用的或者必要的。特别是在嵌入式的模式下运行。see Code Loading Strategy。
可以手动编写引导脚本。但是,建议通过从发布资源文件名生成引导脚本来创建它。使用systools:make_script/1,2。这要求源代码按照OTP设计原则构建为应用程序。(该程序不必启动OTP应用程序,但是可以使普通的Erlang)。
有关.rel文件的更多信息,请参见SASL中OTP设计原则和rel(4)手册。
二进制启动脚本文件名。引导是由引导脚本文件名生成的。脚本,使用systools:script2boot(File)。

Code Loading Strategy

运行时系统可以以嵌入式(embedded)或交互式(interactive)模式启动。哪一个是由命令行标志模式决定的。-mode

1
% erl -mode embedded

默认是interactive
模式属性如下:
在嵌入式模式下,所有代码都是在系统启动期间根据引导脚本加载的。(稍后还可以通过显式地命令行代码服务器加载代码)。
在交互模式下,代码在第一次引用时被动态加载。当对模块中的函数进行调用,而模块没有加载时,代码服务器将搜索代码路径并将模块加载到系统中。
最初,代码路径由当前工作目录和ROOT/lib下的所有目标代码目录组成,根目录是Erlang/OTP的安装目录。目录可以命名为Name[-vsn]。默认情况下,代码服务器将选择同名目录中版本号最高的目录。后缀-Vsn是可选的。如果名称[-Vsn]是可选的。如果名称[-Vsn]目录下存在ebin目录,则将该目录添加到代码路径中。
可以使用命令行标志-pa目录和-pz目录扩展代码路径。它们分别将添加到代码路径的开头或结尾。例子:

1
% erl -pa /home/arne/mycode

代码服务器模块代码包含了许多修改和检查搜索路径的函数,see code(3)。

文件类型

1.Module .erl 模块
2.Include file .hrl 头文件
3.Release resource file .rel 发布资源文件
4.Application resourece file .app 应用程序文件
5.Boot script .script 引导脚本文件
6.Binary boot script .boot 二进制引导脚本文件
7.Configuration file .config 配置文件
8.Application upgrade file .appup 应用程序更新文件
9.Release upgrade file relup 发布升级文件

Error Logging

Error Information From the Runtime System

运行时系统中的错误信息,即由于未捕获的错误异常导致进程终止的信息,在默认的情况下被写入到terminal(tty):

1
2
=ERROR REPORT==== 9-Dec-2003::13:25:02 ===
Error in process <0.27.0> with exit value: {{badmatch,[1,2,3]},[{m,f,1},{shell,eval_loop,2}]}

错误信息由Logger处理,它是内核应用程序的一部分。
运行时系统使用的退出原因(如badarg)在错误和错误处理中进行了描述。(Errors and Error Handling).
有关日志记录器及其用户界面的信息。可以对系统进行配置,以便将日志事件写入文件或tty,或者两者都写入。此外,用户定义的应用程序可以使用Logger发送和格式化日志事件。

Log events from OTP behaviours

标准行为(supervisor、gen_server等)将进度和错误信息发送给Logger。进度报告默认不记录,但是可以通过将主日志级别设置为info来启用,例如通过使用内核配置参数logger_level。监控器报告、崩溃报告和其他错误和信息报告默认通过日志处理程序记录,日志处理程序是在内核应用程序启动时设置的。
在Erlang/OTP 21.0之前,只有在SASL应用程序运行时才记录管理程序、崩溃和进度报告。为了向后兼容,可以通过将内核配置参数logger_sasl_compatible设置为true来启用此行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
% erl -kernel logger_level info
Erlang/OTP 21 [erts-10.0] [source-13c50db] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

=PROGRESS REPORT==== 8-Jun-2018::16:54:19.916404 ===
application: kernel
started_at: nonode@nohost
=PROGRESS REPORT==== 8-Jun-2018::16:54:19.922908 ===
application: stdlib
started_at: nonode@nohost
=PROGRESS REPORT==== 8-Jun-2018::16:54:19.925755 ===
supervisor: {local,kernel_safe_sup}
started: [{pid,<0.74.0>},
{id,disk_log_sup},
{mfargs,{disk_log_sup,start_link,[]}},
{restart_type,permanent},
{shutdown,1000},
{child_type,supervisor}]
=PROGRESS REPORT==== 8-Jun-2018::16:54:19.926056 ===
supervisor: {local,kernel_safe_sup}
started: [{pid,<0.75.0>},
{id,disk_log_server},
{mfargs,{disk_log_server,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
Eshell V10.0 (abort with ^G)
1>

Creating and Upgrading a Target System

使用Erlang/OTP创建系统时,最简单的方法是在某个地方安装Erlang/OTP,在其他地方安装特定于应用程序的代码,然后启动Erlang运行时系统,确保代码路径包含特定于应用程序的代码。
通常不希望按原样使用Erlang/OTP系统。开发人员可以为特定的目的创建新的符合Erlang/OTP的应用程序,而几个原始的Erlang/OTP应用程序可能与目标无关。因此,需要能够基于给定Erlang/OTP系统创建新系统,删除不必要的应用程序并包含新的应用程序。文档和源代码是不相关的,因此不包含在新系统中。
本章是关于创建一个系统,它被称为目标系统。
下面几节讨论具有不同功能需求的目标系统:

  • 一个简单的目标系统,可以通过调用普通的erl脚本来启动。
  • 一个简单的目标系统,也可以在运行时进行代码替换。
    嵌入式目标系统,其中还支持将系统输出的日志记录到文件中供以后检查,并且可以在引导时自动启动系统。
    这里只考虑在UNIX系统上运行Erlang/OTP的情况。
    sasl应用程序包括示例Erlang模块target_system。它包含用于创建和安装目标系统的函数。

支持,兼容性,弃用和删除 (Support, Compatibility, Deprecations, and Removal)

Supported Releases

一般来说,bug只在最新的版本去修复,新特性将在正在开发的新版本中引入。但是,由于内部原因,当我们修复旧版本的bug时,这些bug也会发布。
由于上述原因,pull请求只在git存储库中maint和master分支上被接受。maint分支包含对最新OTP版本的下一个维护补丁包的计划更改,而master包含对即将到来的OTP版本的计划更改。