在 Fedora 或 Rocky 系统上,主目录之外的几乎每个文件都由某个 rpm 软件包放置,而 rpm 能告诉你究竟是哪一个。它能回答 dnf 通常略过的问题:软件包的精确版本是什么、某个文件属于哪个包、包内文件是否仍与安装时的元数据一致,以及一个下载下来的 rpm 会把文件放到哪里。
本文所有输出均来自 2026 年 11 月在 Fedora 45(RPM 6.1)和 Rocky 10.2(RPM 4.19)上的实际运行。两者的差异主要集中在签名密钥处理上,因此单独安排了一节。Debian 和 Ubuntu 用户也可以通过 APT 速查表完成同类工作。
RPM 速查表
普通用户即可执行查询;安装、删除或重建数据库需要 sudo,校验同样通常需要 root,因为像 sshd_config 这类权限为 0600 的文件无法在不提权的情况下读取并比对摘要。命令末尾出现 *.rpm 时,表示读取已下载的软件包文件,而不是已安装包;带 -p 的变体会直接读取这些文件,不访问 rpm 数据库。
查询已安装软件包
| 命令 | 作用 |
|---|---|
rpm -q bash |
显示某个软件包精确的 name-version-release |
rpm -qi bash |
显示完整元数据:大小、许可证、安装日期与签名密钥 |
rpm -ql sudo |
列出该软件包安装的全部文件 |
rpm -qc openssh-server |
只列出该软件包的配置文件 |
rpm -q --requires bash |
列出软件包所需的依赖 |
rpm -q --provides bash |
列出软件包向其他包提供的能力 |
rpm -qf /usr/bin/sudo |
显示某个文件属于哪个软件包 |
rpm -qa |
列出所有已安装软件包 |
rpm -qa | wc -l |
统计已安装软件包数量 |
rpm -qa --last |
按安装时间从新到旧列出软件包 |
rpm -q bash --qf '%{NAME} %{VERSION}-%{RELEASE} %{ARCH}\n' |
按自定义格式输出,每个软件包一行 |
-q 系列会有意以安静方式失败。软件包未安装时会输出 package nginx is not installed 并返回退出码 1,因此不加额外参数就能直接串入 shell 条件判断。工具中没有比这更友好的输出方式,掌握一次退出码即可长期依赖它。
查询 rpm 文件
| 命令 | 作用 |
|---|---|
rpm -qp pkg.rpm |
不安装,直接查询软件包文件 |
rpm -qip pkg.rpm |
显示软件包文件的元数据 |
rpm -qlp pkg.rpm |
列出软件包文件中的内容 |
dnf download jq |
将当前版本的 rpm 下载到当前目录,不执行安装 |
dnf download 是取得可检查软件包文件的干净方式。在 Fedora 上,该命令内置于 dnf5;在 Rocky 上它来自 dnf-plugins-core,而在 Rocky 10.2 实验镜像中无需额外安装即可直接使用 dnf download。取得文件后,可参考后文解包部分。
校验已安装软件包
| 命令 | 作用 |
|---|---|
sudo rpm -V openssh-server |
将包内文件与安装时记录的元数据比较 |
sudo rpm -Va |
校验全部已安装软件包;速度较慢,但能获得全貌 |
sudo dnf reinstall -y openssh-server |
恢复缺失文件;已修改的配置文件会保持不变 |
没有异常时软件包不会输出任何内容,并以 0 退出。只要有输出,每个文件一行,其中包含九字符标志串;后文会解释这些标志。
安装、升级与删除
| 命令 | 作用 |
|---|---|
sudo rpm -ivh btop-*.rpm |
显示详细过程与进度条进行安装 |
sudo rpm -ivh a.rpm b.rpm |
将多个软件包作为一个事务安装 |
sudo rpm -Uvh pkg.rpm |
未安装则安装;已安装则升级并移除旧版本 |
sudo rpm -e jq |
删除已安装软件包 |
sudo rpm --rebuilddb |
根据软件包头重建 rpm 数据库索引 |
除非有明确理由,应优先使用 rpm -U,而不是 rpm -i。对已安装软件包使用 -i 会报错,并不会执行升级;安装一节展示了这种拒绝结果。
提取 rpm 内容
| 命令 | 作用 |
|---|---|
rpm2cpio pkg.rpm | cpio -idmv 2>&1 |
将载荷提取到当前目录 |
rpm2cpio pkg.rpm | cpio -it |
只列出载荷内容,不提取 |
提取需要 cpio 软件包;两个实验镜像均已预装,如果系统缺少它,可执行 dnf install cpio。提取过程不会运行脚本、检查签名或触碰 rpm 数据库,因此这是从不愿安装的软件包中取出配置文件或二进制的安全方式。
签名与密钥
| 命令 | 作用 |
|---|---|
rpmkeys --checksig pkg.rpm |
验证软件包的摘要与签名 |
rpm -q gpg-pubkey |
列出已导入的签名密钥,它们以伪软件包形式存储 |
rpmkeys --list |
列出密钥及其用户 ID |
sudo rpmkeys --import vendor.asc |
从文件导入供应商公共签名密钥 |
sudo rpmkeys --import https://dl.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-10 |
直接从 HTTPS URL 导入密钥 |
rpmkeys --export <fingerprint> > key.asc |
将已导入密钥保存为文件(RPM 6) |
sudo rpmkeys --erase <fingerprint> |
删除密钥;RPM 4.19 也接受 8 位十六进制密钥 ID |
在 Fedora 45 上,gpg-pubkey 名称与旧教程不同,因为 RPM 6 会记录完整指纹,而 RPM 4 记录短密钥 ID。RPM 6 一节会同时展示两种形式。对于软件包之外的密钥与证书工作,可在 rpmkeys 停止的地方改用 OpenSSL 速查表。
查找文件所属的软件包
需要知道某个文件由什么安装时,使用 rpm -qf。它可用于二进制、库和配置文件,因为查询只读取数据库,不读取文件本身。答案就是所属软件包的完整 name-version-release:
rpm -qf /usr/bin/sudo
rpm -qf /etc/ssh/sshd_config
这两条查询在 Fedora 45 上都正常解析,并同时展示系统的两个层面。sudo 二进制属于 sudo 包,而守护进程配置属于 openssh-server,因此修改这两个文件所影响的对象完全不同:

