RPM打包

禁止自动分析源码添加不应该加入的依赖 在spec文件中加入Autoreq: 0即可
opnvswitch源码打包需要加入,否则会解析代码中的依赖,在ISO中安装检测失败/bin/python3
%post 部分如果有shell 则依赖关系会自动增加/bin/sh , 如果合并入镜像是不能有/bin/sh /bin/python等

一、打包工具安装

执行命令安装所需的rpm包:
yum install rpmdevtools rpmlint make gcc -y
rpmdevtools包里包括了rpmbuild ,安装好工具后,使用命令rpmdev-setuptree 生成~/rpmbuild目录及其子目录
tree rpmbuild

rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS

或者手动生成目录,命令如下:
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
Fedora的文档建议不使用root用户进行RPM打包

二、使用spec文件创建rpm包

切换路径至SPECS文件夹,使用命令创建spec文件(rpm打包的脚本规则文件),执行命令
rpmdev-newspec myrpm
在当前目录生成了myrpm.spec文件,内容如下(增加了说明和其他部分,源文件比较简单)

Name: myrpm
Version:
Release: 1%{?dist}
Summary:
License: # GPLBSDMITor
URL:
Source0: SOURCES/%{name}-%{version}.tar.gz
BuildRequires: # rpm
Requires: # rpm -ivh
%description
#
%prep
# %prep %setup -q SOURCES${Source0} BUILD %{name}-%{version}
%setup -q
# %patch0 -p1
%build
# %build %build
# cdBUILD/%{name}-%{version}()
%configure # %configureconfigureautoconfconfigure ,
make %{?_smp_mflags} # %{_smp_mflags} cpuCPUmake , ~/.rpmmacros
%install
# %install
# BUILD/%{name}-%{version}()
# BUILDROOTBUILDROOT
rm -rf $RPM_BUILD_ROOT #BUILDROOTcentos6 $RPM_BUILD_ROOT %{buildroot} BUILDROOT/%{name}-%{version}-%{release}.%{_arch}
%make_install # %make_installmake install
%clean
#RPMBUILD
rm -rf %{buildroot}
%files
# BUILDROOT/package/ , /usr/bin/test
%config(noreplace) %{_sysconfdir}/foo.conf # *.rpmsave *.rpmnew
%config %{_sysconfdir}/foo.conf # /etc
%attr(755, root, root) %{_sysconfdir}/foo.conf
%attr(mode, user, group) %{_sysconfdir}/foo.conf # ”-”
/usr/bin/test
%doc
%changelog
## rpm -q package --changelog

开始部分里开头是大写字母的字段,可以被当做变量引用 %{name} %{version} %{release} ...
rpmlint xx.spec可以检测spec语法正确性
spec 中不需要的部分直接删除即可
%build和%install部分都是先cd到BUILD/包名的目录下, 在执行其他命令

三、 SPEC规则注解

rpmbuild
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS

rpmdev-setuptree 执行完之后缺少一个BUILDROOT目录, 实际执行 还要用到该目录, 但不需手动创建,在rpmbuild的过程中会 自动创建。
rpmbuild的规则里有一些内置宏变量,以%开头的, 查看方法rpmbuild --showrc 或者rpm --showrc 几种方式都可以查看;
要查看具体某个宏的值可以使用rpm --eval/-E , 比如 (规范宏写法应该是%{_name})

$ rpm -E %{_topdir}
/home/wanglin/rpmbuild
路径 名称 用途
~/rpmbuild/BUILD %_builddir 构建目录 源代码包从SOURCES目录解压缩后放到该目录,并在该目录进行编译即configure 和 make命令
~/rpmbuild/BUILDROOT %_buildrootdir 最终安装目录 保存%install阶段安装的文件,即make install执行后产生的文件
~/rpmbuild/RPMS %_rpmdir 标准rpm包目录 生成的二进制rpm包会存放在该目录
~/rpmbuild/SOURCES %_sourcedir 源代码目录 源码tar.gz包放到该目录
~/rpmbuild/SPECS %_specdir Spec文件目录 Spec文件存放路径
~/rpmbuild/SRPMS %_srcrpmdir 源码RPM包目录 生成的srpm包存放在该目录

四、spec中的脚本

脚本片段 类似kickstart文件,使用shell编写

  • %pre: 在rpm包安装之前执行
  • %post: 在安装rpm包之后执行
  • %preun: 在卸载rpm包之前执行
  • %postun: 在卸载rpm包之后执行
  • %pretrans: 在事务开始时执行
  • %posttrans: 在事务结束时执行

