3.3. RPM — 包管理器

在 SUSE Linux 中,RPM(RPM 包管理器)用于管理软件包。其主要程序是 rpmrpmbuild。用户、系统管理员和包构建人员可以查询强大的 RPM 数据库以获得有关已安装软件的详细信息。

本质上,rpm 具有 5 种方式:安装、卸载或更新软件包;重构建 RPM 数据库;查询 RPM 库或个别的 RPM 档案;包的完整性检查和包签名。rpmbuild 可用于从最初的源代码构建可安装包。

用特殊的二进制格式对可安装 RPM 档案进行打包。这些档案由要安装的程序文件和某些元信息组成,这些元信息供 rpm 在安装过程中配置软件包使用或者储存在 RPM 数据库中进行存档。RPM 档案通常具有扩展名 .rpm

[Tip]软件开发包

对于许多包,已将软件开发所需的部件(库、标题、包含文件等)放入单独的包中。只有当您要自己编译软件时才需要这些开发包(例如最新的 GNOME 包)。可以通过名称扩展 -devel 确定这些开发包,例如包 alsa-develgimp-develkdelibs3-devel

3.3.1. 校验包真实性

SUSE Linux RPM 包具有 GnuPG 签名。包括指纹的密钥是:


1024D/9C800ACA 2000-10-19 SuSE Package Signing Key <build@suse.de>
Key fingerprint = 79C1 79B2 E1C8 20C1 890F  9994 A84E DAE8 9C80 0ACA

命令 rpm --checksig package-1.2.3.rpm 可用于校验 RPM 包的签名来确定它确实来自 SUSE Linux 还是其它可信机构。特别建议对来自因特网的更新包使用此命令。SUSE Linux 公共包签名密钥通常驻留在 /root/.gnupg/ 中。该密钥还位于目录 /usr/lib/rpm/gnupg/ 中,允许一般用户校验 RPM 包的签名。

3.3.2. 管理包:安装、更新和卸载

通常,RPM 档案的安装非常简单:rpm -i package.rpm。使用此命令可以安装包,但前提是满足其依赖性并且不与其它包冲突。如果出现错误讯息,rpm 将请求那些需要安装的包以满足依赖性要求。在后台,RPM 数据库确保不出现冲突 - 一个特定文件只能属于一个包。通过选择不同的选项,您可以强制 rpm 忽略这些默认设置,但这只供专家用户使用。否则将影响系统的完整性并可能使系统无法更新。

选项 -U(即 --upgrade)和 -F(即 --freshen)可用于更新包。例如,rpm -F package.rpm。此命令将去除旧版本的文件并立即安装新文件。两个版本之间的差别是 -U 安装系统中以前不存在的包,但 -F 只更新以前安装的包。更新时,rpm 使用以下策略小心更新配置文件:

  • 如果配置文件未被系统管理员更改,则 rpm 将安装适当文件的新版本。系统管理员无需执行任何操作。

  • 如果更新前配置文件已被系统管理员更改,则 rpm 将以扩展名 .rpmorig.rpmsave(备份文件)保存更改的文件并安装新包中的版本,但前提是原先安装的文件和较新的版本不同。如果是这种情况,则将备份文件(.rpmorig.rpmsave)与新安装的文件进行比较,并在新文件中再次进行更改。随后,确保删除所有 .rpmorig.rpmsave 文件以避免以后的更新出现问题。

  • 如果配置文件已存在并且 .spec 文件中指定了 noreplace 标签,则出现 .rpmnew 文件。

更新后,在使用 .rpmsave.rpmnew 文件进行比较后应将它们去除,从而防止它们阻碍以后的更新。如果 RPM 数据库以前未能识别文件,则将为其指派扩展名 .rpmorig

否则,将使用 .rpmsave。换句话说,.rpmorig 是从异系统格式更新为 RPM 的结果。而 .rpmsave 是从较早的 RPM 更新为较新的 RPM 的结果。.rpmnew 不提供任何有关系统管理员是否对配置文件进行了任何更改的信息。/var/adm/rpmconfigcheck 中提供这些文件的列表。不覆盖某些配置文件(如 /etc/httpd/httpd.conf)以允许继续进行操作。

-U 开关仅仅是使用 -e 选项进行卸载并使用 -i 选项进行安装的等效项。只要可能,就可以使用 -U