加固服务器时,配置文件的情形尤其重要。/etc/ssh/sshd_config 中的设置属于 openssh-server 的范畴,并非 sudo;监视它是否被改动应使用 rpm -V openssh-server,下一节会详细说明。
查看软件包详情和文件列表
rpm -qi 会打印一个软件包的元数据块。面对陌生系统时,应查看大小、安装日期和签名行,这三项合起来能说明包是什么、何时进入系统,以及发行版是否为其签名:

文件侧的查询可以补全全貌:rpm -ql 列出软件包安装的全部文件,rpm -qc 进一步缩小到配置文件。依赖方面,--requires 说明包需要什么,--provides 说明它向系统其他部分提供什么:
rpm -q --requires bash | head -4
在 Rocky 10.2 上,前四条混合了文件路径、带版本的 capability 和共享库,这正是 rpm 记录大多数依赖的方式:
/usr/bin/sh
config(bash) = 5.2.26-6.el10
filesystem >= 3
libc.so.6()(64bit)
Fedora 45 会输出同样四行,只是 config(bash) 使用自己的 bash 发行版本。-qp 变体会对已下载的软件包文件执行相同查询,而不是访问数据库。在允许第三方 rpm 接近安装流程之前,应先使用这些查询检查它。
如果想使用上述 name-version-release 以外的格式,--qf 接受的每个查询标签都记录在 rpm.org 的 queryformat 手册页中。
使用 rpm -V 校验已安装软件包
rpm -V 会将磁盘文件与安装时记录的大小、摘要、模式、所有者和时间戳比较。它是回答“这个软件包是否被改过”的工具,一切正常时会有意保持沉默。下例先修改一个配置文件并删除另一个文件,随后两次尝试修复:

