rpm相关命令和知识

-- TOC --

RPM, Redhat Package Manager, is quite a mature project in the OSS landscape, with first VCS commit of the current tree dating back to 1995.

我更喜欢有历史的开源项目。

https://rpm.org/index.html

rpm和dnf都是开源的:https://github.com/rpm-software-management

rpm

rpm,Redhat Package Manager,是一种很流行的Linux环境下的软件包管理工具。

$ sudo dnf install rpm rpmdevtools rpm-build

查询已安装的rpm软件包:rpm -qa | grep <name>

安装rpm软件包:rpm -ivh <rpm-package>

删除rpm软件包:rpm -evh <rpm-package>

-vh是为了更好的视觉效果,verbose + rpm特有的hash

升级rpm软件包:rpm -U <rpm-package>

--nodeps,无视rpm包之间的依赖关系,直接干!

--force,无视一切错误,直接干!

查询rpm包的依赖:rpm -qR <installed-package> 或者 rpm -qpR <uninstalled-package>

批量删除rpm包:rpm -qa | grep <keyword> | xargs rpm -evh

查询rpm包的安装位置:rpm -ql <rpm-package>,这个命令实际上是在查询此rpm安装的文件及其位置,想知道某个rpm包在/usr/bin里面安装了那些文件,使用rpm -ql <rpm-package> | grep bin

下面是一些与制作rpm包有关的命令

在redhat系列linux中安装rpm工具包:sudo dnf install rpmdevtools,查询这个软件包所包含的工具:rpm -ql rpmdevtools | grep bin

rpmbuild所在的工具包:sudo dnf install rpm-build

rpmdev-setuptree:此命令会在$HOME目录下生成一组目录,作为rpm packaging workspace:

$ rpmdev-setuptree
$ tree rpmbuild -L 1
rpmbuild
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS

5 directories, 0 files

rpmbuild -ba,同时构建srpm和rpm。

spec文件

制作rpm包,主要就是编写spec文件。

vim创建一个.spec文件,vim默认会给你一个编写模板,也可以用rpmdev-newspec命令创建spec文件,你会得到另一种模板。

hello-rpm.spec

$ cat hello-rpm.spec
Name: hello-rpm
Version: 1
Release: 3
Summary: Most simple RPM package
License: MIT
BuildArch: noarch
Requires: bash

%description
This is my first RPM package, which does nothing.

%prep
# we have no source, so nothing here

%build
cat > hello-rpm.sh <<EOF
#!/usr/bin/bash
echo Hello rpm!
EOF
pwd
cat hello-rpm.sh
echo 'here i am in build phase!'

%install
mkdir -p %{buildroot}/%{_bindir}
install -m 755 hello-rpm.sh %{buildroot}/%{_bindir}/%{name}

%files
%{_bindir}/%{name}

%changelog
* Sat Jan 29 2022 somename <maxamillion@fedoraproject.org>
- first release

这是一个非常简单的spec文件。A SPEC file can be thought of as the "recipe" that the rpmbuild utility uses to actually build an RPM. It tells the build system what to do by defining instructions in a series of sections. The sections are defined in the Preamble and the Body. The Preamble contains a series of metadata items that are used in the Body. The Body contains the main part of the instructions.

%定义的section,被称为body,它们主要提供制作rpm包的指令。其它非%开始的,被称为Preamble!

Preamble 含义
Name base name of this package,which should match the spec file name. 最后生成的rpm包的名称,是spec文件的名称,因此这个Name最好能够与spec文件名称保持一致。
Version 软件版本
Release 软件Release信息
Summary 一句话简介
License License说明
BuildArch If the package is not architecture dependent, for example, if written entirely in an interpreted programming language, set this to BuildArch: noarch. If not set, the package automatically inherits the Architecture of the machine on which it is built, for example x86_64. 当与计算机体系架构无关时,设置为noarch,否则就是打包时机器本身的arch信息,此处的信息会成为rpm包的一个后缀
Requires A comma- or whitespace-separated list of packages required by the software to run once installed. There can be multiple entries of Requires, each on its own line in the SPEC file. 运行时的依赖

