LabHub
学习 学习路径 课程

RHEL 系管理

dnf 与 apt 不同的地方

在 LabHub 中继续学习

一句话总结

dnf 最关键的不同之处在于:每次安装都会被记录为事务,并且可以撤销。apt 没有与之对应的功能。

概念图: 每次安装都会被记录为事务,并且可以撤销 · 记录 · 撤销操作的命令 · 不过,它的局限也很明确。

为什么需要理解这一点

这是从 Ubuntu 转到 RHEL 系列系统的人最先感到意外的地方。

dnf history                    # 지금까지의 모든 트랜잭션 목록
dnf history info 42            # 42번 트랜잭션에서 무엇이 바뀌었나
dnf history undo 42            # 42번을 되돌린다
dnf history rollback 41        # 41번 시점의 상태로 되돌린다

apt 的 /var/log/apt/history.log 里虽然有记录,却没有用于撤销操作的命令。这一差异会改变运维方式。在 RHEL 系列系统上,可以“先安装试试,不合适再撤销”。

不过,它的局限也很明确。 如果仓库中已经没有旧版软件包,降级就会失败。而且 Red Hat 明确表示,不支持降级系统软件包(selinux、selinux-policy、kernel、glibc,以及依赖 glibc 的 gcc 等)。回滚并不是万能的。

它是如何工作的

命令对照表

操作 apt dnf
更新索引 apt-get update (自动完成,需要时运行 dnf makecache
安装 apt-get install X dnf install X
删除 apt-get remove X dnf remove X
搜索 apt-cache search X dnf search X
查看信息 apt-cache show X dnf info X
文件→软件包 dpkg -S /path dnf provides /path(包括未安装的软件包)
已安装文件列表 dpkg -L X rpm -ql X
升级 apt-get upgrade dnf upgrade
锁定版本 apt-mark hold dnf versionlock add
回滚 没有 dnf history undo

dnf provides 尤其强大。 apt 的 dpkg -S 只能查找已经安装的文件,而 dnf provides检索仓库元数据,连尚未安装的软件包也能找到

dnf provides '*/nginx.conf'
dnf provides 'libnl-3.so.200()(64bit)'

第二个示例非常重要。在 RPM 中,依赖项的单位不是软件包名称,而是能力(capability)。共享库的 soname、文件路径,甚至符号版本都可以成为依赖目标。

dnf repoquery --requires httpd
dnf repoquery --requires --resolve --recursive httpd | sort -u | wc -l

--requires 表示所需的能力,--resolve 把该能力替换为提供它的软件包,而 --recursive 则继续递归查找。制作隔离网络导入清单时,它们是核心工具。

仓库文件

# /etc/yum.repos.d/labhub-local.repo
[labhub-local]
name=LabHub local (snapshot 2026-08-20)
baseurl=file:///srv/repo/labhub
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-labhub
metadata_expire=-1

理解每个键的默认值很重要。

如果在仓库显示名称中写明快照日期,六个月后只需查看 dnf repolist -v 的一行输出,就能知道该服务器安装的是哪个时间点的内容。

缓存

隔离网络中最常见的报障是“软件包已经放进仓库,却还是看不到”。原因通常只有下面两个之一。

# 저장소 쪽: 메타데이터를 다시 만들었는가 (이걸 빼먹는 경우가 정말 많다)
createrepo_c --update /srv/repo/labhub
# 클라이언트 쪽: 캐시를 만료 표시 (가장 가벼움)
dnf clean expire-cache
# 그래도 안 되면
dnf clean metadata
# 최후의 수단
dnf clean all
dnf makecache

各操作的定义如下:expire-cache 只把元数据标记为过期,metadata 删除元数据,packages 删除缓存的软件包,而 all 删除全部缓存。

实际工作中会遇到的情况

dnf update --security 悄无声息地以“无事可做”结束。 仓库中没有安全公告(updateinfo)元数据时就会出现这种情况。createrepo_c 只能从 rpm 文件生成 primary、filelists 和 other,而公告信息并不存在于 rpm 内部。它不报错、什么也不做,恰恰是危险之处。 应养成使用 dnf updateinfo --summary 进行确认的习惯。

下一个实验要做什么

使用 dnf 检查仓库、安装软件包,通过 provides 反向追踪来源,再利用历史记录回滚并锁定版本。