标志串从左到右阅读,每列对应一项检查:
S表示文件大小与记录不同5表示摘要不同,也就是内容已改变T表示修改时间发生变化- 行尾的
c表示该文件属于配置文件
这些是本文截图实际命中的列。其余列覆盖模式、设备、符号链接、用户、组和能力变化,rpm 手册列出了全部九个字段。已删除的文件显示为 missing,而不是标志串。截图中,/etc/ssh/sshd_config 被追加一行后显示为 S.5....T. c,被删除的 PAM 片段显示为 missing。两个软件包失败时退出码为 2;单个软件包失败时退出码为 1。
大多数教程在这里容易出错。dnf reinstall 会恢复缺失的 PAM 文件,但会保留已编辑的 sshd_config,因为它是你修改过的配置文件,而同版本软件包中的副本并未变化,所以 rpm 保留你的版本。Rocky 10.2 的行为相同。要取回软件包原始副本,应先把已编辑文件移开再重装,之后 rpm -V 会恢复安静并返回 0。接着将自己的副本与新文件做 diff,只迁移真正需要的修改。
全系统审计可使用 rpm -Va 遍历所有软件包。在刚克隆的 Fedora 45 虚拟机上,它不到 6 秒检查了 554 个软件包,并输出 8 行,均不是真正问题:
..5....T. c /etc/cloud/cloud.cfg
.M....... /run/cloud-init
.M....... g /usr/lib/sysimage/libdnf5/environments.toml
.M....... g /usr/lib/sysimage/libdnf5/groups.toml
.M....... g /usr/lib/sysimage/libdnf5/modules.toml
.M....... g /usr/lib/sysimage/libdnf5/nevras.toml
.M....... g /usr/lib/sysimage/libdnf5/packages.toml
.M....... g /usr/lib/sysimage/libdnf5/system.toml
M 列表示模式改变,g 标记表示 ghost 文件,即软件包声明但运行时才创建的文件,因此 dnf 的状态文件总会出现在这里。Rocky 10.2 在约 4 秒内输出 7 行。长期运行的服务器会报告更多结果,其中大多是主动编辑过的配置文件,因此应先过滤 c 和 g 行,再检查剩余内容。
使用 rpm 安装、升级和删除
当手头已有软件包文件,通常是下载或自行构建的文件时,可直接使用 rpm。-ivh 表示安装、详细输出和哈希进度条。两个相互依赖的软件包可以在同一事务中安装:

实际最常遇到的两种情况会被 rpm 明确拒绝。缺少依赖会在写入任何内容前中止事务;安装已存在的软件包会报错,而不是静默无操作:

这两种失败都能干净恢复,不会留下残留:
- 缺少依赖时,运行
sudo dnf install ./btop-*.rpm,让 dnf 从配置仓库解析其余依赖 - 遇到已安装错误时,如果文件是新版本,可使用
rpm -Uvh;同版本时-Uvh也会拒绝(实验中退出码为 2),此时应使用dnf reinstall - 要完全重来,可先用
rpm -e删除软件包,再重新安装
-U 也能安装尚不存在的软件包,因此是更安全的默认选择。在 Fedora 45 上删除 tree 后,同一文件可直接重新安装:
sudo rpm -Uvh tree-2.3.1-2.fc45.x86_64.rpm
rpm 会验证软件包、准备事务并安装,h 参数会显示哈希进度条:
Verifying... ########################################
Preparing... ########################################
Updating / installing...
tree-2.3.1-2.fc45 ########################################
在删除前,对已安装的 tree 执行同一命令会输出 package tree-2.3.1-2.fc45.x86_64 is already installed,不会发生任何变化。相比之下,sudo rpm --rebuilddb 在两个发行版上成功时都完全静默并返回 0;它只应在 rpm 报告数据库损坏时运行,不应作为日常维护。
dnf5 速查表深入介绍了仓库侧流程,包括 dnf 处理本地文件时所需的 ./ 路径语法。
删除失败也遵循类似逻辑。Fedora 45 删除 jq 时会因 lvm2 依赖而停止,Rocky 10.2 上则会因 dracut-network 停止:
sudo rpm -e jq
拒绝信息会指出依赖包。Fedora 给出的原因是 lvm2:
error: Failed dependencies:
jq is needed by (installed) lvm2-2.03.43-2.fc45.x86_64
Rocky 10.2 会以相同格式指出另一个软件包,并返回 1:
error: Failed dependencies:
jq is needed by (installed) dracut-network-107-9.el10_2.x86_64
两种情况下都没有删除任何内容,系统与执行命令前完全一致。可以同时删除依赖包,或者接受该包继续存在,因为依赖关系真实存在,系统中有组件正在使用它。--nodeps 可以强制删除,但会让依赖包保留一个已不存在的依赖,之后每次事务都可能重新发现这一损坏状态。
不安装 rpm,直接提取文件
rpm2cpio 会把软件包文件转换成 stdout 上的 cpio 流,cpio -idmv 则相对于当前目录解包。整个过程不会安装任何内容、不会运行脚本,rpm 数据库也不知道发生过操作。因此,这是恢复单个配置文件,或读取一个不值得信任、不适合安装的二进制时的安全方式:

