服务器升级踩坑后如何快速定位 AlmaLinux版本更新卡顿或冲突的常见原因与解决步骤
一、先别慌,看看磁盘和内存到底剩多少
上个月我们团队在生产环境升级 AlmaLinux 8.5 到 8.8 的时候,整整卡了三个小时不动,dnf update 的进度条像焊死了一样。一开始以为是网络问题,换了几条线路还是老样子,最后差点想把服务器重启。
后来运维的老张说了一句话:”你先看看资源够不够?”
我们一查,磁盘只剩不到 2%,内存也基本被占满。dnf 在升级过程中需要下载大量包并解压,磁盘空间不足时它会疯狂尝试清理缓存却清不掉,于是卡住了。
快速检查命令
# 查看磁盘空间,重点关注 / 和 /var 分区
df -h
# 查看内存使用情况
free -h
# 查看当前进程占用的 CPU 和内存
top -bn1 | head -30
如果 /var 分区满了,dnf 的缓存和临时文件根本没地方写,这时候你可以先清理一下:
# 清理 dnf 缓存
sudo dnf clean all
# 清理系统日志(如果日志文件过大)
sudo journalctl --vacuum-size=100M
# 删除旧的 kernel 保留最新两个
sudo package-cleanup --oldkernels --count=2
清理完后再跑 dnf update,你会发现速度快了不止一倍。
二、网络问题——别忽视 repo 源的速度
国内服务器升级 AlmaLinux 最常见的坑就是 repo 源选错了。AlmaLinux 官方源在海外,直连的话下载速度可能只有几十 KB/s,看起来像是在更新,其实一直在超时重试。
怎么判断是不是网络问题
# 查看当前配置的 repo 源
dnf repolist -v
# 手动测试某个 repo 的下载速度
time curl -o /dev/null https://repo.almalinux.org/almalinux/8.8/BaseOS/x86_64/os/repodata/repomd.xml
如果 time 命令执行下来超过 10 秒,基本可以确定是网络延迟问题。
换成国内镜像源
# 备份原有配置
sudo cp -r /etc/yum.repos.d /etc/yum.repos.d.bak
# 更换为阿里云镜像
sudo sed -i 's/mirrorlist=/#mirrorlist=/g' /etc/yum.repos.d/AlmaLinux*.repo
sudo sed -i 's|#baseurl=https://repo.almalinux.org/almalinux|baseurl=https://mirrors.aliyun.com/almalinux|g' /etc/yum.repos.d/AlmaLinux*.repo
# 或者使用清华源
sudo sed -i 's|#baseurl=https://repo.almalinux.org/almalinux|baseurl=https://mirrors.tuna.tsinghua.edu.cn/almalinux|g' /etc/yum.repos.d/AlmaLinux*.repo
# 清理缓存并重新生成
sudo dnf clean all
sudo dnf makecache
换成国内源之后,下载速度基本能跑到几 MB/s,升级过程顺畅很多。
三、依赖冲突——这是最容易踩的雷
dnf 的依赖解析机制比 yum 智能很多,但也不是万无一失。如果你之前手动装过一些 RPM 包,或者用了第三方 repo,依赖冲突的概率会大大增加。
常见冲突场景
# 查看有哪些依赖冲突
sudo dnf distro-sync --nogpgcheck 2>&1 | grep -i "problem"
# 查看具体哪些包有冲突
sudo dnf history list
有一次我们升级的时候,python3 相关的包一直报错,原因是有人之前手动装了一个 python39 的 RPM 包,和系统自带的 python3 产生了冲突。
解决依赖冲突的步骤
第一步:查看冲突详情
sudo dnf distro-sync --skip-broken -v 2>&1 | less
加上 --skip-broken 可以让 dnf 跳过无法解决的冲突包继续更新其他包,同时 -v 输出详细信息方便排查。
第二步:找出问题包
# 查看哪些包不在官方 repo 里
rpm -qa --queryformat='%{NAME} %{VENDOR}\n' | grep -v "AlmaLinux"
# 或者查看第三方源安装的包
dnf repoquery --disablerepo="*" --enablerepo="*" --qf '%{name} %{repo}' | grep -v "almalinux"
第三步:处理问题包
# 方案一:移除第三方包
sudo dnf remove <问题包名>
# 方案二:强制用系统自带的版本替换
sudo dnf install --exclude=<冲突包> <依赖包>
# 方案三:如果必须保留,考虑用 dnf versionlock 锁定版本
sudo dnf install dnf-plugin-versionlock
sudo dnf versionlock add <包名>
第四步:重新尝试升级
sudo dnf clean all
sudo dnf distro-sync
四、事务锁和残留进程——后台悄悄捣鬼
dnf 在执行过程中会在 /var/lib/dnf/system_state 生成一个状态文件,如果上一次更新被强行中断(比如 Ctrl+C 或者服务器断电),这个状态文件可能残留,导致新的更新被锁住。
检查是否有残留事务锁
# 查看 dnf 锁文件
ls -la /var/lib/dnf/system_state
ls -la /var/lib/rpm/.rpm.lock
# 查看是否有 dnf 或 yum 进程还在运行
ps aux | grep -E "dnf|yum" | grep -v grep
清理锁和状态文件
# 先杀进程(如果有的话)
sudo pkill -9 dnf
sudo pkill -9 yum
# 清理 dnf 状态文件
sudo rm -f /var/lib/dnf/system_state
# 清理 rpm 锁(谨慎操作,确保没有 dnf 进程在跑)
sudo rm -f /var/lib/rpm/.rpm.lock
# 重建 rpm 数据库(如果怀疑数据库损坏)
sudo rpm --rebuilddb
清理完之后重新运行更新命令就可以了。
五、GPG 签名验证失败——安全机制的”误伤”
AlmaLinux 8.6 之后强制要求 GPG 签名验证,如果你之前手动导入了过期的或者错误的 GPG key,升级时就会一直报错。
典型的错误信息
GPG key reception error (2): server certificate verification failed.
CAfile: /etc/pki/tls/certs/ca-bundle.crt CRLfile: none
解决步骤
第一步:更新系统的 CA 证书
sudo dnf install ca-certificates --refresh
第二步:重新导入 AlmaLinux 的 GPG key
# 删除旧的 key
sudo rm -f /etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux*
# 重新导入(从官方源获取)
sudo rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux
# 或者用国内镜像
sudo rpm --import https://mirrors.aliyun.com/almalinux/RPM-GPG-KEY-AlmaLinux
第三步:如果网络原因无法下载 key,可以临时关闭验证(仅用于排查)
# 注意:这只在排查问题时临时使用,不要长期使用
sudo dnf update --nogpgcheck
关闭 GPG 检查后如果更新能正常进行,说明确实是 key 的问题,之后再重新导入正确的 key 即可。
六、模块流冲突——被忽略的”隐藏炸弹”
AlmaLinux 8 引入了 dnf 模块(Module)机制,同一个软件包可能有多个”流(stream)”版本。如果模块流被锁定或变更,升级时会报一堆模块相关的错误。
检查模块状态
# 查看所有模块及其流状态
sudo dnf module list
# 查看锁定的模块
sudo dnf module list | grep "enabled"
# 查看具体某个模块的详情
sudo dnf module info <模块名>
常见的模块冲突和解决
# 重置问题模块到默认流(会移除当前非默认流安装的包)
sudo dnf module reset <模块名>
# 如果确认不需要某个模块,直接禁用
sudo dnf module disable <模块名>
# 重新启用默认流
sudo dnf module enable <模块名>
# 重新尝试升级
sudo dnf distro-sync
我们升级的时候遇到过 nodejs 模块冲突,原因是之前有人把 nodejs 锁定到了 12 版本流,但系统升级需要切换到 18 版本流。用上面的方法重置之后问题就解决了。
七、完整的升级检查清单
把上面所有的排查步骤整理成一个脚本,方便以后一键检查:
#!/bin/bash
# AlmaLinux 升级前健康检查脚本
echo "=== 磁盘空间检查 ==="
df -h / /var | awk 'NR==1 || $5+0 > 90 {print "⚠️ " $0}' || echo "✅ 磁盘空间正常"
echo ""
echo "=== 内存检查 ==="
free -h | awk '/Mem:/ {if($3/$2 > 0.9) print "⚠️ 内存使用率过高: "$3 "/" $2; else print "✅ 内存正常"}'
echo ""
echo "=== 残留进程检查 ==="
if pgrep -x dnf > /dev/null || pgrep -x yum > /dev/null; then
echo "⚠️ 检测到 dnf/yum 进程正在运行,请先结束后再升级"
ps aux | grep -E "dnf|yum" | grep -v grep
else
echo "✅ 无残留 dnf/yum 进程"
fi
echo ""
echo "=== 事务锁检查 ==="
if [ -f /var/lib/dnf/system_state ]; then
echo "⚠️ 发现 dnf 状态文件,可能存在残留锁"
ls -la /var/lib/dnf/system_state
else
echo "✅ 无残留事务锁"
fi
echo ""
echo "=== Repo 源检查 ==="
dnf repolist -v 2>/dev/null | grep -E "repo id|name" | head -20
echo ""
echo "=== 模块冲突检查 ==="
dnf module list 2>/dev/null | grep -i "error\|conflict\|incompatible" || echo "✅ 未发现明显模块冲突"
echo ""
echo "=== 推荐操作 ==="
echo "1. 如果磁盘不足,运行: sudo dnf clean all"
echo "2. 如果发现有残留锁,运行: sudo rm -f /var/lib/dnf/system_state"
echo "3. 如果网络慢,更换为国内镜像源"
echo "4. 检查完毕后运行: sudo dnf distro-sync"
把这段脚本保存为 /usr/local/bin/pre-update-check.sh,每次升级前执行一下:
sudo chmod +x /usr/local/bin/pre-update-check.sh
sudo pre-update-check.sh
八、真实案例复盘:一次完整的排查经历
说一个我们实际遇到的情况。服务器是阿里云的 ECS,跑的是 AlmaLinux 8.5,计划升级到 8.8。
现象:dnf update 执行后 CPU 飙到 100%,跑了 20 分钟没有任何输出,屏幕一直卡在 Downloading packages: 0%。
排查过程:
第一步:先按 Ctrl+C 中断,发现进程没杀死,再 kill -9 杀掉
第二步:df -h 看到 /var 分区用了 97%,磁盘空间告警
第三步:dnf clean all 清完缓存,腾出 8GB 空间
第四步:换成阿里云镜像源,重新 dnf makecache
第五步:再跑 dnf distro-sync,这次只用了 8 分钟就下载完了
第六步:安装过程中又报了一个 python3 模块冲突
第七步:dnf module reset python39 重置模块流,问题解决
第八步:升级成功完成,reboot 重启后验证版本
整个过程大概花了 40 分钟,从卡死到完全恢复。如果一开始就直接盲升,可能得更长时间才能发现问题。
九、升级后的验证步骤
升级完成别急着走,做几个基础验证确保系统没问题:
# 确认系统版本
cat /etc/almalinux-release
hostnamectl
# 检查是否有残留的未升级包
dnf list updates
# 检查内核是否正常
uname -r
rpm -qa kernel | sort -V | tail -2
# 检查系统日志有没有报错
journalctl -p err --since "1 hour ago" | tail -20
# 检查关键服务是否正常运行
systemctl is-active httpd php-fpm mysql
如果上面的命令都正常输出,那这次升级基本就是成功的。
最后说两句
服务器升级这件事,预防永远比修复简单。养成升级前备份、检查磁盘空间和依赖状态的习惯,能避开 80% 的坑。AlmaLinux 本身是个很稳定的系统,大部分更新卡顿的问题都是环境因素造成的,按上面的步骤一步步排查,基本都能定位到原因。
如果你遇到上面没有覆盖到的情况,可以把 dnf 的详细日志贴出来再分析:
sudo dnf update -v -v -v 2>&1 | tee /tmp/dnf-debug.log
日志保存在 /tmp/dnf-debug.log,不管是自己看还是求助社区,都有足够的信息可以参考。
