软件包版本锁定
在生产环境中,某些关键软件包需要固定在特定版本,避免自动更新导致兼容性问题。dnf-plugin-versionlock 提供了精确的版本锁定能力。
安装 versionlock 插件
Section titled “安装 versionlock 插件”dnf install -y dnf-plugin-versionlockdnf versionlock --help锁定指定包的当前版本
Section titled “锁定指定包的当前版本”dnf versionlock add nginx锁定特定版本号
Section titled “锁定特定版本号”dnf versionlock add nginx-1.20.1-14.el9锁定包含通配符的包
Section titled “锁定包含通配符的包”dnf versionlock add php-*查看所有锁定的包
Section titled “查看所有锁定的包”dnf versionlock list移除某个包的锁定
Section titled “移除某个包的锁定”dnf versionlock delete nginx清除所有锁定
Section titled “清除所有锁定”dnf versionlock clear场景一:锁定内核版本
Section titled “场景一:锁定内核版本”防止内核自动升级,适用于对硬件驱动兼容性有严格要求的环境。
dnf versionlock add kerneldnf versionlock add kernel-corednf versionlock add kernel-modulesdnf versionlock add kernel-modules-core验证锁定效果:
dnf check-update kernel# 即使有新版本也不会显示场景二:锁定数据库版本
Section titled “场景二:锁定数据库版本”生产数据库版本升级需要经过充分测试。
dnf versionlock add postgresql-serverdnf versionlock add postgresqldnf versionlock add postgresql-libsdnf versionlock add mariadb-serverdnf versionlock add mariadbdnf versionlock add mariadb-common场景三:锁定 Web 服务器版本
Section titled “场景三:锁定 Web 服务器版本”dnf versionlock add nginxdnf versionlock add nginx-mod-*dnf versionlock add httpddnf versionlock add httpd-corednf versionlock add mod_ssl场景四:锁定编程语言运行时
Section titled “场景四:锁定编程语言运行时”dnf versionlock add php php-cli php-common php-fpm php-mysqlnd php-pdodnf versionlock add nodejsdnf versionlock add npm锁定文件详解
Section titled “锁定文件详解”查看锁定文件
Section titled “查看锁定文件”cat /etc/dnf/plugins/versionlock.list手动编辑锁定文件
Section titled “手动编辑锁定文件”vi /etc/dnf/plugins/versionlock.list文件格式为每行一个 NEVRA(Name-Epoch:Version-Release.Arch)条目:
nginx-1:1.20.1-14.el9.x86_64备份和恢复锁定配置
Section titled “备份和恢复锁定配置”cp /etc/dnf/plugins/versionlock.list /root/versionlock-backup.listcp /root/versionlock-backup.list /etc/dnf/plugins/versionlock.list排除包(exclude 替代方案)
Section titled “排除包(exclude 替代方案)”除了 versionlock,还可以使用 exclude 阻止特定包更新。
在 dnf.conf 中全局排除
Section titled “在 dnf.conf 中全局排除”echo "exclude=kernel* kernel-core*" >> /etc/dnf/dnf.conf在特定仓库中排除
Section titled “在特定仓库中排除”dnf config-manager --save --setopt=baseos.exclude="kernel*"versionlock 与 exclude 的区别
Section titled “versionlock 与 exclude 的区别”| 特性 | versionlock | exclude |
|---|---|---|
| 锁定到特定版本 | 是 | 否(完全阻止) |
| 允许降级 | 否 | 否 |
| 包级别控制 | 精确到 NEVRA | 使用通配符 |
| 配置位置 | 独立文件 | dnf.conf 或 repo 文件 |
使用 dnf history undo 回滚
Section titled “使用 dnf history undo 回滚”当意外更新了锁定的包,或需要撤销某次操作时使用。
查看操作历史
Section titled “查看操作历史”dnf history list --reverse查看特定操作详情
Section titled “查看特定操作详情”dnf history info <事务ID>撤销指定操作
Section titled “撤销指定操作”dnf history undo <事务ID> -y重做某次操作
Section titled “重做某次操作”dnf history redo <事务ID> -y自动化管理脚本
Section titled “自动化管理脚本”批量锁定关键包
Section titled “批量锁定关键包”#!/bin/bash# 定义需要锁定的包列表LOCKED_PACKAGES=( "kernel" "kernel-core" "kernel-modules" "postgresql-server" "postgresql" "nginx" "php" "php-fpm" "php-cli")
for pkg in "${LOCKED_PACKAGES[@]}"; do echo "锁定: $pkg" dnf versionlock add "$pkg" 2>/dev/nulldone
echo "=== 当前锁定列表 ==="dnf versionlock list审计锁定状态
Section titled “审计锁定状态”#!/bin/bashecho "=== 版本锁定审计报告 ==="echo "日期: $(date)"echo ""
# 临时禁用 versionlock 检查更新echo "--- 被锁定阻止的更新 ---"dnf check-update --disableplugin=versionlock 2>/dev/null | \ grep -f <(dnf versionlock list 2>/dev/null | awk -F: '{print $1}' | sed 's/-[0-9].*//')
echo ""echo "--- 当前锁定的包 ---"dnf versionlock listEL 10 注意事项:versionlock 与 EL 9 相同
Section titled “EL 10 注意事项:versionlock 与 EL 9 相同”EL 10 仍然使用 DNF 4(4.20),versionlock 也仍由 dnf-plugin-versionlock 提供,用法和配置文件与 EL 9 一致:
| 项目 | EL 9 | EL 10 |
|---|---|---|
| 安装方式 | sudo dnf install dnf-plugin-versionlock | 相同 |
| 配置文件位置 | /etc/dnf/plugins/versionlock.list | 相同 |
| 文件格式 | 每行一个 NEVRA 字符串 | 相同 |
# 锁定包dnf versionlock add nginx
# 查看锁定列表dnf versionlock list
# 移除锁定dnf versionlock delete nginxcat /etc/dnf/plugins/versionlock.list升级后重新整理锁定规则
Section titled “升级后重新整理锁定规则”如果升级后发现某些锁定规则失效(旧 NEVRA 在 EL 10 中不存在),可以按包名重新锁定。思路是:升级前在 EL 9 上记录当前锁定了哪些包,升级后在 EL 10 上用 versionlock add 按包名重新锁定,这样能锁定到 EL 10 仓库中实际存在的版本。
由于 versionlock 列表里是 name-epoch:version-release.arch 这种 NEVRA glob,用 sed/awk 截断包名并不可靠(例如 java-17-openjdk、gcc-toolset-13-gcc 会被截错)。最稳妥的做法是先把原始列表存档供人工核对——通常锁定的包不多、名字你也清楚:
# 原样保存,便于升级后对照dnf versionlock list 2>/dev/null | tee /root/versionlock-el9.txt# 对照 /root/versionlock-el9.txt,把你确实需要锁定的包名列在这里# (示例,请按实际情况替换)for pkg in kernel nginx java-17-openjdk; do sudo dnf versionlock add "$pkg"done
sudo dnf versionlock list如果锁定的包很多、需要批量提取包名,用 rpm 按已安装包解析比 sed 截断可靠:
# 去掉每条记录末尾的 .arch glob 后,交给 rpm 反查规范包名dnf versionlock list 2>/dev/null | sed 's/\.\*$//' | while read -r nevra; do [ -n "$nevra" ] && rpm -q --qf '%{NAME}\n' "$nevra" 2>/dev/nulldone | sort -u