Linux 世界有两大软件包管理体系:
| 体系 | 代表发行版 | 包格式 | 管理工具 |
|---|---|---|---|
| Debian 系 | Debian、Ubuntu、Deepin | .deb | dpkg、apt、apt-get |
| Red Hat 系 | RHEL、CentOS、Fedora、Rocky Linux | .rpm | rpm、yum、dnf |
本文聚焦 Red Hat 系(CentOS 7/8/9)的 RPM 软件包管理体系。这是企业服务器市场占有率最高的派系,也是运维工程师必须熟练掌握的核心技能。
RPM 体系内有三个核心角色,经常分不清:
.rpm 二进制包,负责安装、卸载、查询、校验。但它不能自动解决依赖关系。三者的协作关系可以用一句话说清:SRPM 是"原材料",RPM 是"成品零件",YUM 是"自动化装配流水线"。
RPM(Red Hat Package Manager) 是 Red Hat 公司开发的软件包管理标准,也是 LSB(Linux 标准规范)推荐的包格式。
优点:
缺点:
RPM 包名看似复杂,实则结构规整。以下面这个为例:
展开代码nginx-1.24.0-1.el7.x86_64.rpm
逐段拆解:
| 片段 | 示例值 | 含义 |
|---|---|---|
| 软件名 | nginx | 软件名称 |
| 版本号 | 1.24.0 | 上游软件版本,对应 Nginx 官方发布版本 |
| 发布号 | 1 | RPM 打包的修订次数,同一版本源码第几次打包 |
| 系统标识 | el7 | 适配系统:el7=CentOS/RHEL 7,el8=CentOS 8,el9=CentOS 9 |
| 架构 | x86_64 | CPU 架构:x86_64、aarch64、i686、noarch(无架构限制) |
| 扩展名 | .rpm | 固定后缀 |
noarch表示与架构无关:一般是纯脚本、配置文件、Python/Perl 程序等,所有架构通用。
常见架构对照:
x86_64:64 位 Intel/AMD 处理器aarch64:64 位 ARM 处理器(如鲲鹏、飞腾)i686:32 位 Intel/AMD(已罕见)RPM 所有状态信息存储在 /var/lib/rpm/ 下的 Berkeley DB 数据库中(CentOS 7)或 ndb/sqlite 格式(CentOS 8/9)。
核心文件:
| 路径 | 作用 |
|---|---|
/var/lib/rpm/Packages | 主数据库,记录所有已安装包的信息(名称、版本、文件列表等) |
/var/lib/rpm/Name | 按包名索引 |
/var/lib/rpm/Basenames | 按文件名索引,rpm -qf /path/file 就用它 |
/var/lib/rpm/Group | 按组索引 |
/var/lib/rpm/Requirename | 依赖关系索引 |
⚠️ 核心认知:RPM 数据库是 RPM 体系的心脏。数据库损坏会导致 rpm 命令全部失效,表现为"已安装软件无法查询、新软件无法安装"。
展开代码# 基本安装 rpm -ivh nginx-1.24.0-1.el7.x86_64.rpm # -i: install 安装 # -v: verbose 显示详细信息 # -h: hash 显示进度条(#号) # 典型输出: # Preparing... ################################# [100%] # Updating / installing... # 1:nginx-1.24.0-1.el7 ################################# [100%]
❌ 依赖缺失时的输出:
展开代码# rpm -ivh php-8.0.rpm # error: Failed dependencies: # libcrypto.so.1.1()(64bit) is needed by php-8.0 # libssl.so.1.1()(64bit) is needed by php-8.0 # 意思:缺少 libcrypto 和 libssl 这两个库,需要先安装 openssl-libs
忽略依赖强制安装(高危):
展开代码rpm -ivh --nodeps package.rpm # 跳过依赖检查,强制安装 rpm -ivh --force package.rpm # 强制覆盖安装(即使已安装同版本)
⚠️ 生产禁忌:
--nodeps和--force仅限极端排错场景使用,跳过依赖后软件大概率无法正常运行。
展开代码rpm -e nginx # -e: erase 卸载 # 如果其他包依赖它,会报错: # error: Failed dependencies: # nginx is needed by (installed) nginx-module-xxx # 这时需要先卸载依赖它的包,或使用 --nodeps(不推荐)
展开代码rpm -Uvh nginx-1.26.0-1.el7.x86_64.rpm # -U: upgrade,若已安装旧版本则升级,未安装则安装 rpm -Fvh nginx-1.26.0-1.el7.x86_64.rpm # -F: freshen,仅当已安装旧版本时才升级,未安装则跳过
-U vs -F 的区别:
-U:不管有没有旧版本,都安装。适合通用场景。-F:只升级已有包,不会安装新包。安全性更高,适合批量更新目录。展开代码# 查询已安装的所有包 rpm -qa # query all # 查询指定包是否安装 rpm -q nginx # 已安装显示版本号,未安装提示 not installed # 查询包的详细信息 rpm -qi nginx # -i: info,显示版本、发行、安装时间、描述等 # 查询包的文件列表 rpm -ql nginx # -l: list,列出包安装的所有文件路径 # 查询某文件属于哪个包(排错神器) rpm -qf /etc/nginx/nginx.conf # -f: file,输出 nginx-1.24.0-1.el7.x86_64 # 查询包的配置文件 rpm -qc nginx # -c: config files # 查询包的依赖 rpm -qR nginx # -R: requires,显示该包依赖哪些组件 # 查询未安装包的信息 rpm -qpi nginx-1.24.0.rpm # 查看 .rpm 文件的详细信息(不安装) rpm -qpl nginx-1.24.0.rpm # 查看 .rpm 文件包含哪些文件
展开代码# 校验已安装包的文件是否被篡改(对比数据库记录) rpm -V nginx # -V: verify # 输出示例: # S.5....T. c /etc/nginx/nginx.conf # 这表示 /etc/nginx/nginx.conf 的 MD5 校验和、修改时间发生了变化(因为改了配置,这是正常的)
校验输出字段含义:
| 位 | 含义 | 测试内容 |
|---|---|---|
| S | Size | 文件大小变化 |
| M | Mode | 权限或文件类型变化 |
| 5 | MD5 | MD5 校验和不同 |
| D | Device | 设备号不同 |
| L | Link | 符号链接路径变化 |
| U | User | 属主变化 |
| G | Group | 属组变化 |
| T | Time | 修改时间变化 |
| P | caPabilities | 能力集变化 |
| c | config | 标记为配置文件 |
正常情况:配置文件(标记
c)通常会被修改,校验差异是预期的。如果/usr/bin/下的二进制文件出现5(MD5 变化),可能是被恶意替换或系统受损。
数据库损坏时,需要重建:
展开代码# 备份旧数据库 cp -a /var/lib/rpm /var/lib/rpm.bak # 重建数据库 rpm --rebuilddb # 或者 rpmdb --rebuilddb
重建过程:读取 /var/lib/rpm/Packages 并重建索引文件,如有损坏则尝试修复。重建后建议执行 rpm -qa 验证。
RPM 的依赖关系是一张有向图。当你安装 php 时,RPM 会检查:
RPM 只负责"检查",不负责"解决"。 它只会告诉你缺少什么,然后你自己去找对应的 RPM 包手动安装。如果依赖链很长,你可能会陷入"A 依赖 B,B 依赖 C,C 又依赖 A 的老版本"这样的死循环——这就是臭名昭著的"依赖地狱"。
手动解决依赖的思路:
yum search 或访问 mirror 站点)。rpm -ivh A.rpm B.rpm C.rpm 一次性同时安装多个包。现实是:生产环境中几乎没有人用 RPM 手动解决复杂依赖,这就是 YUM 存在的意义。
| 故障现象 | 原因 | 解决方法 |
|---|---|---|
rpm: error: cannot open Packages database | 数据库损坏或正在被占用 | 检查 /var/lib/rpm 权限,杀掉残留的 rpm 进程后执行 rpm --rebuilddb |
package already installed | 重复安装 | 先 rpm -e 卸载旧版,或加 --force 覆盖 |
error: Failed dependencies | 缺少依赖 | 逐个安装缺失的依赖包,或改用 yum 安装 |
file /path from install conflicts with file from package | 文件冲突(两个包安装了同一路径文件) | 确认哪个包需要该文件,卸载冲突包或用 --replacefiles |
public key not available | 缺少 GPG 公钥 | rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-* |
rpm -qf /some/file 无结果 | 文件不是通过 RPM 安装的(手工编译或直接复制的) | 正常现象,说明该文件不在 RPM 管控范围内 |
| 维度 | RPM(二进制包) | SRPM(源码包) |
|---|---|---|
| 包内容 | 已编译好的二进制程序 + 配置文件 + 元数据 | 源代码 + 编译脚本(spec 文件)+ 补丁 |
| 后缀名 | .rpm | .src.rpm |
| 安装方式 | 直接 rpm -ivh | 需先编译成 .rpm 再安装 |
| 能否跨平台 | 不能,针对特定架构编译(x86_64 包不能在 ARM 上用) | 可以,在目标平台上重新编译 |
| 是否可修改 | 不可修改程序逻辑 | 可以修改源码后再编译打包 |
| 适用场景 | 日常软件部署 | 定制功能、审计源码、适配特殊架构 |
展开代码nginx-1.24.0-1.el7.src.rpm
命名结构与 RPM 基本一致,唯一的区别是架构位变为 src,表示这是一个源码包。
SRPM 默认存放路径:安装后源码解压到 ~/rpmbuild/SOURCES/,spec 文件存放在 ~/rpmbuild/SPECS/。
编译 SRPM 需要一个完整的 C/C++ 编译工具链:
展开代码# CentOS 7/8/9 编译环境一键安装 yum groupinstall -y "Development Tools" # 或手动安装核心组件 yum install -y rpm-build gcc gcc-c++ make automake autoconf \ kernel-devel openssl-devel pcre-devel zlib-devel
核心组件:
rpmbuild 命令和宏定义,是构建 RPM 的核心工具。.h 和 .so)。展开代码# ============ 第一步:安装 SRPM 包(解压源码和 spec 文件) ============ rpm -ivh nginx-1.24.0-1.el7.src.rpm # 注意:这里不会"安装软件",只是把源码解压到 ~/rpmbuild/SOURCES/, # 把 spec 文件放到 ~/rpmbuild/SPECS/ # 查看解压后的文件 ls -la ~/rpmbuild/SOURCES/ ls -la ~/rpmbuild/SPECS/nginx.spec # ============ 第二步:编译并打包成二进制 RPM ============ cd ~/rpmbuild/SPECS/ rpmbuild -ba nginx.spec # -b: build # -a: all,同时生成二进制 RPM 包和新的 SRPM 包 # 或 -bb: 仅生成二进制 RPM 包(常用) # ============ 第三步:查看生成的 RPM 包 ============ ls -la ~/rpmbuild/RPMS/x86_64/ # 输出:nginx-1.24.0-1.el7.x86_64.rpm # ============ 第四步:安装编译好的 RPM 包 ============ rpm -ivh ~/rpmbuild/RPMS/x86_64/nginx-1.24.0-1.el7.x86_64.rpm # 或 yum localinstall ~/rpmbuild/RPMS/x86_64/nginx-1.24.0-1.el7.x86_64.rpm # 推荐用 yum localinstall,可以自动解决依赖
整个流程总结:
展开代码SRPM 包 → rpm -ivh 解压 → rpmbuild 编译 → 生成 RPM 包 → yum/rpm 安装
默认的编译选项可能不满足需求。例如,你需要 Nginx 支持某个第三方模块,或者需要去掉某些功能以精简体积。
展开代码# 1. 查看 spec 文件中可配置的编译选项 vim ~/rpmbuild/SPECS/nginx.spec # 找到 %configure 或 %build 段落,这里面是 ./configure 的参数 # 2. 修改 spec 文件,添加自定义参数 # 例如,在 %build 段落中修改 ./configure 行: # ./configure \\ # --prefix=/usr/share/nginx \\ # --with-http_ssl_module \\ # --with-http_v2_module \\ # --with-http_gzip_static_module \\ # --add-module=/path/to/your/third-party-module # 新增第三方模块 # 3. 重新编译 rpmbuild -ba nginx.spec
修改源码再打包:
展开代码# 1. 先正常编译一次 rpmbuild -bp nginx.spec # -p: prepare,只解压和打补丁,不编译 # 2. 进入源码目录修改 cd ~/rpmbuild/BUILD/nginx-1.24.0/ vim src/core/nginx.c # 修改源码 # 3. 重新打包 rpmbuild -ba nginx.spec
| 场景 | 说明 |
|---|---|
| 定制编译参数 | 需要启用或禁用某些功能模块 |
| 源码安全审计 | 关键系统组件需要审查源代码 |
| 跨架构适配 | 在 ARM 服务器上编译原本只提供 x86_64 的软件 |
| 内核模块编译 | 某些内核驱动需要针对当前内核版本编译 |
| 学习研究 | 查看 spec 文件学习 RPM 打包规范 |
缺点:
YUM(Yellowdog Updater Modified) 的出现就是为了解决 RPM 的依赖地狱。它的核心原理:
repodata/ 目录,包含所有包的索引、依赖关系、文件列表等元信息。yum install nginx 时,YUM 会解析 nginx 的依赖树,自动找到所有需要的底层包(如 openssl-libs、pcre、zlib),一并下载安装。/var/cache/yum/,后续操作直接读缓存,速度大幅提升。YUM 与 RPM 的关系:YUM 是 RPM 的上层封装,底层安装卸载仍然调用 RPM,但增加了自动依赖解决和仓库管理能力。
CentOS 8/9 变化:CentOS 8 开始,yum 命令实际上是 dnf 的软链接。DNF(Dandified YUM)是 YUM 的下一代实现,改进了依赖解析算法和性能,但命令语法完全向下兼容。
/etc/yum.conf展开代码[main] cachedir=/var/cache/yum/$basearch/$releasever # 缓存目录 keepcache=0 # 安装后是否保留 RPM 包缓存(0=删除,1=保留) debuglevel=2 # 调试级别(0-10) logfile=/var/log/yum.log # YUM 操作日志 exactarch=1 # 是否严格匹配架构(1=是) obsoletes=1 # 是否处理废弃包 gpgcheck=1 # 是否检查 GPG 签名(生产必须为 1) plugins=1 # 是否启用插件
/etc/yum.repos.d/*.repo每个 .repo 文件定义一个或多个仓库。以下是一个标准 repo 文件的字段:
展开代码[base] # 仓库ID,唯一标识,方括号内 name=CentOS-$releasever - Base # 仓库名称,给人看的描述 baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ # 或使用 mirrorlist mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os enabled=1 # 是否启用:1=启用,0=禁用 gpgcheck=1 # 是否检查 GPG 签名 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 # GPG 公钥路径 priority=1 # 优先级(需安装 yum-plugin-priorities),数字越小越优先
常用 YUM 变量:
$releasever:系统主版本号(7、8、9)$basearch:基础架构(x86_64、aarch64)$arch:完整架构字符串CentOS 官方仓库已足够日常使用,只需替换为国内镜像源以加速下载:
展开代码# CentOS 7:替换为阿里云镜像 curl -o /etc/yum.repos.d/CentOS-Base.repo \ http://mirrors.aliyun.com/repo/Centos-7.repo # CentOS 8/9:替换为阿里云镜像 curl -o /etc/yum.repos.d/CentOS-Base.repo \ http://mirrors.aliyun.com/repo/Centos-8.repo # CentOS 9 可能需要使用 Rocky Linux 或 AlmaLinux 的替代源
适用于没有外网或安全隔离的生产环境。
展开代码# ============ 第一步:在能上网的机器上下载完整 RPM 包 ============ # 使用 reposync 同步整个仓库 yum install -y yum-utils reposync -r base -p /data/repo/centos7/ # -r: 指定仓库ID # -p: 指定下载目录 # ============ 第二步:创建本地仓库元数据 ============ yum install -y createrepo createrepo /data/repo/centos7/ # ============ 第三步:把 /data/repo/ 目录拷贝到离线服务器(U盘或内网传输) ============ # ============ 第四步:在离线服务器上配置本地 repo 文件 ============ vim /etc/yum.repos.d/local.repo ini[local-base] name=Local CentOS Base baseurl=file:///data/repo/centos7/ enabled=1 gpgcheck=0 # 离线环境可暂时关闭 bash# 第五步:清缓存并测试 yum clean all yum makecache yum repolist
适合企业多台服务器共用同一软件源,节省带宽、统一版本管控。
展开代码# ============ 在仓库服务器上安装 Nginx 作为 HTTP 服务 ============ yum install -y nginx # 将前面 reposync 下载好的 RPM 包和 repodata 放到 Nginx 站点的目录下 cp -r /data/repo/centos7/ /usr/share/nginx/html/repo/ # 启动 Nginx systemctl start nginx # ============ 客户端服务器配置 ============ vim /etc/yum.repos.d/internal.repo ini[internal-base] name=Internal CentOS Base baseurl=http://仓库服务器IP/repo/centos7/ enabled=1 gpgcheck=0
展开代码yum install nginx # 安装 yum install -y nginx # 自动确认,跳过交互 yum localinstall /path/to/local.rpm # 安装本地 RPM 包(自动处理依赖) yum remove nginx # 卸载软件包 yum autoremove # 自动卸载不再需要的依赖包
展开代码yum update nginx # 更新指定包 yum update # 更新所有包(生产环境慎用,需测试验证) yum check-update # 检查有哪些包可以更新(不实际更新) yum upgrade # 同 update,但会处理废弃包
展开代码yum list installed # 列出所有已安装的包 yum list available # 列出所有可安装的包 yum list updates # 列出所有可更新的包 yum search keyword # 按关键字搜索包名和描述 yum info nginx # 显示包的详细信息 yum provides /usr/bin/nginx # 反向查询:哪个包提供了指定的文件 yum deplist nginx # 查询包的依赖关系
展开代码yum grouplist # 列出所有组包 yum groupinstall "Development Tools" # 安装组包 yum groupremove "Development Tools" # 卸载组包
展开代码yum clean all # 清空所有缓存 yum makecache # 重新生成缓存 yum makecache fast # CentOS 7 可加 fast 参数加速
展开代码yum history # 查看所有 YUM 操作历史 yum history info 15 # 查看第15条操作的详细信息 yum history undo 15 # 撤销第15条操作(回滚!生产故障救命稻草) yum history redo 15 # 重新执行第15条操作
yum history undo是运维的后悔药:假如一次误执行yum update导致服务异常,用此命令可直接回滚到更新前的状态。
展开代码# 安装优先级插件 yum install -y yum-plugin-priorities # 编辑仓库配置,设置 priority 值(可选) # /etc/yum.repos.d/CentOS-Base.repo priority=1 # 官方源优先级最高 # /etc/yum.repos.d/epel.repo priority=10 # EPEL 源优先级低,同样包优先用官方源
离线环境推荐双线策略:
方案一:本地光盘/ISO 挂载
展开代码# 1. 上传 CentOS ISO 镜像,挂载 mount -o loop /path/to/CentOS-7.iso /mnt/cdrom # 2. 配置本地仓库 vim /etc/yum.repos.d/cdrom.repo [cdrom] name=Local CDROM baseurl=file:///mnt/cdrom enabled=1 gpgcheck=0 # 3. 验证 yum clean all && yum repolist
方案二:U盘拷贝 RPM 包 + 本地构建仓库(见 4.3.2 节)。
| 故障现象 | 原因 | 解决方法 |
|---|---|---|
Could not resolve host: mirror.centos.org | 网络不通或 DNS 故障 | ping 8.8.8.8 检查网络,检查 /etc/resolv.conf |
No package nginx available | 仓库中没有这个包,或仓库未启用 | yum repolist 确认仓库状态,可能需要安装 EPEL |
Cannot find a valid baseurl for repo: base | 网卡未启动或网络配置文件有误 | 启用网卡:ifup eth0,检查 repo 文件中的 baseurl |
Package does not match intended download | 缓存损坏 | yum clean all && yum makecache |
依赖冲突:Error: Package A conflicts with B | 不同仓库提供同名包导致版本冲突 | 安装优先级插件,或临时禁用冲突仓库 yum --disablerepo=xxx install |
Transaction check error 大量文件冲突 | 包系统中存在破碎安装 | 尝试 yum-complete-transaction 清理未完成事务,或 package-cleanup --cleandupes |
| GPG 签名检查失败 | 缺少公钥或下载的包被篡改 | rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-* |
YUM 诞生于 2003 年,到 CentOS 7 时代已经服役超过 15 年。随着软件生态的膨胀,YUM 的架构缺陷逐渐暴露:
| YUM 的痛点 | 具体表现 |
|---|---|
| 依赖解析慢 | 使用 Python 实现的依赖解析算法,复杂依赖树计算缓慢,CPU 单核跑满 |
| 内存占用大 | 加载完整仓库元数据时经常占用 1GB+ 内存 |
| API 设计差 | 代码耦合严重,第三方工具很难调用 YUM 的依赖解析能力 |
| 缺少模块化支持 | 无法处理同一软件的多个版本流(如 Python 3.8 / 3.9 / 3.11 并存) |
| 无人维护 | 上游社区停止开发,只剩安全补丁 |
DNF(Dandified YUM) 于 2015 年在 Fedora 22 中首次亮相当默认包管理器,RHEL 8 / CentOS 8 起正式取代 YUM。它的设计目标是:保留 YUM 的全部命令习惯,但在底层彻底重写。
我们来看一眼证据:
展开代码# CentOS 8/9 上验证 which yum # /usr/bin/yum ls -la /usr/bin/yum # lrwxrwxrwx. 1 root root 5 /usr/bin/yum -> dnf-3 # ↑ 本质就是指向 dnf 的软链接 yum --version # 4.7.0 # 显示的是 DNF 版本,不是 YUM
所以 CentOS 8/9 用户无论敲 yum 还是 dnf,执行的都是 DNF。YUM 命令得以保留,纯粹是出于兼容性考虑。
| 改进点 | YUM | DNF |
|---|---|---|
| 依赖解析引擎 | Python 实现,复杂度高时极慢 | 用 C 和 C++ 重写的 libsolv,使用 SAT 求解算法,速度提升数倍到数十倍 |
| 内存占用 | 全量加载元数据到内存 | 按需加载,内存占用显著降低 |
| API | 紧耦合,无正式公共 API | 提供 DNF API,可供其他工具调用 |
| 模块化 | 不支持 | 原生支持 Module Stream,同一软件多版本并存 |
| 事务回滚 | yum history undo | 同样支持且更快:dnf history rollback |
| Python 版本 | Python 2(已停止支持) | Python 3 |
一句话总结:DNF 是 YUM 的脱胎换骨版——命令习惯不变,五脏六腑全换了。
好消息:如果你已经熟悉 YUM,迁移到 DNF 几乎没有学习成本。下面是常用命令对照:
| 操作 | YUM 命令 | DNF 命令 | 说明 |
|---|---|---|---|
| 安装软件 | yum install pkg | dnf install pkg | 完全相同 |
| 卸载软件 | yum remove pkg | dnf remove pkg | 相同 |
| 升级某包 | yum update pkg | dnf upgrade pkg | DNF 推荐用 upgrade,但 update 也可用 |
| 全系统升级 | yum update | dnf upgrade | 相同 |
| 检查更新 | yum check-update | dnf check-update | 相同 |
| 搜索软件 | yum search keyword | dnf search keyword | 相同 |
| 查看包信息 | yum info pkg | dnf info pkg | 相同 |
| 列出已安装 | yum list installed | dnf list installed | 相同 |
| 查看仓库 | yum repolist | dnf repolist | 相同 |
| 清缓存 | yum clean all | dnf clean all | 相同 |
| 重建缓存 | yum makecache | dnf makecache | 相同 |
| 操作历史 | yum history | dnf history | 相同 |
| 回滚操作 | yum history undo ID | dnf history rollback ID | 命令不同,但效果一致 |
| 卸载孤立包 | yum autoremove | dnf autoremove | 相同 |
| 反向查文件 | yum provides /path | dnf provides /path | 相同 |
以下命令是 DNF 独有的,YUM 没有:
展开代码# 1. 查看包的依赖关系(更直观) dnf repoquery --requires nginx # 输出: # /bin/sh # libc.so.6(GLIBC_2.14)(64bit) # libcrypto.so.1.1()(64bit) # systemd # 相反方向:查看哪些包依赖 nginx dnf repoquery --whatrequires nginx # 2. 查看仓库中包含指定文件的包 dnf provides /usr/bin/passwd # 输出:passwd-0.80-4.el8.x86_64: An utility for setting or changing passwords # 3. 下载 RPM 包但不安装 dnf download nginx # 下载到当前目录:nginx-1.24.0-1.el8.x86_64.rpm # 4. 下载包及所有依赖(离线部署神器) dnf download --resolve --destdir=/tmp/nginx-offline/ nginx # --resolve:递归下载所有依赖 # --destdir:指定下载目录 # 5. 重新安装已损坏的包 dnf reinstall nginx # 适用场景:二进制文件被误删、配置文件丢失 # 6. 查看包的变动日志 dnf changelog nginx # 显示该包的版本更新历史 # 7. 管理软件组 dnf group list # 列出所有组 dnf group info "Development Tools" # 查看组详情
这是 DNF 相比 YUM 最大的功能升级,也是 CentOS 8/9 的核心变化之一。
传统仓库中,一个软件名只能对应一个版本。比如官方仓库只能提供一个版本的 Node.js、一个版本的 Python。如果你需要 Python 3.9 而仓库提供的是 3.11,就会很麻烦。
模块化(Modularity) 允许同一个软件同时提供多个版本流(Stream),用户可以选择安装哪个版本流。
| 概念 | 解释 | 类比 |
|---|---|---|
| Module(模块) | 一个软件的完整集合(包+依赖) | 一个产品线,如 "Python" |
| Stream(版本流) | 该软件的一个特定版本分支 | 产品的不同型号,如 "Python 3.8"、"Python 3.9" |
| Profile(配置集) | 该版本流的安装组合(最小/标准/全量) | 同型号的不同套餐,如 "最小安装"、"完整安装" |
展开代码# 1. 列出所有可用模块 dnf module list # 输出示例: # Name Stream Profiles Summary # nodejs 10 common, development Javascript runtime # nodejs 12 common, development Javascript runtime # nodejs 14 common, development Javascript runtime # python38 3.8 build, common Python 3.8 # python39 3.9 build, common Python 3.9 # python311 3.11 build, common Python 3.11 # 2. 查看模块详细信息 dnf module info nodejs # 显示该模块所有可用的 Stream 和 Profile # 3. 启用某个 Stream 并安装 # 要安装 Node.js 14 而不是默认的 18: dnf module enable nodejs:14 dnf install nodejs # 两步可以合为一步: dnf module install nodejs:14 # 4. 安装特定 Profile dnf module install nodejs:14/minimal # 只安装最小运行环境,不包含开发头文件 # 5. 切換已启用的 Stream(先重置再启用新版本) dnf module reset nodejs # 重置模块状态 dnf module enable nodejs:18 # 启用新版本流 dnf module install nodejs:18 # 安装 # 6. 查看当前启用的模块和 Stream dnf module list --enabled
展开代码# 场景:CentOS 8 默认 Python 3.11,但你的老项目需要 Python 3.8 # 传统做法:手动编译安装,污染系统环境 # 模块化做法:一条命令搞定 # 查看可用的 Python 模块 dnf module list | grep python # python38 3.8 [x] build, common Python 3.8 # python39 3.9 build, common Python 3.9 # 安装 Python 3.8 dnf module install python38:3.8 # 验证 python3.8 --version # Python 3.8.17 # 注意:python3.8 和系统的 python3 可以共存,互不冲突
模块化的价值:
展开代码# 1. 所有 YUM 命令照常使用(因为 yum 就是 dnf 的软链接) yum install nginx # ← 实际执行 dnf install nginx yum update # ← 实际执行 dnf upgrade # 2. YUM 插件不能直接在 DNF 中使用 # 原 YUM 插件(如 yum-plugin-priorities)在 DNF 中有等价物 # 优先级管理:DNF 原生支持,配置方式和 YUM 一致(见下文)
展开代码# 仓库配置文件路径不变 /etc/yum.repos.d/*.repo # DNF 完全兼容 YUM 的 repo 文件格式 # 但 DNF 多了一个变量 $stream(用于模块化仓库) # 标准仓库无需关心这个,零改动迁移
展开代码# YUM 缓存 /var/cache/yum/ # DNF 缓存(CentOS 8/9 实际使用的) /var/cache/dnf/ # 日常清理命令通用 dnf clean all
展开代码# YUM 回滚 yum history undo <ID> # DNF 回滚(推荐使用) dnf history rollback <ID> # 回滚到指定事务ID时的状态 dnf history undo <ID> # 撤销指定事务(DNF 也兼容此写法) # DNF 特有:回滚到某个时间点之前 dnf history rollback 15 # 回滚到事务15的状态
| 注意点 | 说明 |
|---|---|
| CentOS 7 没有 DNF | 默认只有 YUM,需手动安装 yum install dnf |
| CentOS 8/9 上 YUM 就是 DNF | 无需额外操作,习惯敲 yum 可以继续敲 |
| 插件不兼容 | 原有 YUM 第三方插件需更换为 DNF 版本 |
yum update vs dnf upgrade | DNF 推荐 upgrade,语义更明确 |
| 模块化仓库需要额外配置 | 如需使用模块化功能,仓库必须支持 module metadata |
| 故障现象 | 原因 | 解决方法 |
|---|---|---|
dnf: command not found(CentOS 7) | 未安装 DNF | yum install -y dnf |
Failed to synchronize cache for repo 'xxx' | 仓库元数据下载失败 | dnf clean all && dnf makecache |
Modular dependency problem | 模块依赖冲突 | dnf module reset <模块名> 后重新操作 |
Cannot find a valid baseurl | 网络问题或仓库地址失效 | 检查网络,更换可用镜像源 |
Error: Transaction check error | RPM 数据库存在冲突文件 | dnf reinstall 重装冲突包,或 rpm --rebuilddb |
No match for argument: pkgname | 包名拼写错误或未启用对应仓库模块 | dnf search pkgname 确认名称,检查 dnf module list |
Nothing to do | 已经是最新版,或包名不存在 | 确认包名正确,dnf list available 查看可安装列表 |
模块安装失败报 No default profile | 该模块未指定默认 Profile | 手动指定 Profile:dnf module install module:stream/profile |
展开代码# ============ /etc/dnf/dnf.conf(DNF 主配置文件) ============ vim /etc/dnf/dnf.conf ini[main] gpgcheck=1 installonly_limit=3 # 最多保留几个内核版本 clean_requirements_on_remove=True # 卸载时自动清理不再需要的依赖(推荐开启) best=True # 总是尝试安装最新版本(推荐) skip_if_unavailable=False # 仓库不可用时报错(可以设 True 跳过失效仓库) # 性能优化 fastestmirror=True # 启用最快镜像自动选择 max_parallel_downloads=10 # 并行下载数(默认3,可调高加快下载速度) bash# 应用配置后无需重启 dnf clean all && dnf makecache
展开代码# === DNF 专有命令 === dnf download pkg # 下载 RPM 包但不安装 dnf download --resolve pkg # 下载包及所有依赖 dnf reinstall pkg # 重新安装(修复损坏的包) dnf changelog pkg # 查看包版本变更历史 dnf history rollback ID # 回滚到指定事务状态 # === 模块化管理 === dnf module list # 列出所有可用模块 dnf module info pkg # 查看模块详情 dnf module install pkg:stream/profile # 安装指定版本流 dnf module enable pkg:stream # 启用指定版本流 dnf module reset pkg # 重置模块状态 dnf module list --enabled # 查看已启用的模块 # === 仓库查询 === dnf repoquery --requires pkg # 查询包依赖什么 dnf repoquery --whatrequires pkg # 查询谁依赖这个包 dnf provides /path/file # 反向查文件归属
| 维度 | RPM | SRPM | YUM/DNF |
|---|---|---|---|
| 包类型 | 二进制 RPM | 源码 RPM | 在线仓库(内含 RPM) |
| 安装方式 | rpm -ivh | rpmbuild 编译后 rpm -ivh | yum install |
| 依赖处理 | 手动解决 | 编译阶段需手动安装编译依赖 | 自动解决 |
| 操作难度 | 中等 | 高(需要编译知识) | 低(日常首选) |
| 灵活性 | 低 | 极高(可改源码、改编译参数) | 低 |
| 适用场景 | 离线安装单个简单包 | 定制功能、源码审计、跨架构适配 | 日常安装/更新/卸载 |
| 速度 | 快(本地操作) | 慢(编译耗时) | 快(依赖缓存) |
| 版本管控 | 手动 | 手动 | 仓库统一管理 |
生产环境选型建议:
展开代码YUM 在线安装 > YUM localinstall 本地RPM > RPM 手动安装 > SRPM 编译安装
原则:能用 YUM 不用 RPM,能用官方仓库不用第三方零散 RPM,能用二进制不用源码编译。
| 禁止操作 | 原因 |
|---|---|
rpm -e --nodeps 卸载核心系统包(如 glibc、kernel) | 系统直接崩溃,不可逆 |
生产环境 rpm --force 覆盖安装 | 可能破坏现有文件一致性,导致服务异常 |
| 混用不同版本的第三方 YUM 源(如同时启用 CentOS 7 和 CentOS 8 的源) | 依赖混乱、库版本冲突、系统无法启动 |
跳过 GPG 检查(gpgcheck=0)从不明来源安装包 | 可能安装植入后门的恶意软件 |
在生产服务器上直接 rpmbuild 编译大型软件 | 占用 CPU/内存影响业务,编译产生的临时文件难以清理 |
yum localinstall 安装。yum-versionlock 插件锁定关键服务版本,防止误升级。答案:
.rpm 格式软件包,但无法自动解决依赖。rpmbuild 编译后生成二进制 RPM 包再安装,适用于定制编译参数或源码审计。三者的从属关系:SRPM 编译生成 RPM → RPM 包存于仓库中 → YUM 调用 RPM 安装并自动解决依赖。
答案:
无法自动解决依赖的原因:RPM 工具的设计定位是对单个包文件进行操作,其依赖检查机制仅查询本地数据库,若发现缺失依赖则直接报错停止,不具备联网搜索、下载、递归解析依赖的功能。自动解决依赖需要引入仓库管理和依赖解析引擎——这正是 YUM/DNF 的职责。
答案:
/var/lib/rpm/ 下的数据库记录所有已安装软件包的信息,包括包名、版本、文件列表、依赖关系、校验和等。rpm -q 系列查询命令和安装卸载操作均依赖此数据库。rpm --rebuilddb 或 rpmdb --rebuilddb,系统会扫描现有 Packages 文件并重建索引。答案:
.src.rpm,内含源代码和 spec 编译脚本,不能直接安装,必须先编译成二进制 RPM 包。适用于需定制编译参数、源码安全审计、跨 CPU 架构编译等场景。.rpm,内含已编译的二进制程序及配置文件,可直接使用 rpm -ivh 安装。适用于常规软件部署和分发。答案:
rpmbuild 命令和 RPM 宏定义。openssl-devel、pcre-devel)。yum groupinstall "Development Tools" 快速安装基础编译工具组。答案:
repodata/ 元数据,构建完整的依赖关系图;当用户请求安装时,YUM 自动解析依赖树,从仓库下载所需的所有 RPM 包,最后调用 RPM 依次安装。答案:
[id]:仓库唯一标识,方括号内自定义。name:仓库描述名称,给人看的。baseurl:仓库的具体地址,支持 HTTP/HTTPS/FTP/file 协议。mirrorlist:镜像列表地址(与 baseurl 二选一)。enabled:是否启用该仓库(1=启用,0=禁用)。gpgcheck:是否校验 GPG 签名(1=是,生产环境必须开启)。gpgkey:GPG 公钥文件路径。priority:优先级(需安装 yum-plugin-priorities),数字越小越优先。答案:
reposync 下载完整仓库,用 createrepo 生成元数据,通过 U 盘或内网传输拷贝至离线服务器,配置 baseurl=file:///path 的本地 .repo 文件后使用 yum install。mount -o loop),配置 repo 指向挂载目录,即可作为本地仓库使用。答案: 排序:YUM 在线安装 > YUM localinstall 本地 RPM > RPM 手工安装 > SRPM 编译安装。
原因:YUM 能自动处理依赖、记录历史操作、验证 GPG 签名,安全性和可维护性最好;本地 RPM 安装次之;SRPM 编译安装耗时且引入编译环境复杂性,仅在需要定制功能或源码审计时使用。
答案:
ping),确认 repo 文件中 baseurl 可访问,尝试 yum clean all && yum makecache 重建缓存。若官方源失效,更换为国内镜像源(如阿里云)。yum --disablerepo=冲突仓库ID install 临时禁用某仓库,或安装 yum-plugin-priorities 设置优先级。若存在破损事务,执行 yum-complete-transaction 清理。rpm -ivh、rpm -Uvh、rpm -Fvh 三条命令差异?答案:
rpm -ivh:安装(install)。无论系统是否已存在该包,都会尝试安装。若已安装则报错。rpm -Uvh:升级(upgrade)。若系统中存在旧版本,则升级到新版本;若不存在,则全新安装。rpm -Fvh:刷新(freshen)。仅当系统中已存在旧版本时才升级;若系统未安装该包,则跳过不安装。答案:
/usr/bin/yum 是指向 dnf 的符号链接,实际执行的是 DNF。DNF 是 YUM 的下一代重写版本。yum install、yum update 等命令用法不变,配置文件路径和格式也保持一致。答案: DNF 是 YUM 的下一代重写版本。CentOS 8/9 中 /usr/bin/yum 是 DNF 的软链接,用户敲 yum 实际执行的是 DNF。
替换原因:
命令语法 95% 兼容,用户迁移几乎无成本。
答案: 模块化是 DNF 的一大核心功能,允许同一个软件包在仓库中提供多个版本流(Stream),用户可按需选择安装。
解决的痛点: 传统 YUM 仓库一个软件只能有一个版本。如果官方仓库 Node.js 升级到 18,而项目依赖 Node.js 14,就只能手动编译安装。 模块化允许 dnf module install nodejs:14 直接安装指定旧版本仓库中维护的版本,与系统其他软件互不冲突。
三个核心概念:
minimal 最小安装、common 标准安装)。dnf download --resolve 命令的作用与实际应用场景。答案: dnf download --resolve --destdir=目录 包名 会将指定软件包及其所有依赖的 RPM 文件下载到本地目录,但不执行安装。
应用场景:
rpm -ivh *.rpm 或搭建本地仓库安装。答案:
yum install dnf 安装;CentOS 8/9 无需操作。yum install 可继续使用。yum-plugin-priorities 改用 DNF 原生优先级配置)。/var/cache/yum/ vs /var/cache/dnf/)。dnf history rollback,语义明确。gpgcheck=1,开启 clean_requirements_on_remove=True 防止残留依赖。展开代码rpm -ivh package.rpm # 安装 rpm -e pkgname # 卸载 rpm -Uvh package.rpm # 升级 rpm -qa # 列出所有已安装包 rpm -qi pkgname # 查看包详情 rpm -ql pkgname # 查看包文件列表 rpm -qf /path/file # 查文件属于哪个包 rpm -qc pkgname # 查看包的配置文件 rpm -V pkgname # 校验包文件完整性 rpm --rebuilddb # 重建 RPM 数据库
展开代码rpm -ivh pkg.src.rpm # 解压源码和 spec rpmbuild -ba pkg.spec # 编译为 RPM rpmbuild -bb pkg.spec # 仅生成二进制 RPM(推荐)
展开代码yum install pkg # 安装 yum remove pkg # 卸载 yum update pkg # 更新 yum list installed # 已安装列表 yum search keyword # 搜索 yum info pkg # 查看详细信息 yum provides /path/file # 反向查包 yum history # 操作历史 yum history undo ID # 回滚操作 yum clean all # 清缓存 yum makecache # 重建缓存 yum repolist # 列出可用仓库
展开代码# RPM 数据库重建 rm -f /var/lib/rpm/__db.* rpm --rebuilddb # YUM 缓存清理 yum clean all && yum makecache # 查看 YUM 错误详情 tail -100 /var/log/yum.log # 验证单个包 rpm -V pkgname # 清理未完成事务 yum-complete-transaction package-cleanup --cleandupes
本文作者:zzz
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!