跳转到内容

软件包版本锁定

在生产环境中,某些关键软件包需要固定在特定版本,避免自动更新导致兼容性问题。dnf-plugin-versionlock 提供了精确的版本锁定能力。

安装 dnf versionlock 插件
dnf install -y dnf-plugin-versionlock
确认插件已安装
dnf versionlock --help
锁定当前已安装版本
dnf versionlock add nginx
锁定到精确版本
dnf versionlock add nginx-1.20.1-14.el9
锁定所有 php 相关包
dnf versionlock add php-*
列出当前所有版本锁定
dnf versionlock list
解除指定包的版本锁定
dnf versionlock delete nginx
移除全部版本锁定
dnf versionlock clear

防止内核自动升级,适用于对硬件驱动兼容性有严格要求的环境。

锁定当前内核版本
dnf versionlock add kernel
dnf versionlock add kernel-core
dnf versionlock add kernel-modules
dnf versionlock add kernel-modules-core

验证锁定效果:

确认内核已被锁定
dnf check-update kernel
# 即使有新版本也不会显示

生产数据库版本升级需要经过充分测试。

锁定 PostgreSQL 版本
dnf versionlock add postgresql-server
dnf versionlock add postgresql
dnf versionlock add postgresql-libs
锁定 MySQL/MariaDB 版本
dnf versionlock add mariadb-server
dnf versionlock add mariadb
dnf versionlock add mariadb-common
锁定 Nginx 及其模块
dnf versionlock add nginx
dnf versionlock add nginx-mod-*
锁定 Apache 版本
dnf versionlock add httpd
dnf versionlock add httpd-core
dnf versionlock add mod_ssl
锁定 PHP 及扩展
dnf versionlock add php php-cli php-common php-fpm php-mysqlnd php-pdo
锁定 Node.js 版本
dnf versionlock add nodejs
dnf versionlock add npm
查看 versionlock 配置文件
cat /etc/dnf/plugins/versionlock.list
直接编辑锁定列表
vi /etc/dnf/plugins/versionlock.list

文件格式为每行一个 NEVRA(Name-Epoch:Version-Release.Arch)条目:

nginx-1:1.20.1-14.el9.x86_64
备份 versionlock 配置
cp /etc/dnf/plugins/versionlock.list /root/versionlock-backup.list
恢复 versionlock 配置
cp /root/versionlock-backup.list /etc/dnf/plugins/versionlock.list

除了 versionlock,还可以使用 exclude 阻止特定包更新。

全局排除内核更新
echo "exclude=kernel* kernel-core*" >> /etc/dnf/dnf.conf
在 BaseOS 仓库中排除特定包
dnf config-manager --save --setopt=baseos.exclude="kernel*"
特性versionlockexclude
锁定到特定版本否(完全阻止)
允许降级
包级别控制精确到 NEVRA使用通配符
配置位置独立文件dnf.conf 或 repo 文件

当意外更新了锁定的包,或需要撤销某次操作时使用。

列出最近的 dnf 操作
dnf history list --reverse
查看某次操作安装/更新了哪些包
dnf history info <事务ID>
撤销某次更新操作
dnf history undo <事务ID> -y
重新执行某次被撤销的操作
dnf history redo <事务ID> -y
批量锁定生产环境关键包
#!/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/null
done
echo "=== 当前锁定列表 ==="
dnf versionlock list
检查锁定包是否有可用更新
#!/bin/bash
echo "=== 版本锁定审计报告 ==="
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 list

EL 10 注意事项:versionlock 与 EL 9 相同

Section titled “EL 10 注意事项:versionlock 与 EL 9 相同”

EL 10 仍然使用 DNF 4(4.20),versionlock 也仍由 dnf-plugin-versionlock 提供,用法和配置文件与 EL 9 一致:

项目EL 9EL 10
安装方式sudo dnf install dnf-plugin-versionlock相同
配置文件位置/etc/dnf/plugins/versionlock.list相同
文件格式每行一个 NEVRA 字符串相同
versionlock 基本用法
# 锁定包
dnf versionlock add nginx
# 查看锁定列表
dnf versionlock list
# 移除锁定
dnf versionlock delete nginx
查看 versionlock 配置文件
cat /etc/dnf/plugins/versionlock.list

如果升级后发现某些锁定规则失效(旧 NEVRA 在 EL 10 中不存在),可以按包名重新锁定。思路是:升级前在 EL 9 上记录当前锁定了哪些包,升级后在 EL 10 上用 versionlock add 按包名重新锁定,这样能锁定到 EL 10 仓库中实际存在的版本。

由于 versionlock 列表里是 name-epoch:version-release.arch 这种 NEVRA glob,用 sed/awk 截断包名并不可靠(例如 java-17-openjdkgcc-toolset-13-gcc 会被截错)。最稳妥的做法是先把原始列表存档供人工核对——通常锁定的包不多、名字你也清楚:

EL 9:升级前导出锁定记录(原样存档)
# 原样保存,便于升级后对照
dnf versionlock list 2>/dev/null | tee /root/versionlock-el9.txt
EL 10:升级后按包名重新锁定
# 对照 /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 截断可靠:

可选:用 rpm 可靠地解析包名
# 去掉每条记录末尾的 .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/null
done | sort -u