安装一个发布

当我们完成了一个发布的新版本,然后就可以用这个新版本创建一个发布包并传输到目标环境中。

要在运行时安装新版本的发布,得用到发布处理器。它是属于SASL应用的一个进程,负责发布包的解包、安装和移除。它通过模块 release_handler 暴露了借口,在 release_handler(3) 中有详细阐述。

机设有一个正在运行的目标系统,安装根目录是 $ROOT ,包含发布新版本的发布包应被复制到 $ROOT/releases 中。

第一个动作是先解开发布包,然后文件从包中被释放出来:

  1. release_handler:unpack_release(ReleaseName) => {ok, Vsn}

ReleaseName 是发布包去掉 .tar.gz 扩展之后的名字。 Vsn 是被解开的发布的版本,和在 .rel 文件中定义的一样。

然后会创建一个 $ROOT/lib/releases/Vsn ,其中有 .rel 文件、启动脚本 start.boot 、系统配置文件 sys.config 以及 relup 文件。对于有新版本号的应用,应用目录会被放在 $ROOT/lib 下。未更改的应用不受影响。

解开的发布可以被安装。然后发布处理器会一条条执行在 relup 中指令:

  1. release_handler:install_release(Vsn) => {ok, FromVsn, []}

如果在安装过程中出现了错误,那么系统会使用老版本的发布重新启动。如果安装成功了,系统以后就会使用新版本的发布,但是一旦出了状况系统重启了,那么还是会使用前一个版本进行启动。为了能成为默认版本,新安装的发布必须被设为持久(permanent)的,也就是说前一个版本变成旧的了:

  1. release_handler:make_permanent(Vsn) => ok

系统将哪个版本是旧的哪个是持久的信息保存在文件 $ROOT/releases/RELEASES$ROOT/releases/start_erl.data

要从 Vsn 降级至 FromVsn ,必须再次调用 install_release

  1. release_handler:install_release(Vsn) => {ok, FromVsn, []}

一个安装了,但是并非持久的发布可以被移除。然后关于该发布的信息会从 $ROOT/releases/RELEASES 中被删除,同时该发布指定的代码,也就是新的应用的目录和 $ROOT/releases/Vsn 目录都会被删除。

接着前一节的例子:

  • 按照系统原理中所描述的创建一个目标系统,包含来自 发布 一章的 ch_rel 的第一个版本“A”。这次必须在发布包中包含 sys.config 。如果不需要任何配置,该文件应该包含空列表:
  1. [].
  • 作为一个简单的目标系统启动。注意实际中,它要作为一个嵌入式系统启动。不过,用正确的启动脚本以及 .config 文件启动 erl 对于描述我们的目的已经足够了:
  1. % cd $ROOT
  2. % bin/erl -boot $ROOT/releases/A/start -config $ROOT/releases/A/sys
  3. ...
  • 在另一个Erlang shell中,为新版本“B”生成启动脚本并创建发布包。记住要包含(一个可能更新过的) sys.config 文件和 relup 文件,参见之前的 发布升级文件
  1. 1> systools:make_script("ch_rel-2").
  2. ok
  3. 2> systools:make_tar("ch_rel-2").
  4. ok

现在新的发布包包含了 ch_app 的版本“2”和 relup 文件:

  1. % tar tf ch_rel-2.tar
  2. lib/kernel-2.9/ebin/kernel.app
  3. lib/kernel-2.9/ebin/application.beam
  4. ...
  5. lib/stdlib-1.12/ebin/stdlib.app
  6. lib/stdlib-1.12/ebin/beam_lib.beam
  7. ...
  8. lib/sasl-1.10/ebin/sasl.app
  9. lib/sasl-1.10/ebin/sasl.beam
  10. ...
  11. lib/ch_app-2/ebin/ch_app.app
  12. lib/ch_app-2/ebin/ch_app.beam
  13. lib/ch_app-2/ebin/ch_sup.beam
  14. lib/ch_app-2/ebin/ch3.beam
  15. releases/B/start.boot
  16. releases/B/relup
  17. releases/B/sys.config
  18. releases/ch_rel-2.rel
  • 将发布包 ch_rel-2.tar.gz 复制到 $ROOT/releases 目录中。
  • 在运行中的目标系统上,解开发布包:
  1. 1> release_handler:unpack_release("ch_rel-2").
  2. {ok,"B"}

新应用版本 ch_app-2 被安装在 $ROOT/lib 中,就在 ch_app-1 旁边。 kernelstdlibsasl 目录没受影响,因为都没有做过更改。

$ROOT/releases ,创建了一个新目录 B ,里面包含了 ch_rel-2.relstart.bootsys.configrelup

  • 检查函数 ch3:available/0 是否可用:
  1. 2> ch3:available().
  2. ** exception error: undefined function ch3:available/0
  • 安装新的发布。执行 $ROOT/releases/B/relup 中的指令,最后新版本的 ch3 载入了。现在函数 ch3:available/0 就可用了:
  1. 3> release_handler:install_release("B").
  2. {ok,"A",[]}
  3. 4> ch3:available().
  4. 3
  5. 5> code:which(ch3).
  6. ".../lib/ch_app-2/ebin/ch3.beam"
  7. 6> code:which(ch_sup).
  8. ".../lib/ch_app-1/ebin/ch_sup.beam"

ch_app 中没有更新过代码的进程,例如督程,会继续执行 ch_app-1 中的代码。8. 如果目标系统现在重启了,它还会继续使用“A”。“B”版本必须设置为持久才能在系统重启之后被使用。

  1. 7> release_handler:make_permanent("B").
  2. ok