10 版本
本节内容需要结合 SASL 中的 rel(4)、systools(3) 和 script(4) 手册页阅读。
10.1 版本概念
当你编写了一个或多个应用程序后,你可能希望用这些应用程序和 Erlang/OTP 应用程序的子集创建一个完整的系统。这被称为 **版本**。
为此,请创建一个 版本资源文件,该文件定义了版本中包含哪些应用程序。
版本资源文件用于生成 启动脚本 和 版本包。传输到另一个站点并安装的系统称为 **目标系统**。有关如何使用版本包创建目标系统的说明,请参见系统原则。
10.2 版本资源文件
要定义版本,请创建一个 **版本资源文件**,简称 .rel 文件。在该文件中,指定版本的名称和版本、其基于的 ERTS 版本以及它包含的应用程序
{release, {Name,Vsn}, {erts, EVsn}, [{Application1, AppVsn1}, ... {ApplicationN, AppVsnN}]}.
Name、Vsn、EVsn 和 AppVsn 是字符串。
该文件必须命名为 Rel.rel,其中 Rel 是一个唯一的名称。
每个 Application(原子)和 AppVsn 是版本中包含的应用程序的名称和版本。基于 Erlang/OTP 的最小版本包含 Kernel 和 STDLIB 应用程序,因此这些应用程序必须包含在列表中。
如果要升级版本,它还必须包含 SASL 应用程序。
**示例:** 来自 应用程序 的 ch_app 版本具有以下 .app 文件
{application, ch_app, [{description, "Channel allocator"}, {vsn, "1"}, {modules, [ch_app, ch_sup, ch3]}, {registered, [ch3]}, {applications, [kernel, stdlib, sasl]}, {mod, {ch_app,[]}} ]}.
该 .rel 文件还必须包含 kernel、stdlib 和 sasl,因为这些应用程序是 ch_app 所必需的。该文件名为 ch_rel-1.rel
{release, {"ch_rel", "A"}, {erts, "5.3"}, [{kernel, "2.9"}, {stdlib, "1.12"}, {sasl, "1.10"}, {ch_app, "1"}] }.
10.3 生成启动脚本
SASL 应用程序中的 systools 包含用于构建和检查版本的工具。这些函数读取 rel 和 .app 文件并执行语法和依赖项检查。systools:make_script/1,2 函数用于生成启动脚本(参见系统原则)
1> systools:make_script("ch_rel-1", [local]).
ok
这会创建一个启动脚本,包括可读版本 ch_rel-1.script 和二进制版本 ch_rel-1.boot,由运行时系统使用。
- "ch_rel-1" 是 .rel 文件的名称,减去扩展名。
- local 选项表示启动脚本中使用应用程序所在的目录,而不是 $ROOT/lib($ROOT 是安装版本的根目录)。
这是一种在本地测试生成的启动脚本的有效方法。
使用启动脚本启动 Erlang/OTP 时,.rel 文件中的所有应用程序都会自动加载并启动
% erl -boot ch_rel-1
Erlang (BEAM) emulator version 5.3
Eshell V5.3 (abort with ^G)
1>
=PROGRESS REPORT==== 13-Jun-2003::12:01:15 ===
supervisor: {local,sasl_safe_sup}
started: [{pid,<0.33.0>},
{name,alarm_handler},
{mfa,{alarm_handler,start_link,[]}},
{restart_type,permanent},
{shutdown,2000},
{child_type,worker}]
...
=PROGRESS REPORT==== 13-Jun-2003::12:01:15 ===
application: sasl
started_at: nonode@nohost
...
=PROGRESS REPORT==== 13-Jun-2003::12:01:15 ===
application: ch_app
started_at: nonode@nohost
10.4 创建版本包
systools:make_tar/1,2 函数以 .rel 文件作为输入,并创建一个包含指定应用程序代码的压缩 tar 文件,即 **版本包**
1> systools:make_script("ch_rel-1"). ok 2> systools:make_tar("ch_rel-1"). ok
默认情况下,版本包包含
- .app 文件
- .rel 文件
- 所有应用程序的目标代码,结构根据 应用程序目录结构 组织
- 重命名为 start.boot 的二进制启动脚本
% tar tf ch_rel-1.tar
lib/kernel-2.9/ebin/kernel.app
lib/kernel-2.9/ebin/application.beam
...
lib/stdlib-1.12/ebin/stdlib.app
lib/stdlib-1.12/ebin/beam_lib.beam
...
lib/sasl-1.10/ebin/sasl.app
lib/sasl-1.10/ebin/sasl.beam
...
lib/ch_app-1/ebin/ch_app.app
lib/ch_app-1/ebin/ch_app.beam
lib/ch_app-1/ebin/ch_sup.beam
lib/ch_app-1/ebin/ch3.beam
releases/A/start.boot
releases/A/ch_rel-1.rel
releases/ch_rel-1.rel
在创建版本包之前,生成了一个新的启动脚本,没有设置 local 选项。在版本包中,所有应用程序目录都放置在 lib 下。你不知道版本包将安装在何处,因此不允许使用硬编码的绝对路径。
版本资源文件 mysystem.rel 在 tar 文件中被复制。最初,该文件仅存储在 releases 目录中,以便 release_handler 可以单独提取此文件。解压缩 tar 文件后,release_handler 会自动将文件复制到 releases/FIRST。但是,有时 tar 文件在不涉及 release_handler 的情况下被解压缩(例如,解压缩第一个目标系统时),因此该文件现在改为在 tar 文件中复制,因此无需手动复制。
如果找到了 relup 文件和/或名为 sys.config 的系统配置文件,或 sys.config.src,这些文件也将包含在版本包中。参见 版本处理。
可以设置选项以使版本包还包含源代码和 ERTS 二进制文件。
有关如何使用版本包安装第一个目标系统的说明,请参见系统原则。有关如何在现有系统中安装新的版本包的说明,请参见 版本处理。
10.5 目录结构
版本处理程序从版本包中安装的代码的目录结构如下
$ROOT/lib/App1-AVsn1/ebin /priv /App2-AVsn2/ebin /priv ... /AppN-AVsnN/ebin /priv /erts-EVsn/bin /releases/Vsn /bin
- lib - 应用程序目录
- erts-EVsn/bin - Erlang 运行时系统可执行文件
- releases/Vsn - .rel 文件和启动脚本 start.boot;如果版本包中存在,则为 relup 和/或 sys.config 或 sys.config.src
- bin - 顶级 Erlang 运行时系统可执行文件
应用程序不需要位于目录 $ROOT/lib 下。因此,可以存在包含系统不同部分的多个安装目录。例如,前面的示例可以扩展如下
$SECOND_ROOT/.../SApp1-SAVsn1/ebin /priv /SApp2-SAVsn2/ebin /priv ... /SAppN-SAVsnN/ebin /priv $THIRD_ROOT/TApp1-TAVsn1/ebin /priv /TApp2-TAVsn2/ebin /priv ... /TAppN-TAVsnN/ebin /priv
$SECOND_ROOT 和 $THIRD_ROOT 作为 变量 被引入到调用 systools:make_script/2 函数中。
无盘和/或只读客户端
如果完整的系统包含无盘和/或只读客户端节点,则需要在 $ROOT 目录中添加一个 clients 目录。只读节点是指具有只读文件系统的节点。
clients 目录中应包含每个支持的客户端节点的一个子目录。每个客户端目录的名称应为其对应客户端节点的名称。最少,每个客户端目录都应包含 bin 和 releases 子目录。这些目录用于存储有关已安装版本的的信息并将当前版本指定给客户端。因此,$ROOT 目录包含以下内容
$ROOT/... /clients/ClientName1/bin /releases/Vsn /ClientName2/bin /releases/Vsn ... /ClientNameN/bin /releases/Vsn
如果所有客户端都运行相同的 Erlang 机器类型,则应使用此结构。如果存在运行不同 Erlang 机器类型或在不同操作系统上的客户端,则 clients 目录可以划分为每个 Erlang 机器类型一个子目录。或者,可以为每种机器类型设置一个 $ROOT。对于每种类型,都应包含为 $ROOT 目录指定的某些目录
$ROOT/... /clients/Type1/lib /erts-EVsn /bin /ClientName1/bin /releases/Vsn /ClientName2/bin /releases/Vsn ... /ClientNameN/bin /releases/Vsn ... /TypeN/lib /erts-EVsn /bin ...
使用此结构,Type1 的客户端的根目录为 $ROOT/clients/Type1。