要去除包,请输入 rpm -e packagerpm 只有在没有未解决的依赖性的情况下才会删除该包。例如,只要有其它程序需要 Tcl/Tk,理论上就不能删除它。即使是在这种情况下,RPM 也会向数据库寻求帮助。如果出于任何原因或在任何特殊情况下不能进行这一删除操作,即使存在任何其它依赖性,都最好使用选项 --rebuilddb 重构建 RPM 数据库。

3.3.3. RPM 和增补程序

为了确保系统的操作安全性,必须时常在系统中安装更新包。以前,包中的错误只能通过替换整个包来解决。这样,对只有小文件中存在错误的较大的包进行替换时就很容易产生大量数据。不过,SUSE RPM 提供了一项功能,支持在包中安装增补程序。

以下使用 pine 的示例中对最重要的考虑事项进行了说明:

增补程序 RPM 是否适合我的系统?

要对此进行检查,请先查询包的已安装版本。对于 pine,可以通过以下命令完成:

rpm -q pine
pine-4.44-188

然后检查增补程序 RPM 是否适合此版本的 pine:

rpm -qp --basedon pine-4.44-224.i586.patch.rpm 
pine = 4.44-188
pine = 4.44-195
pine = 4.44-207

此增补程序适用于 pine 的三个不同的版本。还列出示例中已安装的版本,从而可以安装增补程序。

增补程序将替换哪些文件?

在增补程序 RPM 中可以方便地找到受增补程序影响的文件。rpm 参数 -P 允许选择特殊的增补程序功能。使用以下命令显示文件列表:

rpm -qpPl pine-4.44-224.i586.patch.rpm
/etc/pine.conf
/etc/pine.conf.fixed
/usr/bin/pine

或者,如果已安装增补程序,则使用以下命令:

rpm -qPl pine
/etc/pine.conf
/etc/pine.conf.fixed
/usr/bin/pine
如何在系统中安装增补程序 RPM?

增补程序 RPM 的使用与普通 RPM 相同。唯一的区别就是必须已安装合适的 RPM。

系统中已安装了哪些增补程序,用于哪些包版本?

使用命令 rpm -qPa 可以显示系统中已安装的所有增补程序的列表。如果新系统中只安装了一个增补程序(如本示例中),则列表如下:

rpm -qPa
pine-4.44-224

如果以后要了解最初安装了哪个包版本,则可以在 RPM 数据库中获得此信息。对于 pine,可以通过以下命令显示此信息:

rpm -q --basedon pine
pine = 4.44-188

rpmrpmbuild 的手册页中提供了详细信息(包括有关 RPM 的增补程序功能的信息)。

3.3.4. 增量 RPM 包

增量 RPM 包包含旧版本和新版本的 RPM 包之间的差别。在旧 RPM 上应用增量 RPM 将得到全新的 RPM。不需要旧 RPM 的副本,因为增量 RPM 可以与已安装的 RPM 一起工作。增量 RPM 包的大小甚至比增补程序 RPM 小,这有利于通过因特网传送更新包。缺点是,涉及增量 RPM 的更新操作与使用纯粹 RPM 或增补程序 RPM 进行更新的情况相比,占用的 CPU 周期要长得多。要令 YaST 在 YOU 会话中使用增量 RPM 包,请在 /etc/sysconfig/onlineupdate 中将 YOU_USE_DELTAS 设置为 yes。在这种情况下,请准备好您的安装媒体。如果 YOU_USE_DELTAS 为空或者设置为 filesystem,则 YOU 尝试下载适用于已安装文件的增量包。在这种情况下不需要安装介质,但是下载时间将会更长。如果设置为 no,则 YOU 只使用增补程序 RPM 和常规 RPM。

prepdeltarpmwritedeltarpmapplydeltarpm 二进制文件是增量 RPM 套件(包 deltarpm)的一部分并帮助您创建和应用增量 RPM 包。使用以下命令,创建名为 new.delta.rpm 的增量 RPM。以下命令假设 old.rpmnew.rpm 是存在的:

prepdeltarpm -s seq -i info old.rpm > old.cpio
prepdeltarpm -f new.rpm > new.cpio

xdelta delta -0 old.cpio new.cpio delta

writedeltarpm new.rpm delta info new.delta.rpm
rm old.cpio new.cpio delta

如果旧包已经安装,则使用 applydeltarpm 可以从文件系统重新构建新的 RPM:

applydeltarpm new.delta.rpm new.rpm

如果不访问文件系统而从旧 RPM 得到它,请使用 -r 选项:

applydeltarpm -r old.rpm new.delta.rpm new.rpm
  

