Rpmbuild |创建rpm包|从源代码构建rpm

时间:2020-01-09 10:39:05  来源:igfitidea点击:

在本文中,将介绍使用源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。

我将以httpdrpm为基本示例,并且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之后放置在服务器上

  • 这些内容的位置将使用rpmspec文件定义

  • 我们不将单个文件保存在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