本文完整阅读约需 11 分钟,如时间较长请考虑收藏后慢慢阅读~

为了保证Linux的安全性和稳定性,我们经常需要对安装的软件进行更新。但如果某些更新与当前环境存在兼容性问题(最典型的例子是内核更新与虚拟机Hypervisor的兼容性),我们应该怎么做呢?在CentOS/Fedora/RHEL中(后文以CentOS为例),大部分用户可能会直接修改仓库配置文件,或者执行yum update --exclude=xxx,但这两种方法都不够直观,操作也比较繁琐。本文将为读者介绍一种使用yum/dnf的versionlock插件避免特定软件被更新的方法。

问题描述

由于手头的服务器众多,我租用了一台来自Time4VPS的存储型服务器(安装了CentOS 7)给其他服务器提供备份。

但当我尝试执行yum update升级所有自带软件后,却发现firewalld怎么也无法启动。使用journalctl -u firewalld查看错误日志,发现如下错误信息:

modprobe: ERROR: could not insert 'nf_conntrack': Function not implemented
modprobe: ERROR: Error running install command for nf_conntrack
modprobe: ERROR: could not insert 'nf_conntrack': Operation not permitted

问题分析

从以上错误信息我们可以了解,firewalld因为找不到nf_conntrack模块而无法启动。nf_conntrack是NetFilter所使用的内核模块之一,用于跟踪连接状态。

但这台服务器基于OpenVZ(一种基于容器化的虚拟化技术,可以看做Docker/LXC的前身),内核是与宿主机共享的,我无法自行安装该内核模块。

由于更新前的firewalld运行正常,因此我决定使用yum history undo功能,对所有更新进行回滚。如果不了解yum事务机制的读者,可以查看这篇文档

回滚后重新启动firewalld,发现不再出现报错。但这时候问题出现了:我不可能因为这一个不兼容的应用程序而放弃所有的更新,有没有办法更新除firewalld以外的其他软件呢?

问题解决

使用exclude参数

实际上yum提供了非常多的方法来解决这一问题。

首先我们可以在更新时配置exclude参数,如下所示:

yum update --exclude="firewalld*"

但这一方法存在几个问题:
1. 如果某次更新时忘记携带exclude参数,那我们不想更新的软件又会被误更新
2. 如果有很多不希望更新的软件(比如我希望iptables和kernel也不要被更新),命令会变得冗长,不便操作

使用配置文件

为了解决这两个问题,我们可以通过修改软件仓库的配置文件来实现同样的功能。

这里以CentOS-Base仓库为例,我们修改/etc/yum.repos.d/CentOS-Base.repo文件,然后在[updates]下面增加exclude="firewalld"配置。

接下来我们保存该配置,并执行yum makecache重载缓存,这时候再直接执行yum update,就不会自动更新firewalld了。

这一方法尽管解决了上一方法的两个问题,却又带入了新的问题:如果我们希望过滤的软件存在于多个仓库,就必须分别在不同的仓库配置文件中进行配置。此外部分仓库会在更新时修改自己的配置文件,也有可能会覆盖我们的配置。

那么有没有更集中、更优雅、更灵活的方案呢?答案是有的。

使用versionlock插件

虽然本文以yum为例,但其实versionlock插件同时存在于yum和dnf包管理器中,使用方法也是类似的。下文将继续以yum为例,如果读者更习惯使用dnf,可以查看这篇文档

versionlock是一个yum/dnf的插件,顾名思义用于锁定软件版本,禁止其被升级或降级。

该插件的安装方法非常简单:

yum install yum-plugin-versionlock

使用方法同样简单:

# 建立版本更新『黑名单』
yum versionlock add [package-wildcard]        

# 建立版本更新『白名单』
yum versionlock exclude [package-wildcard] 

 # 列出当前配置
yum versionlock list [package-wildcard]        

# 删除某项配置
yum versionlock delete [package-wildcard]    

# 清除所有配置
yum versionlock clear [package-wildcard]     

这里的[package-wildcard]是软件包名,推荐使用通配符如kernel*firewalld*避免相关的devellibsdocs包被更新。

在启用versionlock后,我们会在使用yum时看到Excluding 3 updates due to versionlock (use "yum versionlock status" to show them)这样的提示,说明当前有三个软件被应用了versionlock。这时候我们就可以使用yum versionlock status或者yum versionlock list来查看被应用的软件列表:

Loaded plugins: versionlock
0:firewalld-filesystem-0.6.3-2.el7_7.4.*
0:python-firewall-0.6.3-2.el7_7.4.*
0:firewalld-0.6.3-2.el7_7.4.*
versionlock status done

这样我们就可以简单省心并集中的对软件更新策略进行管理,避免不想更新的软件被误更新。