Rpmbuild |创建rpm包|从源代码构建rpm
在本文中,将介绍使用源rpm重建rpm的步骤。
可以从相应发行版的官方页面上收集源rpm。
在本文中,我将使用httpd源rpm来重建httpd rpm
安装rpmdevtools
我们需要rpmdev-setuptree来设置rpmbuild目录结构来创建rpm包。
该工具由RHEL/CentOS 7 Linux中的rpmdevtools提供
说明:
如果没有活动的存储库,则下载具有所有依赖项列表的rpm,然后可以使用它们创建脱机存储库。
[root@centos-7 ~]# yum install rpmdevtools
创建rpm软件包还需要其他一些必备的rpm。
他们之中有一些是:
[root@centos-7 ~]# yum install gcc gcc-c++ make automake autoconf rpm-build
现在稍后,当我们从源代码构建rpm时,可能会出现更多的依赖项错误,因此我们将根据需求安装任何其他rpm。
创建rpmbuild结构
要使用rpmbuild创建rpm包,我们需要一个适当的目录结构。
rpmbuild将在相应目录中查找文件以从源代码构建rpm
从我们要设置rpmbuild结构的位置运行rpmdev-setuptree实用程序,以创建rpm包。
我将在root的主文件夹下执行
[root@centos-7 ~]# rpmdev-setuptree
如我们所见,目录结构是由/root/rpmbuild下的rpmdev-setuptree创建的。
[root@centos-7 ~]# tree ~/rpmbuild/ /root/rpmbuild/ ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS 5 directories, 0 files
我们将介绍"两种情况"以创建rpm包
从源代码构建rpm
从头开始创建rpm包
从源代码构建RPM
在这个例子中,我们已经有了一个rpm,但是我们想修改rpm的内容,并通过我们的修改从源代码构建rpm。
第1步:下载源rpm
首先,我们必须访问源rpm,我们必须对其进行修改以创建rpm包。
我们可以根据环境和供应商获得源rpm。
我将以httpd
rpm为基本示例,并且src rpm在CentOS项目存储库中可用。
提取来源rpm内容
接下来,我们将从rpm中提取源代码。
我已经创建了一个临时目录/tmp/customrpm
来提取httpd rpm的内容。
[root@centos-7 ~]# mkdir /tmp/customrpm
将" httpd"源rpm复制到此临时目录
[root@centos-7 ~]# cp httpd-2.4.6-89.el7_6.src.rpm /tmp/customrpm/
使用rpm2cpio提取源代码
[root@centos-7 ~]# cd /tmp/customrpm [root@centos-7 customrpm]# rpm2cpio httpd-2.4.6-89.el7_6.src.rpm | cpio -idm 11022 blocks
接下来提取httpd-2.4.6.tar.bz2存档,以便我们可以修改httpd的内容。
它包含httpd包的所有源代码。
[root@centos-7 customrpm]# tar -xjvf httpd-2.4.6.tar.bz2
修改源代码
如果我们观察到,我们的临时目录中有"多个补丁"和"其他配置文件"。
[root@centos-7 customrpm]# ls 00-base.conf httpd-2.4.6-CVE-2016-3169.patch httpd-2.4.6-r1651658.patch 00-dav.conf httpd-2.4.6-CVE-2016-7668.patch httpd-2.4.6-r1662640.patch 00-lua.conf httpd-2.4.6-CVE-2016-7679.patch httpd-2.4.6-r1663647.patch 00-mpm.conf httpd-2.4.6-CVE-2016-9788.patch httpd-2.4.6-r1664565.patch 00-proxy.conf httpd-2.4.6-CVE-2016-9798.patch httpd-2.4.6-r1668532.patch 00-proxyhtml.conf httpd-2.4.6-default-port-worker.patch httpd-2.4.6-r1674222.patch 00-ssl.conf httpd-2.4.6-dhparams-free.patch httpd-2.4.6-r1681107.patch 00-systemd.conf httpd-2.4.6-full-release.patch httpd-2.4.6-r1681114.patch 01-cgi.conf httpd-2.4.6-http-protocol-options-define.patch httpd-2.4.6-r1681289.patch 01-ldap.conf httpd-2.4.6-ldaprefer.patch httpd-2.4.6-r1683112.patch 01-session.conf httpd-2.4.6-mod_authz_dbd-missing-query.patch httpd-2.4.6-r1684462.patch action-configtest.sh httpd-2.4.6-mpm-segfault.patch httpd-2.4.6-r1688399.patch {Output trimmed}
现在,根据源rpm," rpm的内容可能会有所不同"。
我将继续并将"一些伪数据"放入" httpd"下的一个文件中,然后我们将使用新的更改从源代码构建rpm。
[root@centos-7 customrpm]# cd httpd-2.4.6 [root@centos-7 httpd-2.4.6]# echo "TEST hynman" >> README
建立RPM内容封存
接下来,我将在/tmp
下使用更新的源代码创建一个新的存档。
[root@centos-7 customrpm]# tar -cjvf ../httpd-2.4.6.tar.bz2 httpd-2.4.6/*
在后面的步骤中,我们将把这个归档文件转移到rpmbuild结构的SOURCE目录中,以从源代码构建rpm。
因此,既然我已经创建了一个新的存档,那么我将从临时目录中删除多余的内容。
[root@centos-7 customrpm]# rm -rf httpd-2.4.6 httpd-2.4.6.tar.bz2 httpd-2.4.6-89.el7_6.src.rpm
这我"安排以后创建rpm包所需的文件"。
更新来源
接下来,我们将新存档复制到SOURCES
目录中
[root@centos-7 customrpm]# cp /tmp/httpd-2.4.6.tar.bz2 /root/rpmbuild/SOURCES/
更新rpm规范文件
spec文件始终是任何rpm的一部分。
因此,当我们提取src rpm时,我们还获得了httpd.spec文件,将httpd.spec文件复制到SPEC目录中。
我们将需要它来创建具有新版本的rpm软件包。
[root@centos-7 customrpm]# cp httpd.spec /root/rpmbuild/SPECS/
修改rpm版本并提供在源代码中执行的更改列表以跟踪更改始终是一个好主意。
[root@centos-7 customrpm]# cd /root/rpmbuild/SPECS/ [root@centos-7 SPECS]# vim httpd.spec <Updated the Release Number> Summary: Apache HTTP Server Name: httpd Version: 2.4.6 Release: 90%{?dist} <Added change log> %changelog * Fri Jun 21 2019 hynman Prasad <[email protected]> - 2.4.6-90 - Test Changes
使用源代码构建rpm
如果我们检查spec
文件,则会找到BuildRequires
部分。
`这包含httpd rpm安装所必需的准备工作。
BuildRequires: autoconf, perl, pkgconfig, findutils, xmlto BuildRequires: zlib-devel, libselinux-devel, lua-devel BuildRequires: apr-devel >= 1.4.0, apr-util-devel >= 1.2.0, pcre-devel >= 5.0 BuildRequires: systemd-devel Requires: /etc/mime.types, system-logos >= 7.92.1-1 Requires(pre): /usr/sbin/useradd Requires(pre): /usr/sbin/groupadd Requires(preun): systemd-units Requires(postun): systemd-units Requires(post): systemd-units
因此,在我们开始从源代码构建rpm之前,"我们必须确保构建机器已安装了这些rpm"以及主机上可用的那些文件。
要获得依赖关系的完整列表,我们可以启动rpmbuild
,它将抛出依赖关系列表。
这里的-ba表示构建二进制和源程序包(在执行%prep,%build和%install阶段之后)。
[root@centos-7 SPECS]# rpmbuild -ba httpd.spec error: Failed build dependencies: autoconf is needed by httpd-2.4.6-90.el7.x86_64 xmlto is needed by httpd-2.4.6-90.el7.x86_64 zlib-devel is needed by httpd-2.4.6-90.el7.x86_64 libselinux-devel is needed by httpd-2.4.6-90.el7.x86_64 lua-devel is needed by httpd-2.4.6-90.el7.x86_64 apr-devel >= 1.4.0 is needed by httpd-2.4.6-90.el7.x86_64 apr-util-devel >= 1.2.0 is needed by httpd-2.4.6-90.el7.x86_64 pcre-devel >= 5.0 is needed by httpd-2.4.6-90.el7.x86_64 systemd-devel is needed by httpd-2.4.6-90.el7.x86_64 openssl-devel >= 1:1.0.1e-37 is needed by httpd-2.4.6-90.el7.x86_64 libxml2-devel is needed by httpd-2.4.6-90.el7.x86_64
rpmbuild将抛出一个错误,将依赖关系错误。
因此,`在创建rpm包之前,我们必须手动安装这些依赖rpms:
[root@centos-7 SPECS]# yum -y install autoconf xmlto zlib-devel libselinux-devel lua-devel apr-devel apr-util-devel pcre-devel systemd-devel openssl-devel libxml2-devel
一旦安装了所有依赖的rpm,我们就可以再次触发rpmbuild从源代码构建rpm。
[root@centos-7 SPECS]# rpmbuild -ba httpd.spec Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.u33j1b + umask 022 + cd /root/rpmbuild/BUILD + cd /root/rpmbuild/BUILD + rm -rf httpd-2.4.6 + /usr/bin/bzip2 -dc /root/rpmbuild/SOURCES/httpd-2.4.6.tar.bz2 + /usr/bin/tar -xf + STATUS=0 <Output Trimmed> Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/rpmbuild/BUILDROOT/httpd-2.4.6-90.el7.x86_64 Wrote: /root/rpmbuild/SRPMS/httpd-2.4.6-90.el7.src.rpm Wrote: /root/rpmbuild/RPMS/x86_64/httpd-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/httpd-devel-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/noarch/httpd-manual-2.4.6-90.el7.noarch.rpm Wrote: /root/rpmbuild/RPMS/x86_64/httpd-tools-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/mod_ssl-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/mod_proxy_html-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/mod_ldap-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/mod_session-2.4.6-90.el7.x86_64.rpm Wrote: /root/rpmbuild/RPMS/x86_64/httpd-debuginfo-2.4.6-90.el7.x86_64.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.5JJBBV + umask 022 + cd /root/rpmbuild/BUILD + cd httpd-2.4.6 + rm -rf /root/rpmbuild/BUILDROOT/httpd-2.4.6-90.el7.x86_64 + exit 0
因此,我们的create rpm软件包成功了。
在执行结束时,我们可以在rpmbuild结构的" RPMS"目录下看到新rpm文件的路径。
安装并验证RPM
我将安装新的rpm来验证对httpd rpm的README
文件所做的更改。
[root@centos-7 SPECS]# rpm -Uvh /root/rpmbuild/RPMS/x86_64/httpd-2.4.6-90.el7.x86_64.rpm /root/rpmbuild/RPMS/x86_64/httpd-tools-2.4.6-90.el7.x86_64.rpm Preparing... ################################# [100%] Updating/installing... 1:httpd-tools-2.4.6-90.el7 ################################# [ 50%] 2:httpd-2.4.6-90.el7 ################################# [100%]
验证rpm是否已成功安装
[root@centos-7 SPECS]# rpm -qa | grep httpd httpd-tools-2.4.6-90.el7.x86_64 httpd-2.4.6-90.el7.x86_64
获取我们对源rpm进行更改的" README"文件的路径:
[root@centos-7 SPECS]# rpm -ql httpd-2.4.6-90.el7.x86_64 | grep README /etc/httpd/conf.d/README /usr/share/doc/httpd-2.4.6/README /usr/share/httpd/error/README /usr/share/httpd/icons/README /usr/share/httpd/icons/README.html
因此,看起来我们的更改按预期进行了:
[root@centos-7 SPECS]# grep TEST /usr/share/doc/httpd-2.4.6/README TEST hynman
从头开始创建rpm包
我们可能想为开发和测试任务创建一个全新的rpm包。
我们将需要类似的rpmbuild目录结构
`为单独的rpm创建单独的rpmbuild结构很重要。
我将以我的名字hynman创建一个新的rpm
所以我将创建一个新文件夹来创建rpmbuild结构
[root@centos-7 ~]# mkdir /root/hynman [root@centos-7 ~]# cd /root/hynman
执行rpmdev-setuptree来创建rpmbuild结构来创建rpm包
[root@centos-7 ~]# rpmdev-setuptree
这将创建与我们先前创建的类似的目录结构,以从源代码构建rpm
[root@centos-7 ~]# tree /root/hynman/rpmbuild/ /root/hynman/rpmbuild/ ├── BUILD ├── RPMS ├── SOURCES ├── SPECS └── SRPMS 5 directories, 0 files
建立rpm规格档案
由于我们计划从头开始创建rpm包,因此我们需要一个spec文件。
我们可以参考fedora:创建rpm软件包以获取示例spec
文件
或者,我们可以将以下spec
文件模板用于rpm
[root@centos-7 ~]# vim /tmp/hynman/rpmbuild/SPECS/hynman.spec Name: hynman Summary: Test Rpm Version: 1.0.0 Release: 1 Group: theitroad License: Not Applicable URL: https://www.theitroad.com SOURCE0: %{name}-%{version}-%{release}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description we are learning how to create rpm package in Linux %prep %setup -q %build #Empty %install rm -rf %{buildroot} mkdir -p %{buildroot} cp -a * %{buildroot} %clean rm -rf %{buildroot} %files %defattr(-,root,root,-) /test1/file1 /test2/file2 %changelog * Wed Jan 06 2017 hynman Prasad - 1.0.0-1 - Created first draft
规范文件中最重要的部分之一是"脚本"
使用
scriptlets
我们可以定义%pre
,%post
和rpmspec
文件的许多其他部分。因此,我们可以使用相应的部分来调用自定义脚本或者函数
例如,我们需要在安装rpm之前先设置环境,以便可以选择相应的"脚本"来添加更改。
我写了另一篇文章,以详细的示例覆盖所有scriptlet。
建立RPM内容
" SOURCES"下的所有内容都将视为rpm内容
这些将在安装rpm之后放置在服务器上
这些内容的位置将使用rpm
spec
文件定义我们不将单个文件保存在
SOURCES
中,而是必须将内容捆绑在一起,然后将其放置在SOURCES
目录中
所以我将在/tmp
下创建一个临时目录。
下面是我们的源目录,其基本发行版号为1.0.0。
[root@centos-7 ~]# cd /tmp [root@centos-7 ~]# mkdir hynman-1.0.0
接下来,我们创建一些虚拟文件和目录,这些虚拟文件和目录在规范文件中的"%files"下已提到。
[root@centos-7 ~]# mkdir -p hynman-1.0.0/test1/file1 [root@centos-7 ~]# mkdir -p hynman-1.0.0/test2/file2
更新来源
接下来,我们将使用上面创建的临时文件和目录创建一个存档。档案必须使用正确的发行版和版本号
例如我的spec
文件包含在下面
Version: 1.0.0 Release: 1
所以我的档案名称是hynman-1.0.0-1.tar.gz
[root@centos-7 ~]# cd /tmp [root@centos-7 ~]# tar -czvf /root/hynman/rpmbuild/SOURCES/hynman-1.0.0-1.tar.gz hynman-1.0.0/*
建立RPM套件
至此,我们的" rpmbuild"环境设置已完成。
接下来,我们将使用带有规范文件的rpmbuild创建rpm包
[root@centos-7 ~]# rpmbuild -ba /root/hynman/rpmbuild/SPECS/hynman.spec Executing(%prep): /bin/sh -e /root/hynman/rpmbuild/tmp/rpm-tmp.p63FqV + umask 022 + cd /root/hynman/rpmbuild/BUILD + cd /root/hynman/rpmbuild/BUILD + rm -rf hynman-1.0.0 + /usr/bin/gzip -dc /root/hynman/rpmbuild/SOURCES/hynman-1.0.0-1.tar.gz + /usr/bin/tar -xf + STATUS=0 + '[' 0 -ne 0 ']' + cd hynman-1.0.0 + /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w . + exit 0 Executing(%build): /bin/sh -e /root/hynman/rpmbuild/tmp/rpm-tmp.Oekwnu + umask 022 + cd /root/hynman/rpmbuild/BUILD + cd hynman-1.0.0 + exit 0 Executing(%install): /bin/sh -e /root/hynman/rpmbuild/tmp/rpm-tmp.My9Zk3 + umask 022 + cd /root/hynman/rpmbuild/BUILD + '[' /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 '!='/']' + rm -rf /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 ++ dirname /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + mkdir -p /root/hynman/rpmbuild/BUILDROOT + mkdir /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + cd hynman-1.0.0 + rm -rf /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + mkdir -p /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + cp -a test1 test2 /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /root/hynman/rpmbuild/BUILD/hynman-1.0.0 /usr/lib/rpm/sepdebugcrcfix: Updated 0 CRC32s, 0 CRC32s did match. + /usr/lib/rpm/check-buildroot + /usr/lib/rpm/redhat/brp-compress + /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip + /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1 + /usr/lib/rpm/redhat/brp-python-hardlink + /usr/lib/rpm/redhat/brp-java-repack-jars Processing files: hynman-1.0.0-1.x86_64 Provides: hynman = 1.0.0-1 hynman(x86-64) = 1.0.0-1 Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 Processing files: hynman-debuginfo-1.0.0-1.x86_64 Provides: hynman-debuginfo = 1.0.0-1 hynman-debuginfo(x86-64) = 1.0.0-1 Requires(rpmlib): rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rpmlib(CompressedFileNames) <= 3.0.4-1 Checking for unpackaged file(s): /usr/lib/rpm/check-files /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 Wrote: /root/hynman/rpmbuild/SRPMS/hynman-1.0.0-1.src.rpm Wrote: /root/hynman/rpmbuild/RPMS/x86_64/hynman-1.0.0-1.x86_64.rpm Wrote: /root/hynman/rpmbuild/RPMS/x86_64/hynman-debuginfo-1.0.0-1.x86_64.rpm Executing(%clean): /bin/sh -e /root/hynman/rpmbuild/tmp/rpm-tmp.OipO2Y + umask 022 + cd /root/hynman/rpmbuild/BUILD + cd hynman-1.0.0 + rm -rf /root/hynman/rpmbuild/BUILDROOT/hynman-1.0.0-1.x86_64 + exit 0
我们的rpmbuild执行成功。
新的rpm放在/root/hynman/rpmbuild/RPMS/x86_64/hynman-1.0.0-1.x86_64.rpm
下
安装并验证rpm内容
让我们检查一下rpm的内容
[root@centos-7 ~]# rpm -qlp /tmp/rpmbuild/RPMS/x86_64/hynman-1.0.0-1.x86_64.rpm /test1/file1 /test2/file2
安装并验证rpm
[root@centos-7 ~]# rpm -ivh /tmp/rpmbuild/RPMS/x86_64/hynman-1.0.0-1.x86_64.rpm Preparing... ################################# [100%] Updating/installing... 1:hynman-1.0.0-1 ################################# [100%]
rpm安装成功,并且rpm的内容保持不变
[root@centos-7 ~]# rpm -ql hynman /test1/file1 /test2/file2