如何测试 RPM 宏的参数?

各位大佬好!

情况介绍

CentOS 7 下学习打 RPM 包,网上没有找到在命令行怎么测试 RPM 宏的参数,用的到包是 php-fpm :

wget -c \
'https://repo.ius.io/7/x86_64/packages/p/php73-fpm-7.3.13-1.el7.ius.x86_64.rpm' \
'https://repo.ius.io/7/src/packages/p/php73-7.3.13-1.el7.ius.src.rpm'

RPM 宏的定义:

# /usr/lib/rpm/macros.d/macros.systemd
%systemd_post () \
if [ $1 -eq 1 ] ; then \
        # Initial installation \
        systemctl preset %{?*} >/dev/null 2>&1 || : \
fi \
%{nil}

SPEC 文件中的使用方式:

%post fpm
%systemd_post php-fpm.service

rpm 安装 rpm 生成的脚本,可以看到 systemctl 命令是有参数的:

# rpm -qp --scripts php73-fpm-7.3.13-1.el7.ius.x86_64.rpm | Less
postinstall scriptlet (using /bin/sh):

if [ $1 -eq 1 ] ; then 
        # Initial installation 
        systemctl preset php-fpm.service >/dev/null 2>&1 || : 
fi

使用 rpm --eval 测试的结果,参数的处理和脚本里不一样:

$ » rpm --eval "%{systemd_post} php-fpm.service"

if [ $1 -eq 1 ] ; then 
        # Initial installation 
        systemctl preset  >/dev/null 2>&1 || : 
fi 
 php-fpm.service

$ » rpm --eval "%{systemd_post} 1 php-fpm.service"

if [ $1 -eq 1 ] ; then 
        # Initial installation 
        systemctl preset  >/dev/null 2>&1 || : 
fi 
 1 php-fpm.service

问题

请问各位打包达人,

  1. systemd_post$1 的用法是不是和 %pre 哪些宏一样?
  2. 类似有 if [ $1 -eq 1 ] 有参数的宏怎么测试?

参考链接

更新

自己发现问题了,受 How to know the value of built-in macro in RPM? 这个问题的答案影响,rpm --eval 命令宏的格式写错了。正确的命令如下:

$ » rpm --eval "%systemd_post php-fpm.service"

if [ $1 -eq 1 ] ; then 
        # Initial installation 
        systemctl preset php-fpm.service >/dev/null 2>&1 || : 
fi

参考链接

  1. 使用宏%{…} 格式允许变量插值的方式使用宏,%<name> 格式允许处理 argc/argv 参数。
  2. Scripts: RPM’s WorkhorseInstall/Erase-time Scripts 介绍了小脚本 $1 取值方式。

还有问题

  1. 命令行通过 rpm --eval 单独测试宏,是不是不考虑小脚本的 $1
  2. SPEC 文件里这么用(代码如下),%systemd_post 宏和 %post 宏的 $1 取值规则是不是一样?
%post fpm
%systemd_post php-fpm.service

这几天正好在搞 golang 的 RPM specfile 解析。

  1. 不考虑,你理解错误的地方:rpm —eval 是展开宏(expand),不是运行宏。$1 是 rpm 真正运行 scriptlet 时候返回的,运行条件也很明确,就是 pre post preun postun。你想测试真正的 $1 得用 rpmbuild -ba —test。
  2. 所有非内置宏都相当于 plain text 的 alias,rpm 没有处理它们的东西,都是先 expand 成纯文本,然后在处理内置宏 %post 的地方执行。也就是说你在 %post 里写八个自定义宏,也只处理一遍,$1 都是相同的。你混淆的是 rpm scriptlet 的 $1 和 bash script 的 $1。前者表示一次安装过程中动了多少个同名包,后者表示传入脚本的第一个参数。rpm 的 scriptlet 看着像 bash script 但不是由 bash 调用而是由 rpm 调用。

https://github.com/rpm-software-management/rpm/build

下面的几个 parseXX.c 看一下能收获不少。

1赞