Version和Release是分开的概念,同一个Version的代码,可以有多个Release,比如不同的arch就是不同的Release,比如对同一个Version多次制作rpm包,每次Release都会增加1(手动修改,这是个convention)。

NVRN-V-R,就是Name-Version-Release的缩写,表示这种命令方式。

%description是一段详细的rpm包的介绍info,用rpm -qi <rpm-package>查看;%changelog是此rpm包spec文件的修改记录,可通过rpm -q --changelog <rpm-package>来查看。

changelog部分有格式要求:

  1. 每个entry要用*开头;
  2. 内容部分要用-开头;

跟很多linux平台下工具一样,spec文件内也有很多macro可以用来做文本替换,hello-rpm.spec中使用到的macro内容如下:

$ rpm -E %{buildroot}
/home/xinlin/rpmbuild/BUILDROOT/%{NAME}-%{VERSION}-%{RELEASE}.x86_64
$ rpm -E %{_bindir}
/usr/bin
$ rpm -E %{?dist}  # not used
.el8

Preamble中的Name,Version,Release也都成了可以在body中使用的macro,貌似大小写都可以。

我们先来做个SRPM包

source RPM,安装此类rpm包,相当于得到源码和一个spec文件,你可以修改spec文件,然后再打包成binary rpm包。

$ cd ~
$ rm -rf rpmbuild
$ rpmdev-setuptree
$ tree rpmbuild/
rpmbuild/
├── BUILD
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS

5 directories, 0 files
$ rpmbuild -bs test/hello-rpm.spec
Wrote: /home/xinlin/rpmbuild/SRPMS/hello-rpm-1-3.src.rpm
$ tree rpmbuild
rpmbuild
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
    └── hello-rpm-1-3.src.rpm

6 directories, 1 file

安装这个SRPM包看看效果:

$ rpm -ivh rpmbuild/SRPMS/hello-rpm-1-3.src.rpm
Updating / installing...
   1:hello-rpm-1-3                    ################################# [100%]
$ tree rpmbuild
rpmbuild
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
│   └── hello-rpm.spec
└── SRPMS
    └── hello-rpm-1-3.src.rpm

6 directories, 2 files

安装这个rpm包,仅仅是在SPECS目录下install了原来自己编写的spec文件。

制作RPM包

$ rpmbuild -bb test/hello-rpm.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.BBxVfK
+ umask 022
+ cd /home/xinlin/rpmbuild/BUILD
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.nVRE1I
+ umask 022
+ cd /home/xinlin/rpmbuild/BUILD
+ cat
+ pwd
/home/xinlin/rpmbuild/BUILD
+ cat hello-rpm.sh
#!/usr/bin/bash
echo Hello rpm
+ echo 'here i am in build phase!'
here i am in build phase!
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.S8UdyJ
+ umask 022
+ cd /home/xinlin/rpmbuild/BUILD
+ '[' /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64 '!=' / ']'
+ rm -rf /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64
++ dirname /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64
+ mkdir -p /home/xinlin/rpmbuild/BUILDROOT
+ mkdir /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64
+ mkdir -p /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64/usr/bin/
+ install -m 755 hello-rpm.sh /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64/usr/bin/hello-rpm.sh
+ '[' noarch = noarch ']'
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-ldconfig
/sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-strip /usr/bin/strip
+ /usr/lib/rpm/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile '' 1
+ /usr/lib/rpm/brp-python-hardlink
+ PYTHON3=/usr/libexec/platform-python
+ /usr/lib/rpm/redhat/brp-mangle-shebangs
Processing files: hello-rpm-1-3.noarch
Provides: hello-rpm = 1-3
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: /usr/bin/bash
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64
Wrote: /home/xinlin/rpmbuild/RPMS/noarch/hello-rpm-1-3.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.J7NQiK
+ umask 022
+ cd /home/xinlin/rpmbuild/BUILD
+ /usr/bin/rm -rf /home/xinlin/rpmbuild/BUILDROOT/hello-rpm-1-3.x86_64
+ exit 0
$ tree rpmbuild/
rpmbuild/
├── BUILD
│   └── hello-rpm.sh
├── BUILDROOT
├── RPMS
│   └── noarch
│       └── hello-rpm-1-3.noarch.rpm
├── SOURCES
├── SPECS
│   └── hello-rpm.spec
└── SRPMS
    └── hello-rpm-1-3.src.rpm

