RHEL服务器执行dnf update时,终端停在某一行长时间没有输出,这是运维中很常见的故障。有人会直接按Ctrl+C中断,结果下次运行dnf时提示事务被锁定;也有人会重启服务器,但重启后问题依旧。正确处理方式是先判断进程状态,再根据日志确定卡住的环节。下面从实际排查角度梳理一套可复用的流程。

用进程状态和日志快速判断卡点
当dnf update卡住时,先不要重复执行。打开另一个终端,查看当前dnf进程是否还在运行以及占用了多少CPU。命令如下:
ps aux | grep dnf top -p $(pgrep -f 'dnf update')
如果进程CPU占用接近100%,说明它可能正在做依赖解析或解包计算,此时应观察几分钟;如果CPU占用为0%,多半是在等待网络响应或锁资源。接着查看dnf日志,RHEL默认记录在/var/log/dnf.log,可以执行tail -f /var/log/dnf.log观察最新输出。日志中若反复出现Timeout、Cannot download等字样,说明网络或仓库源有问题;若出现waiting for lock,则是另一个进程占用了rpm数据库锁。
还有一种情况是dnf进程状态为D,即不可中断睡眠,通常与存储I/O有关。可以用ps -eo pid,stat,cmd | grep dnf查看,如果STAT列为D,需要检查磁盘是否响应缓慢,比如NFS挂载超时或本地磁盘出现坏道。
常见卡住原因与针对性处理
网络超时是最常见的卡住原因。RHEL默认仓库源可能速度慢或不可达,更新时需要下载大量元数据。如果一个仓库源长时间无响应,dnf会一直等待。可以先手动测试仓库源连通性:
curl -I http://mirror.ipipp.com/repodata/repomd.xml # 如果连接不上,修改/etc/yum.repos.d/下的仓库文件,更换镜像源
注意上述示例中的mirror.ipipp.com仅为演示地址,实际使用时替换为可用镜像。修改仓库文件后,执行dnf clean all清理缓存,再运行dnf makecache重新生成元数据。如果网络本身不稳定,可以在/etc/dnf/dnf.conf中增加超时与重试参数:
[main] timeout=30 retries=3 minrate=1k
第二个常见原因是rpm数据库被锁。当另一个yum或dnf进程未退出,或者异常中断后残留了锁文件,后续更新就会卡在等待锁的阶段。可以检查锁文件:
ls -l /var/run/dnf.pid /var/lib/rpm/.rpm.lock fuser /var/lib/rpm/.rpm.lock
确认没有其他进程占用后,可以删除残留锁文件再重试。但删除前务必用ps确认没有真正运行的dnf进程,否则会导致rpm数据库损坏。如果rpm数据库已经出现异常,比如执行rpm -qa报错,可以用rpm --rebuilddb重建数据库。该操作会重新生成索引,耗时取决于已安装包数量,通常在几分钟内完成。
磁盘空间不足也会导致更新卡住。当/var或根分区写满,dnf在下载包或解包时无法写入,会出现看似卡死的情况。用df -h检查各挂载点使用率,重点看/var/cache/dnf所在分区。如果空间不足,先清理旧缓存:dnf clean packages,或者删除/var/cache/dnf下的旧文件。还有一种情况是inode耗尽,虽然空间剩余但无法创建新文件,可以用df -i确认。
强制中断后的事务修复
如果已经按了Ctrl+C或者系统意外重启,dnf下次运行可能报Transaction check error或提示rpmdb: Lock table is out of available locks。这时需要先清理dnf的历史事务记录。执行dnf history查看最近事务ID,再用dnf history rollback <事务ID>回滚到更新前状态。回滚命令中的尖括号在实际使用时无需输入,直接写数字即可。
如果回滚失败,可以手动修复rpm数据库:先备份/var/lib/rpm目录,然后执行rpm --rebuilddb。再运行dnf check检查依赖关系,根据输出用dnf distro-sync同步已安装包到仓库版本。这个操作会重新下载所有不一致的包,耗时较长但能解决大部分事务残留问题。
还有一种极端情况是dnf自身被更新到一半,导致命令无法正常执行。此时可以下载对应版本的dnf rpm包,用rpm -Uvh --force强制覆盖安装,恢复后重新执行更新。
从配置和流程上避免再次卡住
更新前先检查仓库源可用性,是预防卡住最有效的方式。可以写一个简单的检查脚本,放在定时任务中定期验证各仓库返回状态。生产环境建议配置本地镜像或代理仓库,减少对公网仓库的直接依赖。对于大规模节点,搭建一个内部dnf缓存代理,例如使用nginx缓存repomd.xml和rpm包,能显著降低更新时的网络等待。
在/etc/dnf/dnf.conf中合理设置超时参数也很重要。timeout控制单次连接超时秒数,retries控制重试次数,minrate设置最低下载速率,低于该速率则中断连接。对于网络环境较差的服务器,建议设置timeout=60、retries=5,避免因瞬时抖动导致更新长时间挂起。同时开启keepcache=0让更新后自动清理下载包,减少磁盘占用。
定期维护rpm数据库同样不可忽视。每隔几个月执行一次rpm --rebuilddb可以清理索引碎片,提高包管理操作速度。执行前建议先备份/var/lib/rpm目录,避免意外导致数据库损坏。对于关键业务服务器,更新应安排在低峰期,并先在测试环境验证更新包兼容性,这样即使出现卡住也不会影响核心业务。