关于技术详细信息,请参见 /usr/share/doc/packages/deltarpm/README"

3.3.5. RPM 查询

使用 -q 选项, rpm 将初始化查询,使查看 RPM 档案(通过添加选项 -p)并查询已安装包的 RPM 数据库成为可能。可以使用多个开关指定所需信息的类型。请参见 表 3.6 “最重要的 RPM 查询选项”

表 3.6. 最重要的 RPM 查询选项

-i

包信息

-l

文件列表

-f FILE

查询包含文件 FILE 的包(必须使用 FILE 指定完整路径)

-s

带有状态信息的文件列表(间接指定 -l

-d

仅列出文档文件(间接指定 -l

-c

仅列出配置文件(间接指定 -l

--dump

带有完整详细信息的文件列表(将用于 -l-c-d

--provides

列出包中可被另一个包通过 --requires 请求的功能

--requires, -R

包需要的功能

--scripts

安装脚本(预安装、后安装、卸载)

例如,命令 rpm -q -i wget 显示 例 3.2 “rpm -q -i wget” 中所示的信息。

例 3.2. rpm -q -i wget


Name        : wget                         Relocations: (not relocatable)
Version     : 1.9.1                             Vendor: SUSE LINUX AG, Nuernberg, Germany
Release     : 50                            Build Date: Sat 02 Oct 2004 03:49:13 AM CEST
Install date: Mon 11 Oct 2004 10:24:56 AM CEST      Build Host: f53.suse.de
Group       : Productivity/Networking/Web/Utilities   Source RPM: wget-1.9.1-50.src.rpm
Size        : 1637514                          License: GPL
Signature   : DSA/SHA1, Sat 02 Oct 2004 03:59:56 AM CEST, Key ID a84edae89c800aca
Packager    : http://www.suse.de/feedback
URL         : http://wget.sunsite.dk/
Summary     : A tool for mirroring FTP and HTTP servers
Description :
Wget enables you to retrieve WWW documents or FTP files from a server.
This can be done in script files or via the command line.
[...]

只有当您指定带有完整路径的完整文件名时,选项 -f 才起作用。根据需要提供任意多个文件名。例如,以下命令

rpm -q -f /bin/rpm /usr/bin/wget

产生:

rpm-4.1.1-191
wget-1.9.1-50

只要知道部分文件名,就可以使用 shell 脚本,如 例 3.3 “搜索包的脚本” 所示。当运行所显示的脚本时,将部分文件名以参数的形式传递给该脚本。

例 3.3. 搜索包的脚本

#! /bin/sh
for i in $(rpm -q -a -l | grep  $1); do
    echo "\"$i\" is in package:"
    rpm -q -f $i
    echo ""
done

命令 rpm -q --changelog rpm 按照日期显示有关特定包更改信息的详细列表。此示例显示有关包 rpm 的信息。

借助已安装的 RPM 数据库,可以进行校验检查。使用 -V-y--verify 对其进行初始化。使用此选项,rpm 显示安装后已被更改的包中的所有文件。rpm 使用 8 个字符符号给出有关以下更改的一些提示:

表 3.7. RPM 校验选项

5

MD5 校验和

S

文件大小

L

符号链接

T

修改时间

D

主要和次要设备编号

U

拥有者

G

M

方式(权限和文件类型)

对于配置文件,将输出字母 c。例如,对于 /etc/wgetrc (wget) 的更改:

rpm -V wget
S.5....T c /etc/wgetrc

RPM 数据库的文件被放置在 /var/lib/rpm 中。如果分区 /usr 的大小为 1 GB,则这个数据库可能会占用将近 30 MB,特别是在完全更新之后。如果数据库比预期大得多,则最好使用选项 --rebuilddb 重构建数据库。在执行此操作之前,制作旧数据库的备份。cron 脚本 cron.daily 每天制作数据库的副本(用 gzip 打包)并将这些副本储存在 /var/adm/backup/rpmdb 中。副本数由变量 MAX_RPMDB_BACKUPS 来控制(默认值:5)(在 /etc/sysconfig/backup)。对于 1 GB 的 /usr,单个备份的大小大约为 1 MB。

3.3.6. 安装和编译源包

SUSE Linux 的所有源包都带有 .src.rpm 扩展名(源 RPM)。

[Tip]提示

源包可以从安装媒体复制到硬盘并使用 YaST 解压缩。但是,在包管理器中它们不会被标记为已安装 ([i])。这是因为源包不是在 RPM 数据库中输入的。只有已安装的操作系统软件列在 RPM 数据库中。“安装”源包时,只将源代码添加到系统中。

以下目录必须可用于 /usr/src/packages 中的 rpmrpmbuild(除非在诸如 /etc/rpmrc 这样的文件中指定自定义设置):

SOURCES

代表原始源(.tar.bz2.tar.gz 文件等)和特定于发布版本的调整(多为 .diff.patch 文件)

SPECS

代表 .spec 文件,类似于元 Makefile,该文件控制构建进程

BUILD

在此目录中解包、增补和编译所有源

RPMS

存储完整的二进制包的位置

SRPMS

这里是源 RPM

使用 YaST 安装源包时,将在 /usr/src/packages 中安装所有需要的组件:源和调整在 SOURCES 中,相关的 .spec 文件在 SPECS 中。

[Warning]警告

不要对系统部件(glibcrpmsysvinit 等)进行试验,因为这将会影响系统的可操作性。

下面的示例使用 wget.src.rpm 包。使用 YaST 安装此包之后,您应该具有与以下所列相似的文件:

/usr/src/packages/SOURCES/nops_doc.diff
/usr/src/packages/SOURCES/toplev_destdir.diff
/usr/src/packages/SOURCES/wget-1.9.1+ipvmisc.patch
/usr/src/packages/SOURCES/wget-1.9.1-brokentime.patch
/usr/src/packages/SOURCES/wget-1.9.1-passive_ftp.diff
/usr/src/packages/SOURCES/wget-LFS-20040909.tar.bz2
/usr/src/packages/SOURCES/wget-wrong_charset.patch
/usr/src/packages/SPECS/wget.spec

rpmbuild -b X /usr/src/packages/SPECS/wget.spec 启动编译。X 是通配符,代表构建进程的不同阶段(有关详细信息,请参见 --help 的输出或 RPM 文档)。以下内容只是简要说明:

-bp

/usr/src/packages/BUILD 中准备源:解包和增补。

-bc

执行与 -bp 相同的操作,但还进行编译。

-bi

执行与 -bp 相同的操作,但还安装生成的软件。警告:如果包不支持 BuildRoot 功能,则可能会覆盖配置文件。

-bb

执行与 -bi 相同的操作,但还创建二进制包。如果编译成功,二进制包应该在 /usr/src/packages/RPMS 中。

-ba

执行与 -bb 相同的操作,但还创建源 RPM。如果编译成功,二进制包应该在 /usr/src/packages/SRPMS 中。

--short-circuit

跳过某些步骤。

现在可以使用 rpm -i 或最好使用 rpm -U 来安装创建的二进制 RPM。使用 rpm 进行安装使它显示在 RPM 数据库中。

3.3.7. 使用 build 编译 RPM 包

许多包存在的风险是构建进程中会将许多不需要的文件添加到正在运行的系统中。为防止发生这种情况,请使用 build,它将创建构建包的确定环境。要建立这一 chroot 环境,build 脚本必须和完整的包树结构一起提供。可以通过 NFS 或从 DVD 使用硬盘上的此树。使用 build --rpms directory 设置位置。与 rpm 不同,build 命令在源目录中查找 SPEC 文件。要用系统中 /media/dvd 下装入的 DVD 构建 wget(如上面的示例中),请以 root 用户的身份使用以下命令:

cd /usr/src/packages/SOURCES/
mv ../SPECS/wget.spec .
build --rpms /media/dvd/suse/ wget.spec

随后,将在 /var/tmp/build-root 建立一个最小的环境。在此环境中构建包。完成后,生成的包位于 /var/tmp/build-root/usr/src/packages/RPMS 中。

build 脚本提供多个附加选项。例如,使脚本优先选择您自己的 RPM、忽略构建环境的初始化或者将 rpm 命令限制在上述阶段之一。使用 build --help 并通过阅读 build 手册页来访问更多信息。

3.3.8. 用于 RPM 档案和 RPM 数据库的工具

Midnight Commander (mc) 可以显示 RPM 档案的内容并复制部分内容。它将档案表示为虚拟文件系统,提供 Midnight Commander 所有常用的菜单选项。使用 F3 键显示 HEADER。 使用光标键和 Enter 键查看档案结构。使用 F5 键复制部分档案。

KDE 提供 kpackage 工具,作为 rpm 的前端。还提供作为 YaST 模块的功能齐全的包管理器(请参见第 2.3.1 节 “安装和去除软件” (↑启动))。