5.3. Epoch, Scriptlets 和 Triggers
本节介绍了 Epoch
、Scriptlets
和 Triggers
,它们代表 RMP spec
文件的高级指令。
所有这些指令不仅影响 spec
文件,还影响安装了生成的 RPM 的终端机器。
5.3.1. Epoch 指令
Epoch
指令支持根据版本号定义权重的依赖关系。
如果 RPM spec
文件中没有列出这个指令,则根本不会设置 Epoch
指令。这与常规的理解不同:不设置 Epoch
的结果是 Epoch
为 0。但是,dnf
工具会把一个未设置的 Epoch
视为 Epoch
为 0 用于处理。
但是,在 spec
文件中列出 Epoch
通常会省略,因为在大多数情况下,引入 Epoch
值会在比较软件包版本时扭曲预期的 RPM 行为。
例 5.2. 使用 Epoch
如果您安装了 foobar
软件包,带有 Epoch:1
和 Version:1.0
,以及其它软件包 foobar
,带有 Version:2.0
但没有 Epoch
指令,新版本永远不会被视为更新。原因是,在签发 RPM 软件包版本是首选使用 Epoch
版本而不是传统的 Name-Version-Release
marker。
使用 Epoch
比较罕见。但是,Epoch
通常用于解决升级排序问题。在软件版本号方案或带有字母字符的版本中,这个问题可能会出现上游变化的影响,这些字符不能始终根据编码进行可靠地进行比较。
5.3.2. scriptlets 指令
Scriptlets 是一组在安装或删除软件包之前或之后执行的 RPM 指令。
使用 Scriptlets 仅在构建时或启动脚本中无法完成的任务。
存在一组常用 Scriptlet 指令。它们与 spec
文件部分标题头类似,如 %build
或 %install
。它们由多行代码段定义,这些片段通常写为标准的 POSIX shell 脚本。但是,它们也可以使用其他适用于目标机器分布接受的 RPM 编程语言编写。RPM 文档包括可用语言的详尽列表。
下表包含 Scriptlet 指令,按其执行顺序列出。请注意,包含脚本的软件包会在 %pre
和 %post
指令之间安装,并在 %preun
和 %postun
指令之间卸载。
指令 | 定义 |
---|---|
| Scriptlet 在安装或删除任何软件包之前执行。 |
| Scriptlet 在目标系统上安装软件包之前执行。 |
| Scriptlet 仅在目标系统上安装软件包后执行。 |
| 在从目标系统卸载软件包前执行的 Scriptlet。 |
| Scriptlet 在软件包从目标系统卸载后执行。 |
| 在事务结束时执行的 Scriptlet。 |
5.3.3. 关闭 scriptlet 执行
下面的步骤描述了如何使用 rpm
命令和 --no_scriptlet_name_
选项一起关闭任何 scriptlet 的执行。
流程
例如,要关闭
%pretrans
scriptlets 的执行,请运行:# rpm --nopretrans
您还可以使用
-- noscripts
选项,它等同于以下所有:-
--nopre
-
--nopost
-
--nopreun
-
--nopostun
-
--nopretrans
-
--noposttrans
-
其他资源
-
rpm(8)
手册页.
5.3.4. scriptlets 宏
Scriptlets 指令也适用于 RPM 宏。
以下示例显示了使用 systemd scriptlet 宏,这样可确保 systemd 会收到有关新单元文件的通知。
$ rpm --showrc | grep systemd -14: __transaction_systemd_inhibit %{__plugindir}/systemd_inhibit.so -14: _journalcatalogdir /usr/lib/systemd/catalog -14: _presetdir /usr/lib/systemd/system-preset -14: _unitdir /usr/lib/systemd/system -14: _userunitdir /usr/lib/systemd/user /usr/lib/systemd/systemd-binfmt %{?*} >/dev/null 2>&1 || : /usr/lib/systemd/systemd-sysctl %{?*} >/dev/null 2>&1 || : -14: systemd_post -14: systemd_postun -14: systemd_postun_with_restart -14: systemd_preun -14: systemd_requires Requires(post): systemd Requires(preun): systemd Requires(postun): systemd -14: systemd_user_post %systemd_post --user --global %{?*} -14: systemd_user_postun %{nil} -14: systemd_user_postun_with_restart %{nil} -14: systemd_user_preun systemd-sysusers %{?*} >/dev/null 2>&1 || : echo %{?*} | systemd-sysusers - >/dev/null 2>&1 || : systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || : $ rpm --eval %{systemd_post} if [ $1 -eq 1 ] ; then # Initial installation systemctl preset >/dev/null 2>&1 || : fi $ rpm --eval %{systemd_postun} systemctl daemon-reload >/dev/null 2>&1 || : $ rpm --eval %{systemd_preun} if [ $1 -eq 0 ] ; then # Package removal, not upgrade systemctl --no-reload disable > /dev/null 2>&1 || : systemctl stop > /dev/null 2>&1 || : fi
5.3.5. Triggers 指令
Triggers 是 RPM 指令,可提供在软件包安装和卸载期间交互的方法。
Triggers 可能会在意外执行,例如在更新包含软件包时执行。很难调试 Triggers,因此需要以可靠的方式实施它们,以便在意外执行时不会中断任何操作。因此,红帽建议尽可能减少使用 Triggers。
下面列出了一次软件包升级的顺序以及每个现有 Triggers 的详情:
all-%pretrans … any-%triggerprein (%triggerprein from other packages set off by new install) new-%triggerprein new-%pre for new version of package being installed … (all new files are installed) new-%post for new version of package being installed any-%triggerin (%triggerin from other packages set off by new install) new-%triggerin old-%triggerun any-%triggerun (%triggerun from other packages set off by old uninstall) old-%preun for old version of package being removed … (all old files are removed) old-%postun for old version of package being removed old-%triggerpostun any-%triggerpostun (%triggerpostun from other packages set off by old un install) … all-%posttrans
以上项目位于 /usr/share/doc/rpm-4.*/triggers
文件中。
5.3.6. 在 spec 文件中使用非 shell 脚本
spec
文件中的 -p
scriptlet 选项使用户可以调用特定的解释器,而不是默认的 shell 脚本解释器(-p /bin/sh
)。
下面的步骤描述了如何创建脚本,它会在安装 pello.py
程序后输出信息:
流程
-
打开
pello.spec
文件。 找到以下行:
install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/
在上面的行下,插入:
%post -p /usr/bin/python3 print("This is {} code".format("python"))
- 按照构建 RPM 中所述构建您的软件包。
安装软件包:
# dnf install /home/<username>/rpmbuild/RPMS/noarch/pello-0.1.2-1.el8.noarch.rpm
安装后检查输出信息:
Installing : pello-0.1.2-1.el8.noarch 1/1 Running scriptlet: pello-0.1.2-1.el8.noarch 1/1 This is python code
要使用 Python 3 脚本,请在 spec
文件中的 install -m
下包含以下行:
%post -p /usr/bin/python3
要使用 Lua 脚本,在 SPEC 文件中的 install -m
下包含以下行:
%post -p <lua>
这样,您可以在 spec
文件中指定任何解释器。