示例命令中的 2>&1 很重要,因为 cpio -v 会把文件列表写到 stderr。必须合并流,列表才会显示出来。管道中的 grep -v build-id 会过滤 usr/lib/.build-id/ 下的调试链接目录,因为它们不是这里需要的文件。
提取后,文件会落在 ./usr/ 下。ls -l usr/bin/jq 可确认二进制存在且保留原始模式位,之后可以复制到目标位置或直接读取。模式位来自软件包头。root root 所有者只是因为本次以 root 提取;若以普通用户执行,文件就归该用户所有,这对一次性的副本通常更合适。
若要在提取前查看软件包将安装什么,可改为列出载荷:
rpm2cpio jq-1.8.2-5.fc45.x86_64.rpm | cpio -it | grep -v build-id
对 Fedora 45 的 jq 软件包,这会输出十个路径以及 cpio 的块计数,不向磁盘写入内容:
950 blocks
./usr/bin/jq
./usr/lib64/libjq.so.1
./usr/lib64/libjq.so.1.0.4
./usr/share/doc/jq
./usr/share/doc/jq/AUTHORS
./usr/share/doc/jq/NEWS.md
./usr/share/doc/jq/README.md
./usr/share/licenses/jq
./usr/share/licenses/jq/COPYING
./usr/share/man/man1/jq.1.gz
对同一文件使用 rpm -qlp,会从元数据侧列出完全相同的十个路径,只是没有前导 ./,因此可任选已习惯的方式。如果要安装比仓库更新的应用,例如通过 rpm 安装较新的 LibreOffice,两秒钟的载荷检查就能说明文件会落在哪些位置。
使用 rpmkeys 检查签名和管理密钥
rpmkeys --checksig 会使用 rpm 已知的密钥验证软件包摘要和签名。发行版仓库中的软件包会检查干净,因为其密钥已经在数据库中:
rpmkeys --checksig jq-1.8.2-5.fc45.x86_64.rpm
正常结果会同时列出两层检查并返回 0:
jq-1.8.2-5.fc45.x86_64.rpm: digests signatures OK
失败情况也值得查看一次,因为未导入密钥签名的软件包正是这种表现。内容被篡改的软件包还会摘要失败。下例先删除 Fedora 签名密钥,随后同一检查被拒绝。退出码 1 就是信号,因为 rpm 不会输出比这更醒目的提示:

digests SIGNATURES NOT OK 且退出码为 1,表示软件包本身完整,但没有已导入密钥为其背书。截图完整展示以下循环:
- 用
rpmkeys --export导出当前密钥,便于稍后恢复 - 用
rpmkeys --erase和对应指纹从密钥环删除 - 再次执行
rpmkeys --checksig,此时输出digests SIGNATURES NOT OK并返回 1 - 用
rpmkeys --import导入已保存密钥 - 再次检查,恢复输出
digests signatures OK
旧教程在第二步使用 rpmkeys --delete。该命令在 RPM 6.1 仍可用,但 rpmkeys 手册已把 --delete 和 -d 标记为弃用,建议改用 --erase 和 -e。将 rpmkeys --import 指向不存在的路径会报 import read failed(2),且不产生任何变化,因此拼写错误没有副作用。
--import 也接受 HTTPS URL,可省去手动下载供应商密钥的步骤。在 Rocky 10.2 上,同样的循环针对发行版密钥执行,并从 Rocky 镜像直接重新导入:

