RPM用法指南

Table of Contents

RPM起初是RedHat系统的包管理工具,目前已有多个系统支持RPM包(如SUSE)。

RPM由以下几个部分组成:

$ file /var/lib/rpm/*
/var/lib/rpm/Basenames:            Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Conflictname:         Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/__db.001:             Applesoft BASIC program data, first line number 18
/var/lib/rpm/__db.002:             a.out little-endian 32-bit pure executable
/var/lib/rpm/__db.003:             a.out little-endian 32-bit pure executable not stripped
/var/lib/rpm/Dirnames:             Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Enhancename:          Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Filetriggername:      Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Group:                Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Installtid:           Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Name:                 Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Obsoletename:         Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Packages:             Berkeley DB (Hash, version 9, native byte-order)
/var/lib/rpm/Providename:          Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Recommendname:        Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Requirename:          Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Sha1header:           Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Sigmd5:               Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Suggestname:          Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Supplementname:       Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Transfiletriggername: Berkeley DB (Btree, version 9, native byte-order)
/var/lib/rpm/Triggername:          Berkeley DB (Btree, version 9, native byte-order)

1 查看帮助

rpm命令的参数选项太多,本人也尚未全部掌握,因此这里不会全部讲完,只讲重点。但是,即便是复杂也需要完整地把man rpm(8)看一遍,知道rpm命令能够做哪些工作,这样在使用时心里才有数。

man rpm(8)内容有很好的结构,在“SYNOPSIS”一节,就看得出rpm命令能干的事:

QUERYING AND VERIFYING PACKAGES
INSTALLING, UPGRADING, AND REMOVING PACKAGES
MISCELLANEOUS

这些便是重点了,在实际使用中,需要看好参数选项和参数说明即可。

2 查询包

非常常用的参数就是-q(–query),它负责对RPM Database进行查询,用法:

rpm {-q|--query} [select-options] [query-options]

不同的查询需求,对应不同的select-options和query-options,需要具体查看man。

2.1 列出系统中安装的包

命令:rpm -qa

也可以用通配符来匹配:

$ rpm -qa 'kernel*'
kernel-4.9.8-201.fc25.x86_64
kernel-devel-4.9.9-200.fc25.x86_64
kernel-devel-4.9.10-200.fc25.x86_64
kernel-debuginfo-common-x86_64-4.5.5-300.fc24.x86_64
kernel-modules-4.9.8-201.fc25.x86_64
kernel-4.9.9-200.fc25.x86_64
kernel-core-4.9.10-200.fc25.x86_64
kernel-4.9.10-200.fc25.x86_64
kernel-core-4.9.9-200.fc25.x86_64
kernel-debuginfo-common-x86_64-4.8.6-300.fc25.x86_64
kernel-modules-4.9.10-200.fc25.x86_64
kernel-modules-4.9.9-200.fc25.x86_64
kernel-headers-4.9.10-200.fc25.x86_64
kernel-core-4.9.8-201.fc25.x86_64

还可以结合管道做过滤:

$ rpm -qa | fgrep kernel
kernel-4.9.8-201.fc25.x86_64
kernel-devel-4.9.9-200.fc25.x86_64
kernel-devel-4.9.10-200.fc25.x86_64
kernel-debuginfo-common-x86_64-4.5.5-300.fc24.x86_64
kernel-modules-4.9.8-201.fc25.x86_64
kernel-4.9.9-200.fc25.x86_64
kernel-core-4.9.10-200.fc25.x86_64
texlive-l3kernel-svn41246-30.fc25.noarch
kernel-4.9.10-200.fc25.x86_64
kernel-core-4.9.9-200.fc25.x86_64
kernel-debuginfo-common-x86_64-4.8.6-300.fc25.x86_64
kernel-modules-4.9.10-200.fc25.x86_64
kernel-modules-4.9.9-200.fc25.x86_64
kernel-headers-4.9.10-200.fc25.x86_64
kernel-core-4.9.8-201.fc25.x86_64

上面两个示例列出了系统安装的内核相关包,想知道哪个内核包是最近安装的、哪个时辰安装的,可以带上–last参数:

$ rpm -qa 'kernel*' --last
kernel-devel-4.9.10-200.fc25.x86_64           2017年02月21日 星期二 22时05分12秒
kernel-headers-4.9.10-200.fc25.x86_64         2017年02月21日 星期二 22时04分54秒
kernel-4.9.10-200.fc25.x86_64                 2017年02月21日 星期二 22时04分42秒
kernel-modules-4.9.10-200.fc25.x86_64         2017年02月21日 星期二 22时04分25秒
kernel-core-4.9.10-200.fc25.x86_64            2017年02月21日 星期二 22时04分22秒
kernel-devel-4.9.9-200.fc25.x86_64            2017年02月17日 星期五 16时17分42秒
kernel-modules-4.9.9-200.fc25.x86_64          2017年02月17日 星期五 15时21分04秒
kernel-core-4.9.9-200.fc25.x86_64             2017年02月17日 星期五 15时20分00秒
kernel-4.9.9-200.fc25.x86_64                  2017年02月17日 星期五 15时15分46秒
kernel-4.9.8-201.fc25.x86_64                  2017年02月10日 星期五 13时54分42秒
kernel-modules-4.9.8-201.fc25.x86_64          2017年02月10日 星期五 13时54分32秒
kernel-core-4.9.8-201.fc25.x86_64             2017年02月10日 星期五 13时54分30秒
kernel-debuginfo-common-x86_64-4.8.6-300.fc25.x86_64 2016年11月23日 星期三 12时33分03秒
kernel-debuginfo-common-x86_64-4.5.5-300.fc24.x86_64 2016年06月26日 星期日 16时14分42秒

2.2 查询包信息

查询某个包是否安装,命令用法如下:

rpm -q [包名]

如果没有打印出内容,说明该包尚未安装到系统中。

例,在编译驱动时,先查看是否安装内核源码的头文件:

$ rpm -q kernel-headers
kernel-headers-4.9.10-200.fc25.x86_64

例,查看kernel-headers的具体信息:

$ rpm -q --info kernel-headers
Name        : kernel-headers
Version     : 4.9.10
Release     : 200.fc25
Architecture: x86_64
Install Date: 2017年02月21日 星期二 22时04分54秒
Group       : Development/System
Size        : 3951044
License     : GPLv2 and Redistributable, no modification permitted
Signature   : RSA/SHA256, 2017年02月16日 星期四 21时29分59秒, Key ID 4089d8f2fdb19c98
Source RPM  : kernel-4.9.10-200.fc25.src.rpm
Build Date  : 2017年02月16日 星期四 08时10分58秒
Build Host  : bkernel01.phx2.fedoraproject.org
Relocations : (not relocatable)
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://www.kernel.org/
Summary     : Header files for the Linux kernel for use by glibc
Description :
Kernel-headers includes the C header files that specify the interface
between the Linux kernel and userspace libraries and programs.  The
header files define structures and constants that are needed for
building most standard programs and are also needed for rebuilding the
glibc package.

例,查看某个文件所属包:

rpm -qf `which ifconfig`
net-tools-2.0-0.40.20160329git.fc25.x86_6

例,列出包中包含哪些文件:

$ rpm -ql glibc
/etc/gai.conf
/etc/ld.so.cache
/etc/ld.so.conf
/etc/ld.so.conf.d
/etc/nsswitch.conf
/etc/rpc
/lib64/ld-2.24.so
/lib64/ld-linux-x86-64.so.2
/lib64/libBrokenLocale-2.24.so
...

例,列出包中的配置文件清单:

$ rpm -qc bash
/etc/skel/.bash_logout
/etc/skel/.bash_profile
/etc/skel/.bashrc

例,查询包安装和卸载时运行的脚本代码,这个非常有用,可以看到包安装之后额外做了哪些操作:

$ rpm -q --scripts bash
postinstall scriptlet (using <lua>):
nl        = '\n'
sh        = '/bin/sh'..nl
bash      = '/bin/bash'..nl
f = io.open('/etc/shells', 'a+')
if f then
  local shells = nl..f:read('*all')..nl
  if not shells:find(nl..sh) then f:write(sh) end
  if not shells:find(nl..bash) then f:write(bash) end
  f:close()
end
postuninstall scriptlet (using <lua>):
-- Run it only if we are uninstalling
if arg[2] == "0"
then
  t={}
  for line in io.lines("/etc/shells")
  do
    if line ~= "/bin/bash" and line ~= "/bin/sh"
    then
      table.insert(t,line)
    end
  end

  f = io.open("/etc/shells", "w+")
  for n,line in pairs(t)
  do
    f:write(line.."\n")
  end
  f:close()
end

例,查询包的依赖关系:

$ rpm -q --requires bash
/bin/sh
config(bash) = 4.3.43-4.fc25
filesystem >= 3
libc.so.6()(64bit)
libc.so.6(GLIBC_2.11)(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.15)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
libc.so.6(GLIBC_2.8)(64bit)
libdl.so.2()(64bit)
libdl.so.2(GLIBC_2.2.5)(64bit)
libtinfo.so.6()(64bit)
rpmlib(BuiltinLuaScripts) <= 4.2.2-1
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsXz) <= 5.2-1
rtld(GNU_HASH)

3 安装、更新和卸载

3.1 安装包

用法如下:

rpm {-i|--install} [install-options] PACKAGE_FILE ...

例,安装一个包:

$ sudo rpm -ivh emacs-25.1-3.fc25.x86_64.rpm

参数v和参数h分别表示显示安装详情和进度。

例,忽略依赖关系安装:

$ sudo rpm -ivh --nodeps emacs-25.1-3.fc25.x86_64.rpm

3.2 升级包

用法如下:

rpm {-U|--upgrade} [install-options] PACKAGE_FILE ...

例,更新一个包(卸载旧版本、安装新版本):

$ sudo rpm -Uvh git-2.9.3-2.fc25.x86_64.rpm

3.3 卸载包

用法如下:

rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test] PACKAGE_NAME ...

例,卸载一个软件包:

$ sudo rpm -e git

如果软件包有依赖关系是无法这样卸载的。带上–nodeps参数,将不会删除相关的依赖,而只删除包本身。比如我在Fedora上自己编译了内核,并打成RPM包,结果在卸载时要提示我卸载很多系统关键依赖,所以就得带上–nodeps参数。

4 验证包

RPM不仅提供增删改能力,还提供了验证机制,对已安装的包进行验证,知道每个文件变动情况。

例,bash包提供了多个配置文件,其中/etc/skel/.bashrc被我误删了,RPM的验证机制会发现这一变化:

$ rpm -V bash
遗漏   c /etc/skel/.bashrc

4.1 效验属性

如下,验证python-pip3包的输出结果:

$ rpm -V python3-pip | head -20
.......T.    /usr/bin/pip3
.......T.    /usr/bin/pip3.5
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/DESCRIPTION.rst
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/INSTALLER
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/METADATA
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/RECORD
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/WHEEL
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/entry_points.txt
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/metadata.json
遗漏     /usr/lib/python3.5/site-packages/pip-8.1.2.dist-info/top_level.txt
S.5....T.    /usr/lib/python3.5/site-packages/pip/__init__.py
.......T.    /usr/lib/python3.5/site-packages/pip/__main__.py
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/__init__.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/__main__.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/basecommand.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/baseparser.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/cmdoptions.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/download.cpython-35.pyc
S.5....T.    /usr/lib/python3.5/site-packages/pip/__pycache__/exceptions.cpython-35.pyc

可见第一列有大量类似“S.5….T.”的输出,这表示验证的属性。根据man rpm(8)描述,每位对应的属性如下:

S file Size differs
M Mode differs (includes permissions and file type)
5 digest (formerly MD5 sum) differs
D Device major/minor number mismatch
L readLink(2) path mismatch
U User ownership differs
G Group ownership differs
T mTime differs
P caPabilities differ

如果对应的属性没有问题,该位置以“.”表示。“S.5….T.”表示对应的文件大小(S)、文件MD5(5)和最后修改时间(T)不对。

一般看到大量这样的改变,可能的原因要么是手动安装过对应的软件,要么是通过其他途径升级过软件,或者是出了安全事故。上例的情况就是我用pip3命令做了自身升级。

例,对系统中所有包进行全面验证:

$ rpm -Va

5 RPM Database管理

5.1 重新构造rpm数据库

例,当我运行dnf命令时,提示:

  错误:rpmdb: BDB0113 Thread/process 29848/140606613985024 failed: BDB1507 Thread died in Berkeley DB library
  错误:db5 错误(-30973) 源自 dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
  错误:cannot open Packages index using db5 -  (-30973)
  错误:无法从 /var/lib/rpm 打开软件包数据库
  错误:Error: rpmdb open failed

说明RPM的数据库损坏,这时需要重建数据。

1、先备份/var/lib/rpm,拷贝一份到其他目录,防止彻底丢失;

2、验证存软件包的库是否有问题:dbverify /var/lib/rpm/Packages;

3、重建:rpm –rebuilddb

4、dnf clean all,再dnf update

6 其他

6.1 deb包转rpm包

系统需要安装alien。然执行:

alien -r xxx.deb

-r参数表示转换成rpm包。

6.2 解压RPM包

RPM实际上使用的CPIO格式打包的,用rpm2cpio命令转成CPIO格式即可:

rpm2cpio chkconfig-1.4-1.fc22.src.rpm | cpio -div

或者转成gzip格式解压:

$ rpm2archive git-2.9.3-2.fc25.x86_64.rpm
$ file git-2.9.3-2.fc25.x86_64.rpm.tgz
git-2.9.3-2.fc25.x86_64.rpm.tgz: gzip compressed data, last modified: Wed Feb 22 14:16:00 2017, from Unix

7 RPM包制作

一个软件包(Package)包含以下信息:

  • 包的基本信息,如软件名称、简介、作者、许可协议等;
  • 依赖关系;
  • 安装步骤;
  • 运行的文件、所需配置文件;

以上全部过程和信息定义在spec文件中。

7.1 准备工作

先创建好rpmbuild规范定义的目录,然后把源码等文件放到适当的位置,再创建spec文件。

7.1.1 目录定义

早期的RPM(<= 4.4)包只能由管理员创建,因为相关打包操作都在/usr/src/redhat目录中进行;现普通用户也可以打包,相关文件放在home目录的rpmbuild目录中。

把目录定义在哪儿、要定义哪些目录,可用以下命令来查看相关配置:

rpmbuild --showrc | fgrep _topdir

如下:

-14: _builddir	%{_topdir}/BUILD
-14: _buildrootdir	%{_topdir}/BUILDROOT
-14: _rpmdir	%{_topdir}/RPMS
-14: _sourcedir	%{_topdir}/SOURCES
-14: _specdir	%{_topdir}/SPECS
-14: _srcrpmdir	%{_topdir}/SRPMS

依照规范,需要定义以下目录:

  • BUILD:编译过程中暂存空间
  • BUILDROOT
  • RPMS:编译产生的二进制RPM位置;
  • SOURCES:存放源码;
  • SPECS:存放spec文件;
  • SRPMS:构造的源RPM。

在home下建立rpmbuild目录,然后依次建立以上目录。如果安装了rpmdevtools,可用rpmdev-setuptree命令完成环境初始化。

7.1.2 编写spec文件

这里以打包wget为例,从http://ftp.gnu.org/gnu/wget/ 下载源码压缩包,并把源码压缩包放至SOURCES目录中。

编辑SPECS/wget-1.19.spec:

Summary: 		GNU wget
License: 		GPL
Name: 			wget
Version: 		1.19
Release: 		1
Source: 		%{name}-%{version}.tar.xz
Group: 			Development/Tools

%description
The GNU wget program downloads files from the Internet using the command-line.

%prep
# 编译之前运行这段定义
# %setup -q是解压tarball文件
%setup -q

%build
./configure
make

%install
# 不要在%build的make中写--prefix参数,因为安装阶段只是在一个临时目录,否则可能运行时发生问题
make install DESTDIR=$RPM_BUILD_ROOT

%files
# 列出要打包的文件
%defattr(-,root,root)
/usr/local

# 这里还可以用%config指定配置文件,这样不会在安装时覆盖掉存在的配置文件
# 用%doc指定帮助文档,在使用--excludedocs,这部分会被跳过

有一些宏是系统定义好了的,位于/usr/lib/rpm/macros,不要去修改这个文件,如果要改变某些全局宏,就写在home目录下的.rpmmacros中。

7.1.3 spec其他参数参考

参数 含义
Prefix 安装路径
BuildRequires build过程中需要的包
Requires 安装过程需要的包

几个段说明:

段名 含义
%pre 安装前运行
%post 安装后运行
%preun 卸载包之前运行
%postun 卸载包之后运行

7.2 打包

使用rpmbuild命令:

rpmbuild -bb SPECS/wget-1.19.spec

-bb表示打包二进制包。 用-bs可以打包源码包。

rpmbuild会根据spec的定义依次运行:

1、%prep段,将源码解压到临时目录中;

2、运行%build段,编译源码;

3、运行%install段,把编译后的源码安装到某个目录中;

4、根据%files段中定义的文件,打包RPM包。

7.3 更多参考