安装一个发布
当我们完成了一个发布的新版本,然后就可以用这个新版本创建一个发布包并传输到目标环境中。
要在运行时安装新版本的发布,得用到发布处理器。它是属于SASL应用的一个进程,负责发布包的解包、安装和移除。它通过模块 release_handler 暴露了借口,在 release_handler(3) 中有详细阐述。
机设有一个正在运行的目标系统,安装根目录是 $ROOT ,包含发布新版本的发布包应被复制到 $ROOT/releases 中。
第一个动作是先解开发布包,然后文件从包中被释放出来:
- 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 中指令:
- release_handler:install_release(Vsn) => {ok, FromVsn, []}
如果在安装过程中出现了错误,那么系统会使用老版本的发布重新启动。如果安装成功了,系统以后就会使用新版本的发布,但是一旦出了状况系统重启了,那么还是会使用前一个版本进行启动。为了能成为默认版本,新安装的发布必须被设为持久(permanent)的,也就是说前一个版本变成旧的了:
- release_handler:make_permanent(Vsn) => ok
系统将哪个版本是旧的哪个是持久的信息保存在文件 $ROOT/releases/RELEASES 和 $ROOT/releases/start_erl.data 。
要从 Vsn 降级至 FromVsn ,必须再次调用 install_release :
- release_handler:install_release(Vsn) => {ok, FromVsn, []}
一个安装了,但是并非持久的发布可以被移除。然后关于该发布的信息会从 $ROOT/releases/RELEASES 中被删除,同时该发布指定的代码,也就是新的应用的目录和 $ROOT/releases/Vsn 目录都会被删除。
接着前一节的例子:
- 按照系统原理中所描述的创建一个目标系统,包含来自 发布 一章的 ch_rel 的第一个版本“A”。这次必须在发布包中包含 sys.config 。如果不需要任何配置,该文件应该包含空列表:
- [].
- 作为一个简单的目标系统启动。注意实际中,它要作为一个嵌入式系统启动。不过,用正确的启动脚本以及 .config 文件启动 erl 对于描述我们的目的已经足够了:
- % cd $ROOT
- % bin/erl -boot $ROOT/releases/A/start -config $ROOT/releases/A/sys
- ...
- 在另一个Erlang shell中,为新版本“B”生成启动脚本并创建发布包。记住要包含(一个可能更新过的) sys.config 文件和 relup 文件,参见之前的 发布升级文件 。
- 1> systools:make_script("ch_rel-2").
- ok
- 2> systools:make_tar("ch_rel-2").
- ok
现在新的发布包包含了 ch_app 的版本“2”和 relup 文件:
- % tar tf ch_rel-2.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-2/ebin/ch_app.app
- lib/ch_app-2/ebin/ch_app.beam
- lib/ch_app-2/ebin/ch_sup.beam
- lib/ch_app-2/ebin/ch3.beam
- releases/B/start.boot
- releases/B/relup
- releases/B/sys.config
- releases/ch_rel-2.rel
- 将发布包 ch_rel-2.tar.gz 复制到 $ROOT/releases 目录中。
- 在运行中的目标系统上,解开发布包:
- 1> release_handler:unpack_release("ch_rel-2").
- {ok,"B"}
新应用版本 ch_app-2 被安装在 $ROOT/lib 中,就在 ch_app-1 旁边。 kernel 、 stdlib 和 sasl 目录没受影响,因为都没有做过更改。
在 $ROOT/releases ,创建了一个新目录 B ,里面包含了 ch_rel-2.rel 、 start.boot 、 sys.config 和 relup 。
- 检查函数 ch3:available/0 是否可用:
- 2> ch3:available().
- ** exception error: undefined function ch3:available/0
- 安装新的发布。执行 $ROOT/releases/B/relup 中的指令,最后新版本的 ch3 载入了。现在函数 ch3:available/0 就可用了:
- 3> release_handler:install_release("B").
- {ok,"A",[]}
- 4> ch3:available().
- 3
- 5> code:which(ch3).
- ".../lib/ch_app-2/ebin/ch3.beam"
- 6> code:which(ch_sup).
- ".../lib/ch_app-1/ebin/ch_sup.beam"
在 ch_app 中没有更新过代码的进程,例如督程,会继续执行 ch_app-1 中的代码。8. 如果目标系统现在重启了,它还会继续使用“A”。“B”版本必须设置为持久才能在系统重启之后被使用。
- 7> release_handler:make_permanent("B").
- ok