脚本
这个文档讲述了 openRuyi 对于软件包安装和移除时脚本的编写策略。
RPM spec 文件中有几个部分允许软件包在安装和移除时运行代码,这类都被称为脚本段。
在 openRuyi 中,所有脚本段都可以假设它们在 bash 下运行,除非使用了其它的编程语言。
语法
基本语法类似于 spec 文件中的 %build、%install 和其他部分。这些脚本支持一个特殊的标志 -p,它允许脚本段直接调用单个程序,而不必生成一个 shell 来调用程序。例如使用 %post -p /usr/bin/ldconfig。
脚本段还会接收一个由控制 rpmbuild 进程传递给它们的参数。这个参数(通过 $1 访问)是当操作完成时,系统中将保留的同名软件包的数量。因此,对于安装、升级和卸载这几种常见情况,我们有:
| install | upgrade | uninstall | |
|---|---|---|---|
%pretrans | $1 == 1 | $1 == 2 | (N/A) |
%pre | $1 == 1 | $1 == 2 | (N/A) |
%post | $1 == 1 | $1 == 2 | (N/A) |
%preun | (N/A) | $1 == 1 | $1 == 0 |
%postun | (N/A) | $1 == 1 | $1 == 0 |
%posttrans | $1 == 1 | $1 == 2 | (N/A) |
请注意,如果安装了同一软件包的多个版本 (这主要发生在可并行安装的软件包,如内核和 multilib 软件包中。但是,当错误导致软件包升级未完成时,也可能发生这种情况),这些值将会有所不同。因此,最好将如下代码用于 %pre 和 %post,而不是检查它是否等于 2:
%pre
if [ "$1" -gt 1 ] ; then
...
fi
所有的脚本段都应该以退出状态码 0 结束。因为 RPM 默认在执行 shell 脚本小程序时不会向 shell 传递 -e 参数,所以除了不赞成使用的显式 exit 调用外,脚本段中最后一条命令的退出状态码决定了它的退出状态码。
本文档的代码片段中的大多数命令都附加了 "|| :",这是一种通过执行 :,一个与 /bin/true 作用相同的 shell 语法而忽略这些命令退出状态码的方法。这个方法通常应用在脚本段中的最后一条命令上。不过需要注意的是,在一些情况下,其他的错误检查方法可能更合适,并且不应该应用在某个必须成功的前提命令上,请根据具体情况来使用。
一旦脚本段以非退出状态码 0 结束,这可能会破坏正在进行的安装/升级/卸载操作,从而会有连锁反应——例如导致在升级时旧版本的软件包未被正确移除,从而在 rpmdb 中留下重复的条目,并可能在文件系统上留下过时的、未被任何软件包所管理的无主的文件。在某些情况下,如果脚本段执行失败后仍继续执行,可能会导致安装结果部分损坏或系统配置不完整。不过,这类问题通常仅限于当前软件包本身;相较之下,若在事务 (transaction) 执行过程中有部分软件包被动态移除后仍继续执行,往往会引发更大范围的系统级问题。
顺序
%pre 和 %post 中的脚本段分别在软件包安装之前和之后运行。%preun 和 %postun 脚本段在软件包卸载之前和之后运行。%pretrans 和 %posttrans 脚本段分别在事务的开始和结束时运行。在升级时,脚本段按以下顺序运行:
-
新软件包的
%pretrans -
新软件包的
%pre -
(安装新软件包)
-
新软件包的
%post -
其他软件包的
%triggerin(由安装新软件包触发) -
新软件包的
%triggerin(如果存在为 true 的触发器) -
旧软件包的
%triggerun(如果它由卸载旧软件包触发) -
其他软件包的
%triggerun(由卸载旧软件包触发) -
旧软件包的
%preun -
(移除旧软件包)
-
旧软件包的
%postun -
旧软件包的
%triggerpostun(如果它由卸载旧软件包触发) -
其他软件包的
%triggerpostun(如果它们由卸载旧软件包触发) -
新软件包的
%posttrans
请注意,%pretrans 脚本段会在任何新软件包被安装之前运行。这意味着它不能有任何依赖关系。因此,最好避免使用 %pretrans。