查看源代码 发布

建议同时阅读 SASL 中的 relsystoolsscript 部分。

发布概念

当你编写了一个或多个应用程序后,你可能希望使用这些应用程序和 Erlang/OTP 应用程序的子集创建一个完整的系统。这被称为发布

为此,创建一个发布资源文件,该文件定义了发布中包含哪些应用程序。

发布资源文件用于生成引导脚本发布包。被传输并安装到另一个站点的系统称为目标系统。如何在系统原则中,使用发布包创建目标系统的方法在创建和升级目标系统中进行了描述。

发布资源文件

要定义一个发布,创建一个发布资源文件,简称为 .rel 文件。在该文件中,指定发布的名称和版本、所基于的 ERTS 版本以及它包含的应用程序。

{release, {Name,Vsn}, {erts, EVsn},
 [{Application1, AppVsn1},
   ...
  {ApplicationN, AppVsnN}]}.

NameVsnEVsnAppVsn 都是字符串。

该文件必须命名为 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 文件还必须包含 kernelstdlibsasl,因为 ch_app 需要这些应用程序。该文件名为 ch_rel-1.rel

{release,
 {"ch_rel", "A"},
 {erts, "14.2.5"},
 [{kernel, "9.2.4"},
  {stdlib, "5.2.3"},
  {sasl, "4.2.1"},
  {ch_app, "1"}]
}.

生成引导脚本

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/OTP 26 [erts-14.2.5] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Eshell V14.2.5 (press Ctrl+G to abort, type help(). for help)
1> application:which_applications().
[{ch_app,"Channel allocator","1"},
 {sasl,"SASL  CXC 138 11","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","5.2.3"},
 {kernel,"ERTS  CXC 138 10","9.2.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-9.2.4/ebin/kernel.app
lib/kernel-9.2.4/ebin/application.beam
...
lib/stdlib-5.2.3/ebin/stdlib.app
lib/stdlib-5.2.3/ebin/argparse.beam
...
lib/sasl-4.2.1/ebin/sasl.app
lib/sasl-4.2.1/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/ch_rel-1.rel
releases/A/ch_rel-1.rel
releases/A/start.boot

在制作发布包之前,生成了一个新的引导脚本,没有设置 local 选项。在发布包中,所有应用程序目录都放置在 lib 下。你不知道发布包将安装在哪里,因此不允许使用硬编码的绝对路径。

发布资源文件 mysystem.rel 在 tar 文件中被复制。最初,此文件仅存储在 releases 目录中,以便 release_handler 可以单独提取此文件。解压缩 tar 文件后,release_handler 会自动将该文件复制到 releases/FIRST。但是,有时会在不涉及 release_handler 的情况下解压缩 tar 文件(例如,解压缩第一个目标系统时),因此该文件现在被复制到 tar 文件中,因此无需手动复制。

如果找到 relup 文件和/或名为 sys.config 的系统配置文件,或者 sys.config.src,这些文件也会包含在发布包中。请参阅发布处理

可以设置选项以使发布包包含源代码和 ERTS 二进制文件。

有关如何使用发布包安装第一个目标系统的信息,请参阅系统原则。有关如何在现有系统中安装新发布包的信息,请参阅发布处理

目录结构

发布处理程序从发布包安装的代码的目录结构如下

$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.configsys.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 函数时被引入为 variables

无盘和/或只读客户端

如果一个完整的系统由无盘和/或只读客户端节点组成,则需要在 $ROOT 目录中添加一个 clients 目录。只读节点是具有只读文件系统的节点。

clients 目录为每个受支持的客户端节点都设置一个子目录。每个客户端目录的名称应为相应客户端节点的名称。至少,每个客户端目录都应包含 binreleases 子目录。这些目录用于存储有关已安装发布的信息,并为客户端指定当前发布。$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