上周帮朋友排查一台机器上yum装不上VNC的问题整个终端从sudo yum install tigervnc-server开始到Error:收尾不到一分钟。朋友把报错截图发给我的时候问了一句这种异常记录到底该从哪儿看全我一直觉得这个问题比报错本身更重要。本文就围绕yum新系统上是dnf命令的异常记录展开讲清楚日志体系、排查方法和几个实用习惯适合正在被yum装包报错折磨的人也适合想真正理解Linux包管理器的运维同学。1. 为什么说看报错不等于看记录一次VNC安装翻车现场1.1 屏幕上的报错只是结果完整经过都在日志里那个场景很典型。终端里敲下[yamiwifi-ra81-srv ~]$ sudo yum install tigervnc-server [sudo] password for ya:接着屏幕刷了一堆仓库metadata的进度条然后卡了几秒钟蹦出几行红色字。大多数人这时候的习惯是截图、复制最后三行然后去搜索引擎碰运气。但报错信息里藏的信息非常有限它只告诉你某个环节失败了并没有告诉你整个过程在哪一步开始异常的。比如Error: Cannot retrieve metalink for repository: epel. Please verify its path这种报错你甚至不知道它在下载元数据时就崩了还是依赖解析之后才崩的。而这恰恰是排查的关键。日志记录会告诉你完整的执行链路从读取哪个repo文件、访问哪个镜像、下载哪个rpm、校验哪把GPG key一路到rpm事务具体改写了哪些包。少了这层信息所有排查都是猜。1.2 排查前先想清楚一次yum安装到底要经过几道工序要会看记录先得知道yum执行一个安装命令时到底做了哪些事。拆开看大概是这么几步读取/etc/yum.conf和/etc/yum.repos.d/*.repo加载全局配置和所有仓库定义。加载或下载仓库的metadata也就是repomd.xml、primary数据库这类文件用于描述仓库里有哪些包、包的依赖是什么。做依赖解析。yum会把你要装的包、它依赖的库、依赖的依赖全部列出来做一个闭包计算检查版本冲突。下载rpm包到缓存目录。校验下载文件的完整性包括GPG签名校验。调用rpm库执行真实的事务把包写进系统更新rpmdb数据库。执行post-install脚本生成缓存打印最终结果。这七道工序里任何一步失败最终表现都是yum命令异常这几个字。但每一道工序留下的痕迹完全不一样分散在不同的日志、文件和目录里。所以看异常记录的第一步是先建立按工序找日志的思维而不是傻乎乎盯着终端滚动。1.3 执行yum命令时每一道工序分别留下哪些痕迹我把痕迹分为四类控制台输出默认写道stdout和stderr最直观但信息量最少且滚动后不可回溯。主程序日志/var/log/yum.log老yum和/var/log/dnf.log新dnf记录程序运行过程中repo加载、metadata刷新、依赖解决等阶段的细节。rpm事务日志/var/log/dnf.rpm.log记录每个rpm包从install、update到erase的过程。缓存目录/var/cache/yum/或/var/cache/dnf/下载一半的rpm、metadata缓存、未完成的临时文件都留在这里。记住这四个位置后面所有排查都是围绕它们展开的。下一节详细拆。2. yum的日志到底藏在哪从/var/log/yum.log到dnf history2.1 第一落脚点/var/log/yum.logCentOS 7和RHEL 7这套老系统上yum的主要日志在/var/log/yum.log。打开看内容其实非常简单没有复杂的堆栈就是一行一行的包动作记录Jan 20 14:32:01 Installed: tigervnc-server-1.8.0-23.el7.x86_64 Jan 20 14:32:01 Installed: tigervnc-server-module-1.8.0-23.el7.x86_64 Jan 20 14:32:05 Updated: tigervnc-license-1.8.0-23.el7.x86_64格式是时间 动作 包名。这里有个常见误区很多初学者打开这个文件发现里面没有ERROR、没有FATAL就以为日志没记录。其实yum.log记录的是包层面的结果而不是失败原因。它最关键的用途是核对时间线——失败发生在哪个交易里、装到哪个包时断掉的。排查时可以这么用# 看最近的包变更记录 tail -n 50 /var/log/yum.log # 按日期筛选 grep Jan 20 /var/log/yum.log # 只看异常时间段前后各20行 grep -n Jan 20 14:3 /var/log/yum.log如果系统里同时存在RHEL 8之后的dnf/var/log/yum.log可能压根不更新。这时候别慌张它的替代品在下一节。2.2 升级到dnf之后/var/log/dnf.log与dnf.rpm.logRHEL 8、CentOS 8、RockyLinux、AlmaLinux 以及openEuler、麒麟这类基于RPM的发行版其实都换了dnf作为后端终端里的yum命令只是dnf的兼容入口。日志也跟着变了主要有两个文件/var/log/dnf.logdnf主流程日志包含仓库加载、依赖解析、下载详细信息。可以说这是过程日志。/var/log/dnf.rpm.logrpm事务执行的具体日志内容风格和老yum.log很像一行一个包动作。看的时候优先看/var/log/dnf.log的末尾# 看完整执行过程的最后200行 sudo tail -n 200 /var/log/dnf.log # 查看某一时间段 sudo grep 2025-01-20 14:3 /var/log/dnf.logdnf.log里面每一行通常带时间戳、日志级别和模块名比老yum.log详细得多。失败时它会明确提示(init) Failed to synchronize cache for repo appstream这类信息非常直接。2.3 transaction概念与yum historyyum和dnf有一个被很多老运维忽视的强大机制历史事务记录。每次执行安装、升级、删除、回滚都会被分配一个transaction ID。可以用yum history或dnf history两者等价因为符号链接查看# 查看最近的历史事务 sudo yum history list # 查看最近10条方便定位最后一次失败 sudo yum history list --number 10 # 从旧到新排列 sudo yum history list --reverse输出大致长这样ID | 命令行 | 日期和时间 | 操作数 ---------------------------------------------------------------------- 12 | install tigervnc-server | 2025-01-20 14:32 | 5 11 | update -y | 2025-01-19 20:11 | 3 10 | install htop | 2025-01-18 09:02 | 1想看某一个事务到底动了哪些包用info子命令sudo yum history info 12输出里会有Return Code字段0表示成功非0表示异常。如果最近一次install异常但history里没有对应ID说明yum在事务还未创建之前就崩了问题大概率出在仓库加载或依赖解析阶段。这是非常有效的定位线索。2.4 原始材料/var/cache/yum与/var/cache/dnf下的缓存目录日志是叙述者缓存目录是物证。CentOS 7的缓存路径是/var/cache/yum/x86_64/7/每个repo对应一个子目录下载的rpm放在repo/packages/下面。到了dnf时代则是/var/cache/dnf/。我排查时特别喜欢看这个目录原因很朴素如果下载阶段中断目录里会留下.part文件或只有几KB大小的rpm文件。看到这种文件基本能断定是网络问题或磁盘空间问题。# 看缓存目录占了多少空间 sudo du -sh /var/cache/yum /var/cache/dnf # 看有没有下载一半的残包 sudo find /var/cache/yum /var/cache/dnf -name *.part -o -name *.tmp这些原始材料配合日志用能快速把问题圈定在下载阶段还是事务阶段。2.5 不同发行版的差异对照发行版实际后端主日志与rpm日志history命令CentOS 7 / RHEL 7yum/var/log/yum.logyum historyCentOS 8 / RHEL 8 / Rocky / AlmaLinuxdnf/var/log/dnf.log、/var/log/dnf.rpm.logyum history 或 dnf historyopenEuler / 麒麟 / UOSRPM系dnf/var/log/dnf.log、/var/log/dnf.rpm.logdnf history在这张表里值得注意的是CentOS 8yum命令虽然可用但日志默认写进dnf.log。很多从CentOS 7迁移过来的同学翻不到/var/log/yum.log的更新内容就开始怀疑日志被别人清了其实只是文件换了。3. yum异常日志里最常出现的几个元凶和对应关键字3.1 仓库源异常mirrorlist、repomd.xml、Could not resolve hostyum异常里出现频率最高的就是仓库源问题。日志里常见这些关键字Cannot find a valid baseurl for repo: base/$releasever/x86_64Failed to download metadata for repo appstreamCould not resolve host: mirrors.example.comCannot retrieve the metalink for repository: epel. Please verify its path这类问题通常出现在三个层面机器本身连不上外网、repo文件里写的镜像地址失效、系统版本升级后官方源下架。比如CentOS 8的官方源变动后经常爆出appstream仓库无法获取metadata的报错这个从日志时间线和仓库名称就能一眼定位。排查命令很直接# 验证仓库能否正常列出 sudo yum repolist -v # 看单个repo到底用的什么地址 sudo yum repolist -v | grep -A5 -i base # 检查DNS解析 getent hosts mirrors.aliyun.com如果配置了本地源比如把光盘挂载到/mnt/cdromrepo文件里写的是baseurlfile:///mnt/cdrom但挂载失败或路径写错日志里同样会出现Cannot find a valid baseurl。判断方法很简单先看/mnt/cdrom目录是否存在、有没有repodata目录再看yum报错的仓库名称是不是对应的本地源repo。3.2 依赖冲突和包下载失败Error: Package、Cannot download依赖解析在yum里是一个独立阶段失败时日志会出现Error: Package: tigervnc-server-1.8.0-23.el7.x86_64 requires xorg-x11-fonts-Type1Error: Nothing to doCannot download Packages/xxx.rpm: All mirrors were already tried遇到这类问题先别急着加--skip-broken或者--nogpgcheck硬闯。正确顺序是# 确认包到底有没有 yum list available tigervnc-server # 看完整依赖 yum deplist tigervnc-server # 查看包的所有可用版本 yum --showduplicates list tigervnc-server很多时候下载失败并不是慢而是源里根本没有这个包。比如CentOS 7的base源里没有VNC必须启用epel源epel源没启用或者地址失效日志就会显示下载失败。到了这一步需要看yum search的结果和实际repo状态而不是反复执行同一个安装命令。另外有一点要注意下载失败日志会包含HTTP响应码和镜像列表。(28, Connection timed out)说明镜像连接超时(6, Could not resolve host)说明DNS没解析。这些括号里的数字就是curl错误码非常有用。3.3 GPG签名校验与rpmdb损坏GPG校验失败时日志里通常有这两行之一Public key for xxx-1.0-1.el7.x86_64.rpm is not installedThe GPG keys listed for the repository are not installed yet正确的处理方式是导入对应repo的GPG公钥而不是直接关校验# 导入CentOS官方key按系统版本对应 rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 # 导入epel的key rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7--nogpgcheck可以临时跳过校验但只建议在测试环境里用生产环境长期关闭等于把仓库的包完整性防线拆了。还有一类更隐蔽的问题出现在rpm数据库层叫rpmdb损坏。日志里出现rpmdb: Thread died in Berkeley DB library、db5 error(-30973) from dbenv-open: DB_VERSION_MISMATCH时修复思路不是重新yum install而是重建数据库# 建议先备份 mkdir -p /var/lib/rpm-backup cd /var/lib/rpm tar czvf /var/lib/rpm-backup/rpmdb_$(date %F).tar.gz * # 清掉锁文件并重建 rm -f /var/lib/rpm/__db.* rpm --rebuilddb这类问题在CentOS 7老机器上比较多见尤其是磁盘损坏或非正常关机之后。注意它不会在dnf.log里留下明显记录更像一个底层损坏的哑弹等下次任何rpm操作时突然爆炸。3.4 锁和磁盘Another app is currently holding the yum lock、No space left on device并发执行yum是很多人踩过的坑。日志里出现Another app is currently holding the yum lock; waiting for it to exit...说明有另一个yum/dnf进程还在跑锁文件写在/var/run/yum.pid。处理方式# 先看有没有进程真在跑 ps aux | grep -E yum|dnf | grep -v grep # 确认没有进程后再清理残留pid sudo rm -f /var/run/yum.pid这里的关键是先看进程再删pid文件很多人一看到锁就直接rm结果并发进程还在跑把数据库弄坏了。要记住锁文件存在的意义就是防止多个事务同时操作rpmdb。磁盘空间问题在日志里的表现更多样下载阶段会看到No space left on devicerpm事务阶段也可能因为tmp目录空间不足失败。排查时既看空间也看inodedf -h df -i缓存目录/var/cache/yum或/var/cache/dnf是重点对象积年累月的metadata和rpm包可能占好几个GB。yum clean all是最常用的回收手段。3.5 一张排查对照表日志关键字大概率原因先看哪里常用处理Cannot find a valid baseurl源地址失效/网络不通/etc/yum.repos.d/、DNS换源、检查网络Failed to download metadata for repo官方源下架或改名dnf.log时间戳、repo文件切换vault/镜像源Error: Package: xxx requires yyy依赖缺少或源不全yum deplist启用epel等补充源All mirrors were already tried包下载中断/镜像失效缓存目录.part文件换源、重试Public key ... is not installedGPG公钥缺失rpm导入日志rpm --importrpmdb: Thread died / DB_VERSION_MISMATCHrpm数据库损坏/var/lib/rpm备份后rpm --rebuilddbholding the yum lock并发yum进程ps aux、/var/run/yum.pid等进程或清理pidNo space left on device磁盘或inode不足df -h、df -i清缓存、扩分区这张表是我自己排查时的速查底稿适合保存下来。4. 完整排查实录从yum install tigervnc-server的报错到根因4.1 采集第一手记录重定向与实时跟踪日志回到开头那个场面现在我重新演示一遍完整排查。首先再次执行安装时不要裸跑要主动留痕。我会这么干cd /tmp sudo yum install -y tigervnc-server 21 | tee /tmp/yum_vnc_install.log21把标准错误合并到标准输出tee把输出同时落到文件里。这样即使终端滚动过去、ssh断开日志也都在。同时开一个独立终端实时盯rpm事务日志sudo tail -f /var/log/dnf.rpm.log看着rpm日志滚动能直观感知到底有没有进入事务阶段。这一步非常有效因为它把程序在想什么和实际写了什么分开了。4.2 用yum history定位最后一次失败的transaction失败之后第一件事不是翻安装日志而是查historysudo yum history list --number 5假设输出显示ID | 命令行 | 日期和时间 | 操作数 ---------------------------------------------------------------------- 15 | install tigervnc-server | 2025-01-20 14:32 | 0注意操作数是0这基本可以判断yum在依赖解析或下载阶段就中止了还没来得及创建rpm事务。如果想确认事务内部情况用sudo yum history info 15查看输出里的Return Code。如果history里根本没有ID说明连事务都建立不起来问题直接指向仓库加载或依赖解析阶段。这一步就把排查范围缩小了很多。4.3 顺着yum.log的时间线核对装到哪一步断了再去看rpm事务日志grep Jan 20 14:3 /var/log/dnf.rpm.log如果这个时间段里一行包动作都没有说明rpm事务压根没启动。如果出现了两三条安装记录然后断了说明rpm事务写了一半这种多半是磁盘空间或post-install脚本出错。正常情况下一个成功的tigervnc-server安装会把server、module、license等好几个包全部写入。这个时间线对照法是我觉得最有通用价值的技巧。日志可以没有错误等级但时间一旦对上故障阶段就跑不掉。4.4 定位元凶缓存metadata过期还是源不可达回到控制台日志假设这次报错是Error: Cannot retrieve the metalink for repository: epel. Please verify its path这说明epel源的metalink关联信息拉取失败。不是包的问题不是依赖的问题是仓库metadata拉不下来。于是按顺序执行# 看看当前仓库状态 sudo yum repolist -v # 确认dns解析 getent hosts mirrors.aliyun.com # 验证实际访问 curl -I https://mirrors.aliyun.com/epel/6/x86_64/如果DNS解析正常、curl也能返回HTTP 200那多半是缓存里的metadata损坏了或reposync的缓存索引过期。继续往下处理。4.5 处理与验证清理缓存、更新源信息、重新安装清缓存更新源是一个经典组合拳sudo yum clean all sudo yum makecache sudo yum install -y tigervnc-servermakecache会重新拉取所有已启用源的metadata。注意如果当前系统是CentOS 8且官方源已经下架这一步可能仍然失败需要先把repo文件里的baseurl切到可用的vault或国内镜像再makecache。改动repo文件后可以用yum repolist验证仓库菜单是否正常列出了预期数量和源ID。安装成功后验证# history里新增一条成功记录 sudo yum history list --number 3 # 包确实落盘 rpm -qa | grep tigervnc # 如果想快速冒烟测试服务是否可拉起 sudo systemctl start vncserver:1整个验证闭环走完才算异常真正解决。4.6 复盘思路异常记录怎么用每次排查完我都会把这次记录的链路记成笔记沉淀成自己的排查清单。一个合格的yum异常排查流程最终应该是这样先跑yum history list确认有没有transaction以及它的Return Code。再按报错时间点查dnf.rpm.log或yum.log判断是事务前还是事务中断。结合缓存目录和repo状态把问题归类到源、网络、依赖、GPG、磁盘、锁这六类里。修复后跑一次最小化验证安装再用history确认返回码归零。这套思路看下来会发现其实大部分工作根本不是盯着报错文字猜而是在不同记录之间做时间线和状态交叉验证。5. 养成看记录的好习惯几个压箱底的实用技巧5.1 把yum日志常驻监控我现在有个习惯安装大型软件包或批量更新时会单独开一个终端窗口跑tail -f /var/log/dnf.rpm.log让rpm事务实时滚动在眼前。一旦失败我可以立刻往回翻看到最后一个成功写入的包是哪个这个信息能省掉一半排查时间。同样地主进程日志也会同步看sudo tail -f /var/log/dnf.log可以给常用命令做点手脚比如shell里加别名alias yuylogsudo tail -f /var/log/dnf.rpm.log alias dnfysudo dnf install -y这样脑子不用记两遍命令操作路径就顺很多。5.2 提升调试级别debuglevel和-v -d默认yum日志能提供的信息有限需要在异常时段临时调高调试级别。老yum在/etc/yum.conf里通过debuglevel控制输出详略默认是2可以临时改到6甚至9让每一次repo加载、请求镜像、依赖比较的过程都落到日志里。dnf体系下命令行可以直接加参数# 更详细的输出 sudo dnf -v install tigervnc-server # debug模式 sudo dnf -d 9 install tigervnc-server但记住一个原则调试级别是临时手段不是长期配置。一直开着9级日志几轮更新下来/var/log/dnf.log会变得非常巨大反而干扰后续排查。5.3 保留下载缓存keepcache1yum默认不保留下载的rpm包装完就没失败时已经下载的包也被清掉。对慢网络环境非常不友好。在/etc/yum.conf里把keepcache1改上之后所有下载成功的rpm包都会留在缓存目录里。这样即使事务失败重跑安装时很多包直接命中本地缓存不用重新下载。配合手动下载也很方便sudo yumdownloader --destdir/tmp/vnc-rpms tigervnc-server这个命令只下载不安装可以拿rpm包去离线环境手动安装。缓存目录带来的空间占用问题用前面du -sh /var/cache/dnf定期看一眼就行心里有数就不慌。5.4 把history变成自己的审计清单yum history的价值比大多数人想象的大。它合理记录了每次事务的时间、命令行、操作内容和结果是一个现成的变更审计表。我会在重要变更前后各跑一次# 变更前记录当前最大ID sudo yum history list --number 1 # 变更后看最新两条diff一下差异 sudo yum history list --number 4如果某次异常后系统状态变得奇怪比如某个服务起不来、某个库版本不对用yum history info 某ID慢慢翻能还原出是哪个事务引入的哪个包。这就是所谓的可追溯性。在脚本化批量部署时批量操作后用history批量核对也比一台台rpm -qa高效得多。5.5 我个人的排查顺序与体会这套东西用了很久之后我自己的操作顺序固定成了三连先yum history list --number 3看有没有事务记录再tail -n 100 /var/log/dnf.rpm.log看rpm层面到底动没动最后df -h确认磁盘不是帮凶。三条命令基本能在30秒内把问题定位到仓库源/依赖解析/磁盘锁这三个大类里。之后再针对性扩展查证准确率很高。在异常记录这件事上我越来越觉得时间线比错误码更值钱。错误码只是某一瞬间的状态快照时间线却能把整个失败过程串起来。以后遇到yum命令异常建议先别急着搜报错原文老老实实把history和日志的时间线捋一遍往往答案就已经在里面了。