与 Fedora 相比有两个细节不同。RPM 4.19 的 --erase 接受短密钥 ID 6fedfc85,而且没有 --export,因此如果需要恢复密钥,应保留供应商的 .asc 文件或 URL。URL 导入在 Fedora 45 上也有效。只能从信任的 HTTPS URL 导入,因为该 URL 提供的密钥此后会为软件包背书。
导入的密钥以名为 gpg-pubkey 的伪软件包存储,因此普通查询命令也能管理它们。在 Rocky 10.2 上,它们的显示方式与所有旧教程一致:版本字段为短密钥 ID,发行版密钥文件仍位于 /etc/pki/rpm-gpg/:

对该伪软件包执行 rpm -qi 会打印普通元数据块,其中 Group : Public Keys 且自身没有签名。rpm -e gpg-pubkey-6fedfc85-682ae1a9 也能删除密钥,并在 Rocky 10.2 上静默执行。在 Fedora 45 上相同写法仍可用,但会输出警告:
warning: erasing gpg-pubkey packages is deprecated; use rpmkeys --delete 4f50a6114cd5c6976a7f1179655a4b02f577861e
该警告仍建议 --delete,但手册现在已将其标为弃用。--erase 会执行同一操作,因此两个发行版都应使用 rpmkeys --erase。
新版 RPM 主版本对密钥处理的改变
Fedora 45 使用 RPM 6,而 Rocky 10 及其他企业 Linux 重建版仍使用 4.x 系列,差异正好集中在本速查表覆盖的命令上。最明显的变化是密钥名称:RPM 4 记录 8 位十六进制密钥 ID,因此 rpm -q gpg-pubkey 输出 gpg-pubkey-6fedfc85-682ae1a9;RPM 6 则在该字段记录完整指纹(Fedora v4 密钥为 40 位十六进制),同一查询会输出长得多的版本字符串。任何匹配旧短格式的教程或脚本在 Fedora 上都会得不到结果,因此下文列出密钥的命令比伪软件包名称更重要。
第二个差异会影响旧脚本,但它来自 Fedora 打包方式,而不是 RPM 6 本身。在 Rocky 上,供应商密钥文件位于 /etc/pki/rpm-gpg/,如上图所示。Fedora 45 的该目录为空,因为 fedora-gpg-keys 软件包现在把文件放在 /usr/share/pki/rpm-gpg/。两个发行版中真正导入的密钥都保存在 rpm 数据库,rpmkeys --list 就是从那里读取:
rpmkeys --list
Fedora 45 每行先打印 40 位指纹,再打印密钥用户 ID:
4f50a6114cd5c6976a7f1179655a4b02f577861e Fedora (45) <fedora-45-primary@fedoraproject.org> public key
同一命令在 Rocky 10.2 的 RPM 4.19 上也可用,但会输出短格式 6fedfc85-682ae1a9: Release Engineering (Rocky Linux 10),正如上文 Rocky 截图所示。实用规则是:用两个系列行为一致的 rpmkeys --checksig 进行验证;只有为某一发行版编写脚本时,才需要处理 gpg-pubkey 的命名差异。除本节涉及的密钥处理(命名、--export 和 rpm -e gpg-pubkey 警告)外,两个发行版上的每条命令行为都相同。
将本页放在终端旁对照练习几次,查询参数会比预期更快形成肌肉记忆。命令被拒绝时,拒绝文本通常会直接指出应继续检查的软件包或依赖,这往往已经足够。凡是仓库侧操作,都交给 dnf;只把只有 rpm 能回答的问题留给它。本速查表属于站点的免费资料包,速查表中心还包含 dnf5、kubectl 等其他内容。










