你有没有遇到过这种情况:在 Linux 服务器上执行 yum install 或者 yum update,命令卡住不动、报一连串奇怪的依赖错误、甚至连 yum 自己都报段错误(Segmentation fault),而你翻遍了网上的帖子也不知道系统里到底发生了什么。
我早期的运维生涯有一大半时间都在跟 yum 相爱相杀。用得越多,我越是意识到一个关键问题:yum 命令本身几乎不会告诉你真正的原因,真正的原因全部藏在日志和系统记录里。谁的排查速度快,取决于谁更会看这些“异常记录”。
这篇文章我就把多年攒下来的 yum 异常记录查看方法、日志体系、排查思路和实操案例全部拆开讲一遍,希望能帮你少走几趟弯路。
1. yum 异常日志体系:先搞清楚日志都在哪
1.1 yum 自己写的日志:/var/log/yum.log
yum 从 CentOS 6 时代开始就有自己的日志文件,位置固定在 /var/log/yum.log。这个文件记录的是 yum 执行过程中的安装、更新、删除动作,格式类似这样:
Jun 10 10:23:45 Installed: tigervnc-server-1.13.1-9.el9.x86_64 Jun 10 10:25:02 Updated: kernel-5.14.0-362.13.1.el9_3.x86_64 Jun 10 10:26:18 Erased: telnet-0.17-87.el9.x86_64这个文件最重要的价值在于——它能还原你在某一天到底执行过哪些包操作。很多“yum 突然异常”的问题,根本原因就是某次安装时锁文件没释放,或者某个包被更新坏了,通过这个日志可以直接回推时间线。
不过有个坑需要注意:在 CentOS 8 / RHEL 8 之后的系统里,默认只有 dnf,不再自动生成 /var/log/yum.log。如果你装的是兼容包 yum(CentOS 8 自带一个指向 dnf 的 yum 软链),日志会写到 /var/log/dnf.log。所以排查前先确认系统版本和实际日志路径,别在 /var/log/yum.log 里翻半天,结果系统里压根没有这个文件。
1.2 dnf 的日志:/var/log/dnf.log 与 /var/log/dnf.librepo.log
有人说 CentOS 8 抛弃了 yum,其实只是把 yum 的底层实现换成了 dnf,然后把 yum 命令做成一个薄壳。dnf 自己有两套日志:
- /var/log/dnf.log:记录 dnf 的事务、安装、更新、错误信息,内容比 yum.log 详细得多
- /var/log/dnf.librepo.log:记录库(repo)下载相关日志,比如某个 rpm 包下载失败、镜像源超时
看 dnf 日志的时候我一般直接 grep 关键词,因为日志量非常大,一屏刷完很浪费眼神:
grep -E "ERROR|WARNING|failure|Fail" /var/log/dnf.log | tail -50注意:/var/log/dnf.log 并不是默认开启的,需要在 /etc/dnf/dnf.conf 的 [main] 字段下加上
logfile=/var/log/dnf.log才会持久化。如果没配过,dnf 默认把日志打到 journald 里,所以后边第六节讲的 journalctl 才是 dnf 日志的真正主战场。
1.3 系统层面的日志:/var/log/messages 与 journalct
yum 本身是 Python 写的,它在执行时会调用系统的 RPM 库、网络库、文件系统接口。如果执行过程中系统层面报错,比如磁盘 IO 错误、内存不足、Python 依赖损坏等,yum 往往不会写日志,而是把错误信息吞掉,只给你一个半截的提示。这时候就得去翻 /var/log/messages 或者用 journalctl 查看内核和系统服务的记录。
我遇到过一个很典型的案例:yum install 执行到一半就提示“段错误”。当时 yum.log 里什么也没有,但 journalctl 里赫然写了十几条 python3 进程 OOM(内存不足)的记录。所以,当 yum 异常时,只盯着 yum 自己的日志是不够的,系统日志同样关键。
2. 实时排查异常:journalctl 的正确用法
2.1 查看某一次 yum 执行的实时日志
journalctl 是 systemd 自带的日志工具,从 CentOS 7 起就成了标配。它记录 systemd 管理的所有服务的输出,包括命令行里手动执行的程序(前提是那条命令在 systemd 的会话中执行过)。想看 yum 或 dnf 的实时日志,这两个命令最常用:
# 查看今天 dnf/yum 相关日志(dnf 的进程名是 dnf,yum 兼容包也是调到 dnf) journalctl --since today | grep -E "yum|dnf" | tail -100 # 实时跟踪日志输出,另开一个终端窗口执行 yum 命令,方便现场定位 journalctl -f | grep -E "yum|dnf"第二条命令我强烈推荐。你在一个终端里跑 journalctl -f 跟着输出,另一个终端执行复现问题的 yum 操作,异常发生的那一刻,journald 里会非常清晰地记录下 dnf 到底在哪个环节出的错。
2.2 如何找到某次事务的精确日志
如果你执行的是 dnf install,那么 packagekitd 或 dnf 对应的可执行文件名会在 journald 里留下 _COMM 字段。针对某个特定命令的所有进程输出,可以用:
journalctl _COMM=dnf --since "2025-01-10 10:00:00" --until "2025-01-10 10:30:00"时间范围从你执行命令的前一两分钟开始算起,因为 dnf 启动时还要先加载插件和仓库缓存,真正干活的时间比命令行长很多。
2.3 用 journalctl 查看系统启动以来的所有 RPM 事务
有时候 yum 异常不是现在发生的,而是某个包在一个月前就被更坏了。这时候可以搜索 rpm 相关日志,把系统层和 rpm 层的事故记录下来:
journalctl | grep -i "rpm" | grep -E "error|fail|missing" | tail -50这个组合搜索能帮你发现很多 yum 层发现不了的底层隐患,比如某个 rpm 脚本let报错、某个文件被覆盖等。rpm 是 yum 的后端,yum 只是前端包装,很多“yum 异常”本质上是“rpm 事务异常”,后面第四节会细讲这个关系。
3. 打开 yum 的 debug 模式:让日志告诉你一切
3.1 debuglevel 参数:yum 日志详细程度的开关
yum 默认只记录安装、更新、删除这种级别的事件。想要更详细的过程信息,比如它到底访问了哪个镜像地址、连接哪个 IP、下载了哪个文件、失败在哪个阶段,就要调高 debug 级别。
编辑 /etc/yum.conf,在 [main] 段下加一行:
[main] debuglevel=6debuglevel 的取值范围是 0 到 10,默认值是 2。这个值越高,日志越详细。我在实际生产环境里通常只开到 4 或 5,因为调到 6 以上日志量极其恐怖,刷屏速度远比你看得快。真正紧要的排查窗口期,再开到 6,定位到问题之后马上调回 2,否则日志文件一天能撑爆几个 GB。
调完 debuglevel 之后重新执行 yum 命令,然后把输出重定向到文件里方便分析:
yum install -y tigervnc-server 2>&1 | tee /tmp/yum_debug_$(date +%F).log3.2 用 verbose 读心术分析调试日志
debuglevel 打开后,yum 会输出大量以Config time、Loading mirror speeds、Retrieving、Package、Transaction开头的行。信息量最大的几个关键节点:
Loading mirror speeds from cached hostfile:说明 yum 正在读取镜像源列表,如果卡在这一行之后,说明网络层或 DNS 解析出了问题Retrieving:正在从仓库下载软件包元数据(repomd.xml),如果反复重试,说明镜像源对应包索引不完整或版本不对Running transaction check:正在检查依赖关系,后续跟着的Error: Package或者Nothing provides就是依赖冲突的具体原因
我见过不少新人根本不看这些日志,靠猜去试错误提示。其实 yum 的 debug 日志已经把每个步骤都写得很清楚了,照着日志看,排查效率能翻倍。
3.3 更细粒度的 dnf debug 配置
如果你用的是 dnf 作为后端(CentOS 8+),也可以给 dnf 单独设置日志级别。在 /etc/dnf/dnf.conf 中加:
[main] debuglevel=6与 yum.conf 的设置是等效的。逻辑一样,详细程度分分钟能让你看到一次事务的完整调用链和下载链。
4. 深入 RPM 事务层:yum 异常的真正幕后
4.1 yum 与 rpm 的关系:前端和后端
在讲 rpm 层之前,必须先把 yum 和 rpm 的关系理清楚。rpm 是真正执行软件包安装、升级、删除的程序,它直接操作文件系统、写数据库(/var/lib/rpm)。yum/dnf 则是“包管理器管家”,它负责解析依赖、下载软件包、配置仓库,最后把批量执行事务的指令交给 rpm 来落地。
所以 yum 报错的最后一公里,绝大多数跑在 rpm 层。如果 rpm 层出问题,比如 rpm 数据库损坏、软件包脚本执行失败、文件被第三方覆盖,那 yum 层显示的只会是一串看不懂的依赖冲突或者事务中断。
4.2 查看 RPM 事务日志和数据库状态
要查看 rpm 层的事务历史,最直接的是看 rpm 数据库。rpm 把每个已安装包的信息保存在 /var/lib/rpm,如果这个目录损坏或 rpm 数据库版本不一致,yum 会直接崩溃。
首先确认 rpm 数据库是否健全:
rpm -qa | wc -l如果这条命令能正常返回包总数,说明 rpm 数据库基本可用。如果命令卡住、报错或返回为空,那么十有八九 rpm 数据库坏了,yum 也会跟着废掉。
检查 rpm 数据库目录大小和状态:
ls -lh /var/lib/rpm/ # 正常情况下至少应该有 Packages、Name、Basenames 等文件,单文件大小几 MB 到几十 MB4.3 用 rpm -Va 验证已安装文件的完整性
当你怀疑某个包的文件被改坏导致 yum 依赖校验失败时,可以用 rpm 自带的验证命令:
rpm -Va这条命令会把所有安装包的文件逐一比对校验和。如果输出里出现S(大小变化)、M(权限变化)、5(md5 校验失败)等标志,对应的文件就有问题了。例如:
S.5....T. /usr/lib64/libcurl.so.4.8.0出现这种记录,表示 libcurl 这个被 yum 依赖的核心库文件被改动过,此时 yum install 大概率会报错。处理方案是用 rpm 强制重装这个包:
rpm -ivh --force /var/cache/yum/.../libcurl-版本.rpm4.4 修复 rpm 数据库的常见操作
如果 rpm 数据库确实损坏,比较轻的修复手段是重建 rpm 数据库索引:
rpm --rebuilddb重建过程中会把 /var/lib/rpm 下的临时文件清理干净,并重建索引。如果重建没用,再考虑把损坏的 rpmdb 备份后清空,然后用 rpm -qa 重新扫描 /var/lib/rpm 目录下的所有旧文件来恢复。这些操作在生产环境里务必先备份目录:
cp -a /var/lib/rpm /var/lib/rpm.bak.$(date +%F)5. yum history 与事务历史:精准还原现场
5.1 用 yum history 查看历史事务
yum 本身也维护了一套事务历史,CentOS 7 及以下版本用 yum history 查看,CentOS 8+ 则用 dnf history。这套历史记录其实是从 rmpdb 或者后台数据库里整理出来的。
# 查看最近 50 次事务 yum history | head -50 # 查看某一次特定事务的详细信息,注意编号从 1 开始 yum history info 15输出里会显示这次事务的时间、操作命令、涉及的包、事务状态(成功/失败/中断)。这个信息在复盘问题时价值巨大——你能直接看到是哪次操作把环境弄坏的。
5.2 归档 yum history 的备份位置
yum history 的数据存放在 /var/lib/yum/history/ 目录(CentOS 7)或 /var/lib/dnf/history/ 目录(CentOS 8+),每个事务对应一个以 ID 命名的目录。如果这个目录被误删了,yum history 就会变成空的,但包依旧装得好好的。
如果在排查大量问题时发现 history 是空的,别慌,优先去看 /var/log/yum.log 或 dnf.log,这两个文件才是时间线的“硬证据”。
5.3 结合历史排查的实用思路
我通常的排查习惯是:
- 先
yum history | tail -20,确认最近有没有异常事务 - 再查看那个异常事务的 info,确认到底装了什么、卸载了什么
- 根据异常时间点,回到 yum.log 里找同时间段的安装记录
- 最后从前端(yum)推到后端(rpm),验证文件完整性
这套流程基本能覆盖大多数“莫名异常”的定位需求。
6. 实战排查:三个典型 yum 异常的日志定位实录
6.1 案例一:yum install 卡在 “Loading mirror speeds from cached hostfile”
现象:执行 yum install tigervnc-server,卡在这一行超过 5 分钟,无任何网络错误提示。
排查过程:
第一步,看 dnf/yum 实时日志:
journalctl -f | grep -E "yum|dnf"发现日志静止在 DNS 解析阶段。第二步,手动测试解析:
curl -I http://mirrors.aliyun.com/centos/ --connect-timeout 5能通,但很慢。第三步,查 /var/log/messages,发现网卡 eth0 有大量 RX errors 和丢包记录。结论是网络质量差导致的超时,yum 自己没有日志,但系统网卡层已经给出了信号。
处理:更换更快的镜像源,或者提升 yum 超时时间。在 /etc/yum.conf 里加:
timeout=120 retries=5把默认的 30 秒超时调大,网络环境差的时候效果立竿见影。
6.2 案例二:yum 报依赖冲突,但 rpm 层文件异常
现象:yum install nginx,报错:
Error: Package: nginx-1.20.1-10.el9.x86_64 requires: libssl.so.3()(64bit) Not found而系统里明明装了 openssl。
排查过程:
先rpm -qa openssl,发现 openssl 已经装了新版。再rpm -V openssl,发现文件校验失败。继续看 journalctl 里有没有 openssl 相关更新记录,终于看到一条某天dnf update openssl后文件校验失败的信息。最终原因:更新开头时网络中断,rpm 事务没有完整提交,导致部分文件缺失。
处理:用dnf reinstall openssl强制重装该包,然后rpm -Va复查,问题消失。
6.3 案例三:yum 提示 “Another app is currently holding the yum lock”
现象:
Another app is currently holding the yum lock; waiting for it to exit...排查过程:
先看是什么进程占用锁:
cat /var/run/yum.pid # 列出该进程信息 ps -ef | grep $(cat /var/run/yum.pid | awk '{print $1}')发现是一个卡死的 packagekitd 进程在后台自动更新。查 journalctl 确认它在跑什么任务,然后用kill -9干掉占锁进程,并在 /etc/yum/pluginconf.d/ 下禁用自动更新插件。
处理:
rm -f /var/run/yum.pid systemctl stop packagekit systemctl disable packagekit7. 常见 yum 异常速查对照表
我把多年遇到的 yum 异常整理成一个速查表,排查时直接对照,能大幅缩短定位时间:
| 异常现象 | 优先查看的日志/文件 | 常见根因 | 核心排查命令 |
|---|---|---|---|
| 安装卡在镜像源加载 | /var/log/dnf.log、journalctl 网络层记录 | DNS 慢、镜像源超时、镜像源缓存损坏 | curl 测速镜像源、journalctl -f |
| 依赖冲突但包已安装 | /var/log/yum.log、rpm -Va 输出 | rpm 数据库损坏、文件被覆盖、事务中断 | rpm -Va、rpm --rebuilddb |
| yum 锁占用 | /var/run/yum.pid | 残留进程、自动更新插件、packagekit 抢占 | ps 查 pid、kill 锁进程 |
| 段错误/Python traceback | journalctl 中的 OOM 记录、/var/log/messages | 内存耗尽、python 依赖损坏 | free -m 看内存、rpm -Va python3 |
| 仓库元数据下载失败 | /var/log/dnf.librepo.log、/var/log/messages | 镜像源地址失效、防火墙拦截、时间不同步 | curl -I 仓库 URL、date 看时间同步 |
| 事务中断后再次安装失败 | /var/log/yum.log 历史事务记录、rpmdb 事务残留 | 上次事务没有正确完成 | yum-complete-transaction、package-cleanup |
提示:上面所有排查命令里,第一条永远是“先确认时间同步”。NTP 时间不同步会让 yum 判定仓库元数据过期,导致大量奇怪的下载错误。我踩过不只一次,先看时间再看日志能省掉很多无用功。
8. 几个老手才知道的日志查看心得
最后分享几个平时文档里很少写的细节经验。
第一个心得是别开 debuglevel 到 10。这不是越详细越好,debuglevel=8 以上,yum 会连每个 socket 读了多少字节都打印出来,输出大到让人头皮发麻。真要深挖,6 已经足够了。
第二个心得是重定向日志要带时间戳。用2>&1 | tee /tmp/yum_debug.log的时候,配合script -q -c "yum install xxx" /tmp/yum_session.log还能把完整的交互式会话和时间戳一起录下来,复盘的时候能准确对齐每一步耗时。
第三个心得是日志不会说谎,但日志也可能缺失。当你在 /var/log/yum.log、/var/log/messages、journalctl 里都找不到线索时,先别怀疑日志工具出了问题,大概率是你自己当年的运维操作习惯埋下了隐患——比如手动编辑过 rpm 数据库、清过 /var/lib/rpm、删过历史事务目录。这种时候,破局思路是从业务影响反推:谁能动这个包?什么时候动的?当初有没有备份?顺着这个思路,多半能挖出真相。
我自己这几年配合 yum 异常排查做的最有用的一个习惯,是每次执行高危的 yum 操作之前先把系统关键状态快照下来:
# 操作前记录包列表、RPM 校验、yum history 快照 rpm -qa > /tmp/rpm.list.$(date +%F) rpm -Va > /tmp/rpm.verify.$(date +%F) yum history > /tmp/yum.history.$(date +%F)这个成本几乎为零的习惯,让后续任何一次“yum 异常记录”都变得有据可查。毕竟,排障最快的路径,永远不是现场抓包,而是对比变化。