通常所有安装脚本和触发器脚本都是使用 /bin/sh 来执行的,如果想使用其他脚本,如 perl,可使用 -p /usr/bin/perl 来告诉 rpm 使用perl解释器
如果仅执行一个命令,则 “-p” 选项会直接执行,而不启用 shell。然而,若有许多命令时,不要使用此选项,按正常编写 shell 脚 本即可。
%pre、%post、%preun 和 %postun 提供 1221 的值恒为 0。

- install upgrade uninstall
%pretrans $1 == 0 $1 == 0 (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 == 0 $1 == 0 (N/A)

示例1:

%post
if [ "$1" = 1 ]; then
$1 == 0 $1 == 2 $1 == 2 $1 == 1 $1 == 1 $1 == 0
(N/A) (N/A) (N/A) $1 == 0 $1 == 0 (N/A)
# rpm1 if
if [ ! -f %{_sysconfdir}/shells ] ; then
echo "%{_bindir}/foo" > %{_sysconfdir}/shells
echo "/bin/foo" >> %{_sysconfdir}/shells
else
grep -q "^%{_bindir}/foo$" %{_sysconfdir}/shells || echo "%{_bindir}/foo" >> %{_sysconfdir}/shells
grep -q "^/bin/foo$" %{_sysconfdir}/shells || echo "/bin/foo" >> %{_sysconfdir}/shells
fi
%postun #0
if [ "$1" = 0 ] && [ -f %{_sysconfdir}/shells ] ; then
sed -i '\!^%{_bindir}/foo$!d' %{_sysconfdir}/shells
sed -i '\!^/bin/foo$!d' %{_sysconfdir}/shells
fi

示例2:
例如,如果软件包安装了一份 info 手册,那么可以用 info 包提供的 install-info 来更新 info 手册索引。 首先,我们不保证系统已安装 info 软件包,除非明确声明需要它;其次,我们不想在 install-info 执行失败时,使软件包安装失败:

Requires(post): info
Requires(preun): info
... %post
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi

上边的示例中还有一个安装 info 手册时的小问题需要解释一下。install-info 命令会更新 info 目录,所以我们应该在 %install 阶段删 除 %{buildroot} 中无用的空目录:

rm -f %{buildroot}%{_infodir}/dir

一般最后一条命令的exit状态就是脚本的exit状态,除一些特殊情况,一般脚本都是以exit 0状态退出所以大部分脚本片段都会使用 "||:" 退出

五、执行打包命令生成rpm

SPEC 编写完毕,执行以下命令来构建 SRPM 和 RPM 包:
rpmbuild -ba myrpm.spec
如果成功,RPM 会保存至 ~/rpmbuild/RPMS,SRPM 会保存至 ~/rpmbuild/SRPMS。
如果失败,请查看 BUILD 目录的相应编译日志。为了帮助调试,可以用 --short-circuit 选项来忽略成功的阶段。例如,若想要(略过更早的阶段)重新从 %install 阶段开始,请执行:
rpmbuild -bi --short-circuit myrpm.spec
如果只想创建 RPM,请执行:
rpmbuild -bb myrpm.spec

如果只想创建 SRPM(不需要执行 %prep 或 %build 或其他阶段),请执行:
rpmbuild -bs myrpm.spec

rpmlint检查
为避免常见错误,请先使用 rpmlint 查找 SPEC 文件的错误:
rpmlint program.spec

如果返回错误/警告,使用 “-i” 选项查看更详细的信息。
也可以使用 rpmlint 测试已构建的 RPM 包,检查 SPEC/RPM/SRPM 是否存在错误。你需要在发布软件包之前,解决这些警告。此 页面 提供一些常见问题的解释。如果你位于 SPEC 目录中,请执行:
rpmlint myrpm.spec ../RPMS/*/NAME*.rpm ../SRPMS/NAME*.rpm
进入 ~/rpmbuild/RPMS 下的特定架构目录中,您会发现有许多二进制 RPM 包。使用以下命令快速查看 RPM 包含的文件和权限:
rpmls *.rpm

六、部分宏变量

%{_sysconfdir} /etc
%{_prefix} /usr
%{_exec_prefix} %{_prefix}
%{_bindir} %{_exec_prefix}/bin
%{_libdir} %{_exec_prefix}/%{_lib}
%{_libexecdir} %{_exec_prefix}/libexec
%{_sbindir} %{_exec_prefix}/sbin
%{_sharedstatedir} /var/lib
%{_datarootdir} %{_prefix}/share
%{_datadir} %{_datarootdir}
%{_includedir} %{_prefix}/include
%{_infodir} /usr/share/info
%{_mandir} /usr/share/man
%{_localstatedir} /var
%{_initddir} %{_sysconfdir}/rc.d/init.d
%{_var} /var
%{_tmppath} %{_var} /tmp
%{_usr} /usr
%{_usrsrc} %{_usr}/src
%{_lib} lib (lib64 on 64bit multilib systems)
%{_docdir} %{_datadir}/doc
%{buildroot} %{_buildrootdir}/%{name}-%{version}-%{release}.%{_arch}
$RPM_BUILD_ROOT %{buildroot}
%{_unitdir} /usr/lib/systemd/system
%define Macro Value Macro=Value

七、一个只打包文件的spec实例

Name: cvk_tools
Version: 1.1
Release: 1%{?dist}
Summary: cvk_tools by wanglin
License: GPLv3
URL:
Source: %{name}-%{version}.tar.gz
BuildArch: %{_arch}
Autoreq: 0
%prep
%setup -q
%description
init cvk
%define pack_path root/%{name}-%{version}
%define ca_path etc/pki/CA
%install
install -d %{buildroot}/%{pack_path}
install -d %{buildroot}/%{ca_path}
for i in `ls ./`;do
if [ -f $i ];then
install ./$i %{buildroot}/%{pack_path}
elif [ -d $i ];then
if [[ $i =~ "ca" ]];then
install -m 444 -o root -g root ./ca/cacert.pem %{buildroot}/%{ca_path}
else
install -d %{buildroot}/%{pack_path}/$i
for f in `ls $i`;do
install $i/$f %{buildroot}/%{pack_path}/$i
done
fi
fi
done
# Upgarde${conf}.old
%pre
conf=/%{pack_path}/tools.conf
if (( $1 == 2 ));then
[ -f $conf ] && mv $conf ${conf}.old || :
fi
# Upgrade
%post
conf=/%{pack_path}/tools.conf
if (( $1 == 2 ));then
[ -f ${conf}.old ] && mv ${conf}.old ${conf} || :
fi
%postun
if (( $1 == 0 ));then
[ -d /%{ca_path} ] && rm -rf /%{ca_path} || :
[ -d $(dirname /%{ca_path}) ] && rm -rf $(dirname /%{ca_path}) || :
[ -d /%{pack_path} ] && rm -rf /%{pack_path} || :
fi
%files
%attr(-, root, root)
# first method
/%{pack_path}
/%{ca_path}
#----second method
#%dir /%{pack_path}
#/%{pack_path}/*
#%dir /%{ca_path}
#/%{ca_path}/*
%doc
%changelog
* Fri Jul 1 2022 cvk_tools Release - 1.1-1
- Second Version release
* Thu Nov 25 2021 cvk_tools Release - 1.0-1
- Initial first version

附录: 打包遇到的问题

  • fle段缺少文件
Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/lldpad-1.1-1.el7.x86_64
error: Installed (but unpackaged) file(s) found:
/usr/etc/bash_completion.d/lldpad
/usr/etc/bash_completion.d/lldptool
/usr/include/lldpad/clif.h
/usr/include/lldpad/clif_msgs.h
/usr/include/lldpad/clif_sock.h
...
RPM build errors:
Installed (but unpackaged) file(s) found:
/usr/etc/bash_completion.d/lldpad
/usr/etc/bash_completion.d/lldptool
/usr/include/lldpad/clif.h
/usr/include/lldpad/clif_msgs.h
/usr/include/lldpad/clif_sock.h
...

这个意思是说发现了制作RPM包的spec脚本中没有包含但又被安装的文件
如果显示很多文件,将这些文件你可以分门别类,用%doc、%config这些宏来指定,其实如果它报错的时候,只显示一两个文件,可 以直接把那个文件写在%file下面
vi /usr/lib/rpm/macros,找到%__check_files %{_rpmconfigdir}/check-files %{buildroot} 这一行,把这一行注释掉,然后重新编 译。

  • file段重复包含
warning: File listed twice: /etc/pki/CA/cacert.pem
warning: File listed twice: /root/cvk_tools-1.1/README.md
warning: File listed twice: /root/cvk_tools-1.1/config_ca.sh
...

重复包含了文件
去掉file段重复目录或者文件的包含关系

参考链接

Fedora
链接2
链接3

posted @   ishmaelwanglin  阅读(864)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示