这几天翻译 How to create an RPM package(https://fedoraproject.org/wiki/How_to_create_an_RPM_package),发现 RPM Spec 不像表面上看着那么简单。下面简述 RPM 工作流程。
安装流程:%pre -> 安装文件 -> %post
卸载流程:%preun -> 卸载文件 -> %postun
升级流程:new-%pre -> 安装文件 -> new-%post -> old-%preun -> 卸载文件 -> old-%postun
在以上流程中,%XXX 阶段执行的脚本被称为 脚本片段 (Scriptlet)。它用于在 RPM
包安装/升级/卸载时,对系统执行必要操作。在升级过程中,先安装新包,再卸载旧包。卸载旧包时,不会删除新包已安装的文件,以此完成升级。
假设在 %post 中编写创建文件的脚本,在 %postun 中删除此文件。安装/卸载都很顺利,但升级时问题来了。执行 old-%postun 时,会将 new-%post 中创建的文件删除。为了解决此问题,RPM 向脚本传入一个参数,表示各个阶段此软件包的数量。通过判断 $1 参数的值,执行不同动作。
另外,RPM 还有许多高级特性,如触发器、事务等。以下列出一个完整的参数值列表,供参考:
Install | Update | Uninstall | |
---|---|---|---|
%pretrans | $1 = 0 | $1 = 0 | (N/A) |
%triggerprein |
安装本包:$1 = 0, $2 = 1 安装目标包:$1 = 1, $2 = 0 |
$1 = 1, $2 = 1 | (N/A) |
%pre | $1 = 1 | $1 = 2 | (N/A) |
%post | $1 = 1 | $1 = 2 | (N/A) |
%triggerin | $1 = 1, $2 = 1 |
升级本包:$1 = 2, $2 = 1 升级目标包:$1 = 1, $2 = 2 |
(N/A) |
%triggerun | (N/A) | $1 = 1, $2 = 1 |
卸载本包:$1 = 0, $2 = 1 卸载目标包:$1 = 1, $2 = 0 |
%preun | (N/A) | $1 = 1 | $1 = 0 |
%postun | (N/A) | $1 = 1 | $1 = 0 |
%triggerpostun | (N/A) | 升级目标包:$1 = 1, $2 = 1 | 卸载目标包:$1 = 1, $2 = 0 |
%posttrans | $1 = 0 | $1 = 0 | (N/A) |
在升级软件包时,脚本片段的完整执行顺序如下:
检查软件包依赖、下载软件包和 DRPM
(all)%pretrans:事务开始时,执行新软件包的此段代码
…… (操作其它软件包) ……
(any)%triggerprein:此包的新版本安装之前,触发此包或其他包的脚本(如果有)
(new)%triggerprein:指定的其他软件包安装之前,触发此脚本
(new)%pre:执行新软件包的 %pre 脚本
…… (安装所有新文件) ……
(new)%post:执行新软件包的 %post 脚本
(any)%triggerin:安装此软件包时,触发此包或其他包的脚本(如果有)
(new)%triggerin:安装指定的其他软件包时,触发此脚本
(old)%triggerun:卸载指定的其他软件包的旧版本时,触发此脚本
(any)%triggerun:卸载此软件包的旧版本时,触发此包或其他包的脚本(如果有)
(old)%preun:执行旧软件包的 %preun 脚本
…… (删除所有旧文件) ……
(old)%postun:执行旧软件包的 %postun 脚本
(old)%triggerpostun:指定的其他软件包的旧版本已卸载之后,触发此脚本
(any)%triggerpostun:此包的旧版本已卸载之后,触发其他包的脚本(如果有;此包的脚本只由其他包触发执行,自己不运行)
…… (操作其它软件包) ……
(all)%posttrans:事务结束时,执行新软件包的此段代码
验证软件包,Done
以上就是一个完整的 RPM 包升级过程。关于 trigger 的详细信息,请参考 https://fedoraproject.org/wiki/How_to_create_an_RPM_package/zh-hk#Trigger,Done
linux中shell变量$#$@$0$1$2的含义解释:http://www.linuxdiyf.com/linux/12844.html