7 directories, 4 files

可以很明显的看出,制作RPM包的顺序,就是分好几个阶段,执行临时的shell脚本,这个顺序为:%prep --> %build --> %install --> %clean

hello-rpm.spec的%prep没有内容,因此仅仅执行进入BUILD目录的动作就退出了。%build部分有一些命令,按顺序执行,因此在BUILD目录下,最后能看到用here document技术生成的hello-rpm.sh文件。%install执行的命令较多,hello-rpm.spec里面写明的两个命令也夹在其中,这里要注意,install只在buildroot路径下的install,并不是真正的使用rpm包的用户的install,此时还在rpm包的制作过程中。%clean这部分的内容在spec文件中没有出现,它清空了buildroot中对应的目录。

%files部分才是使用rpm包的用户在安装的时候,要copy的文件!

另一种制作RPM包的方式,是直接使用SRPM包:

$ rpmbuild --rebuild rpmbuild/SRPM/hello-rpm-1-3.src.rpm

RPM包的安装查询删除

安装

$ sudo rpm -ivh rpmbuild/RPMS/noarch/hello-rpm-1-3.noarch.rpm
Verifying...                          ################################# [100%]
Preparing...                          ################################# [100%]
Updating / installing...
   1:hello-rpm-1-3                    ################################# [100%]
$ hello-rpm
Hello rpm!

查询

$ rpm -ql hello-rpm  # file installed
/usr/bin/hello-rpm
$ rpm -qi hello-rpm  # query info, include summary and description
Name        : hello-rpm
Version     : 1
Release     : 3
Architecture: noarch
Install Date: Sat 29 Jan 2022 03:06:26 PM CST
Group       : Unspecified
Size        : 32
License     : MIT
Signature   : (none)
Source RPM  : hello-rpm-1-3.src.rpm
Build Date  : Sat 29 Jan 2022 03:01:22 PM CST
Build Host  : localhost
Relocations : (not relocatable)
Summary     : Most simple RPM package
Description :
This is my first RPM package, which does nothing.
$ rpm -q --changelog hello-rpm  # query changelog in spec
* Sat Jan 29 2022 somename <maxamillion@fedoraproject.org>
- first release
$ rpm -qR hello-rpm  # query relied
/usr/bin/bash
bash
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsXz) <= 5.2-1

删除

$ sudo rpm -evh hello-rpm
Preparing...                          ################################# [100%]
Cleaning up / removing...
   1:hello-rpm-1-3                    ################################# [100%]
$ which hello-rpm
/usr/bin/which: no hello-rpm in (/home/xinlin/.local/bin:/home/xinlin/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin)

rpmlint

这个工具可以检查spec文件,SRPM和RPM包,需要单独安装rpmlint。

$ rpmlint test/hello-rpm.spec
0 packages and 1 specfiles checked; 0 errors, 0 warnings.
$ rpmlint rpmbuild/SRPMS/hello-rpm-1-3.src.rpm
hello-rpm.src: W: no-version-in-last-changelog
hello-rpm.src: W: no-url-tag
1 packages and 0 specfiles checked; 0 errors, 2 warnings.
$ rpmlint rpmbuild/RPMS/noarch/hello-rpm-1-3.noarch.rpm
hello-rpm.noarch: W: no-version-in-last-changelog
hello-rpm.noarch: W: no-url-tag
hello-rpm.noarch: W: no-documentation
hello-rpm.noarch: W: no-manual-page-for-binary hello-rpm
1 packages and 0 specfiles checked; 0 errors, 4 warnings.

本文链接:https://cs.pynote.net/sf/linux/sys/202201192/

-- EOF --

-- MORE --