Anolis OS内核实战:从查询版本到安全升级与回滚
2026/9/16 21:02:39 网站建设 项目流程

很多人一听到“内核升级”四个字,第一反应就是:这玩意儿能不动就不动,万一起不来就是事故。这种谨慎我完全理解,毕竟内核是整台操作系统的地基,地基出了问题,上面跑什么都是白搭。但现实情况是,我们经常不得不去动它——安全漏洞要补、新硬件要认、文件系统要支持新特性,甚至有些软件直接要求内核版本高于某个阈值才肯工作。我这边管理的一批Anolis龙蜥服务器,就多次面临过这种“不得不升”的局面。

Anolis OS作为国内主流的服务器操作系统发行版,和CentOS生态保持了高度兼容,很多朋友是从CentOS迁移过来的,装好之后第一件事就是问:怎么查内核版本?怎么升内核?怎么配新内核默认启动?这些问题看似零散,串起来其实是一条完整链路:先摸清现状,再配置源,然后装包,接着改引导,最后做验证。这篇文章我就按这条链路,把这几年在龙蜥上动内核的完整流程、踩过的坑、总结出的套路全部写出来,方便你照着操作。

1. 升级前的内核现状摸底:先搞清楚为什么动内核

1.1 一个反直觉的事实:升级内核不是更新软件包

很多人第一次在Anolis上执行dnf update,发现内核版本纹丝不动,就开始怀疑是不是源有问题。其实这是正常现象,因为绝大多数发行版的策略是:内核属于“独立更新”的软件包类别,普通update不会主动把内核从一个大版本拉到另一个大版本,这是怕系统自动升级内核后出现兼容性问题,影响正在运行的业务。

所以你在龙蜥上要做的第一件事,不是急着找新内核,而是先想清楚:我到底为什么升内核?我见过不少人是看到别人升了5.10自己也要升,最后升完发现业务依赖的某个内核模块没了,折腾半天又降回来。内核升级不是追求最新,而是追求“当前业务场景下最合适”。

1.2 查询当前内核版本的四种路径

升级前先把现状摸清楚。查询当前内核版本,我常用的有四种方式,各有侧重:

命令输出内容适用场景
uname -r当前运行内核的完整版本号最常用,确认“正在用的”内核
uname -a内核版本+主机名+架构+编译时间需要看编译信息时
hostnamectl内核版本、操作系统版本、架构一次性确认系统和内核
cat /proc/version内核版本+GCC版本+编译时间需要确认编译器信息时

我个人的习惯是uname -r配合cat /etc/os-release一起看,因为内核版本和系统版本是两回事。比如你现在跑的是4.19.132-anolis,只能说明内核是4.19这条线,不代表系统是某个具体版本。/etc/os-release里能看到PRETTY_NAME字段,那才是操作系统的具体版本信息。

uname -r cat /etc/os-release

还有一个容易被忽略的点:uname -r显示的是当前正在运行的内核,而不是机器上已经安装的内核。如果你之前升过内核但一直没重启,这里显示的还是老版本。要看你机器上一共装了哪些内核,需要用下面这条命令:

rpm -qa | grep -E '^kernel'

这条命令会列出所有和内核相关的安装包,包括kernelkernel-develkernel-headerskernel-tools等。其中不带后缀的kernel-版本号才是可引导的内核本体,有几个就说明你的GRUB菜单里应该有几个启动项。

1.3 判断“该不该升”的四个信号

不是任何时候都需要升级内核。结合这些年在龙蜥上处理过的实战场景,我认为出现下面四种信号之一,才真正到了该动手升内核的时候:

  1. 安全漏洞公告:社区或官方发布了针对当前内核版本的安全通告,涉及你正在使用的服务或内核模块。这种情况优先级最高,必须尽快升。
  2. 新硬件无法识别:新加了网卡、磁盘阵列卡、GPU等硬件,系统识别不到,或者识别到了但加载固件报错。通常是内核太老,缺少对应驱动。
  3. 应用对内核版本有硬性要求:某些数据库、虚拟化平台、容器运行时会在启动时检测内核版本,不满足就直接拒绝运行。
  4. 文件系统或内核特性需要新版本支持:比如要用上较新的Btrfs特性、io_uring高性能IO、或者某些TCP拥塞控制算法,这些往往需要较新内核才能完整支持。

如果以上信号一个都没出现,我的建议是:保持现状。内核升级有收益也有风险,没必要为了“新”而“新”。尤其是生产环境,稳定压倒一切。

2. 软件源是一切的起点:repo配置排查与可用版本确认

2.1 Anolis OS的yum源长什么样

在Anolis OS 8.x上,软件源是通过/etc/yum.repos.d/目录下的repo文件管理的。和CentOS 8类似,它会拆成多个仓库:

repo名称主要内容内核相关程度
AnolisOS-BaseOS基础软件包,包含内核、核心工具内核本体在这里
AnolisOS-AppStream应用程序和运行时关系不大
AnolisOS-PowerTools扩展包,部分编译依赖部分开发依赖包
AnolisOS-Extras额外组件关系不大
AnolisOS-Plus增强包部分驱动相关

升级内核主要依赖BaseOS仓库。所以我排查问题时的第一站,就是确认BaseOS仓库有没有被禁用或者地址配置错误。

查看当前所有启用的仓库,可以用:

dnf repolist

如果输出里没有看到BaseOS,或者状态是禁用状态,可以手动查看repo文件内容确认一下:

cat /etc/yum.repos.d/AnolisOS-BaseOS.repo

正常情况下的关键配置大概是这样的:

[AnolisOS-BaseOS] name=Anolis OS $releasever - BaseOS baseurl=http://mirrors.aliyun.com/anolis/$releasever/BaseOS/$basearch/os/ enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS

这里有个非常容易踩的坑:$releasever变量。如果你系统的releasever解析异常,镜像源地址就会拼错,导致明明配置没问题却显示404。排查时可以用下面这个命令看看变量实际解析成了什么:

dnf --releasever=8 repolist

如果加了--releasever=8之后仓库就正常了,说明是系统版本变量出了问题,需要检查/etc/dnf/vars/releasever文件是否存在或者内容是否正确。

2.2 源配置异常时的排查链路

遇到过好几次朋友发截图给我,说dnf makecache报错,一堆Mirror URL无法连接。这种问题90%都不是源本身挂了,而是环境或配置的问题。我自己在龙蜥上排查源故障,遵循的固定链路是:

  1. 先确认网络连通性:用curl -I直接测试镜像地址是否可访问。拿阿里云镜像举例:
curl -I http://mirrors.aliyun.com/anolis/8/BaseOS/x86_64/os/
  1. 确认DNS能解析:如果curl提示无法解析主机名,检查/etc/resolv.conf里的DNS配置。有些内网环境的机器DNS配置不对,但之前一直没暴露,直到需要联网安装软件包时才暴露出来。

  2. 确认能访问但dnf仍报错:这种情况通常是证书或gpgkey的问题。私人内网镜像、自建源经常有这种情况,解决办法是先把repo文件里的gpgcheck=1临时改成0验证一下。如果改成0就好了,说明是gpgkey路径配置错误或导入有问题。

  3. 清理缓存重试:这是最基础但也是最常被忽略的一步。有时候repo文件改了,但dnf还在用旧缓存:

dnf clean all dnf makecache

这条链路走完,90%的源故障都能定位到具体环节。剩下那10%,一般就是镜像源本身在同步或维护,换个时间再试就行。

2.3 查看源里到底有哪些内核版本可装

在确认源可用之后,下一步就是在源里搜索有哪些内核版本可供安装。这一步的关键命令是加--showduplicates参数:

dnf list available kernel --showduplicates

不加这个参数的话,dnf只显示一个“最新版本”,加了之后会把所有仓库里存在的不同版本全部列出来。这个细节很关键,因为有时候你并不想升到最新版,而是想升到某个特定修复版本,比如从5.10的早期版本升到某个中期版本,此时就必须靠这个参数把候选版本看清楚。

也可以加上--allowerasing预览依赖变化,但这个时候还没有真正安装,你也可以用下面这条命令来只做模拟,不做真实变更:

dnf install kernel-5.10.xxxx --assumeno

--assumeno选项会让dnf把解析好的依赖关系打印出来,然后自动回答“否”,从而不实际执行操作。我每次装内核前都会先跑一次这个命令,看看它会引入哪些新依赖、更新哪些旧包,心里有个底。

3. 正式安装内核:装对了版本才能少踩坑

3.1 用“安装”而不是“更新”的方式引入新内核

这是很多内核升级事故的根源所在。在Anolis上装内核,正确做法是用dnf install,而不是dnf update

dnf install kernel的行为是“在现有内核之外,再装一个新内核”。它不会动你当前正在运行的内核,而是让你机器上多出一个可选的启动项。这样即使新内核引导失败,重启时还能在GRUB菜单里选择旧内核进入系统,安全性大大提高。

dnf update kernel这类操作,在某些情况下会把旧内核替换掉或者做更多不可控的变更,操作风险明显更高。所以我强烈建议:升级内核永远用install,不用update

具体安装命令:

dnf install -y kernel

如果你已经通过--showduplicates选定了具体版本,也可以直接指定版本号安装:

dnf install -y kernel-5.10.190-2.5.an8.x86_64

安装过程中dnf会检查依赖关系,正常情况下会拉取内核本体、生成initramfs。这个initramfs是系统启动时加载驱动用的临时根文件系统,安装内核时它会被自动生成,不需要你手动执行dracut。但如果你发现安装完成后/boot/initramfs-版本号.img不存在,那就要留意了,说明安装过程可能出了问题。

3.2 开发包和头文件为什么必须一起装

只装kernel本体,对绝大多数纯运行环境是够的。但如果你的机器上要编译内核模块,比如安装某些第三方驱动、DKMS(Dynamic Kernel Module Support)管理的模块,那么kernel-develkernel-headers几乎是必须的。

这里要特别强调一个坑:这两个包必须是“对版本”的。也就是说,你机器上跑的是哪个版本的内核,就要装哪个版本的kernel-devel。如果版本对不上,去编译模块时大概率会报类似 “Kernel preparation unnecessary” 之类的问题,甚至直接告诉你找不到/lib/modules/版本号/build目录。

所以在安装内核的同时,我一般会把配套的devel和headers一起装上:

dnf install -y kernel kernel-devel kernel-headers

装完开发包后,可以用下面这个命令确认对应的构建目录确实存在:

ls /usr/src/kernels/

正常输出里会有一个以完整内核版本号命名的目录,比如:

/usr/src/kernels/5.10.190-2.5.an8.x86_64

每次重启之后,我都会习惯性地检查这个目录是否与uname -r的输出一致。如果发现不一致,赶紧找原因,因为这意味着你接下来想编译任何内核模块都会受阻。

3.3 安装完成后的即刻检查

安装结束后,不要着急重启。先花一分钟确认三件事情:

第一,检查/boot目录下的引导文件是否齐全:

ls /boot/

重点关注新版本对应的vmlinuz-版本号initramfs-版本号.imgSystem.map-版本号这三个文件是否存在。如果initramfs缺失,后面重启极大概率直接失败,进不了系统。

第二,确认内核启动项已经出现在GRUB配置里:

grubby --info=ALL | grep -E '^kernel|index'

输出里应该能看到新内核对应的kernel=/boot/vmlinuz-版本号条目,并且前面带有index=编号。

第三,确认一下/boot分区的剩余空间。如果/boot空间不足,比如只剩几十MB,dnf install过程中有可能报“No space left on device”,导致内核虽然下载了但无法写入。我自己就遇到过两次,都是因为旧内核堆太多没清理,新内核的 initramfs 又比较大(有些带完整驱动的能到300MB以上),结果卡在这一步:

df -h /boot

如果空间确实紧张,先把旧的、不再使用的内核清理掉(具体方法见第6章),再回来装新的。

4. 重启之后的新世界:切换默认内核是最后一道关卡

4.1 通过grubby精确切换默认内核

装好新内核后,系统并不会自动用新内核启动,除非你是从头安装系统时选的新内核。新内核装好后,默认启动项通常还是旧的那个。此时你想让新内核成为默认启动项,最推荐的工具是grubby,这也是RHEL系发行版里最主流的引导项管理工具。

查看当前默认内核:

grubby --default-kernel

这个命令直接输出当前默认启动项对应的内核完整路径,比如/boot/vmlinuz-4.19.132-1.an8.x86_64

把默认内核切换成新装的版本:

grubby --set-default=/boot/vmlinuz-5.10.190-2.5.an8.x86_64

执行完可以用grubby --default-kernel再确认一次,看看默认内核是不是已经变过来了。除了用完整路径,也可以用grubby --set-default-index配合之前grubby --info=ALL查到的index序号来设置,效果是一样的。

这里要注意一个细节:grubby --set-default修改的是GRUB默认启动项,但它内部操作的实际是/etc/default/grub以及已有的GRUB配置文件。在大多数RHEL系系统上,改完之后是即时生效的,不需要再手动执行grub2-mkconfig。不过有部分特殊环境(比如某些UEFI引导场景)可能需要额外手动生成配置,遇到的话看下面一节。

4.2 手动生成GRUB配置的方法

如果你用的是UEFI启动模式,或者执行完grubby --set-default之后发现重启并没有进入预期内核,那可能需要手动重新生成GRUB配置。

先判断系统是BIOS还是UEFI启动模式:

[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"

如果是BIOS启动,生成的配置文件路径一般是:

grub2-mkconfig -o /boot/grub2/grub.cfg

如果是UEFI启动,路径则可能是:

grub2-mkconfig -o /boot/efi/EFI/anolis/grub.cfg

不同版本、不同发行版的EFI分区挂载路径可能略有不同,最稳妥的办法是先用finddf -h找到EFI分区挂载在哪里,再确认grub.cfg的实际路径。

手动生成配置的操作本身很简单,但执行之后一定要检查输出里是否出现了新内核对应的菜单项:

grep -E 'menuentry' /boot/grub2/grub.cfg | grep 5.10

如果配置生成成功且包含新内核菜单项,那说明GRUB层面已经准备好了。

4.3 重启后的验证清单

切换完默认内核,接下来就是重启验证了。但重启不是随便敲个reboot就完事,我一般会在重启前后对个清单。

重启前:

  1. 检查是否有正在写入的重要数据,生产环境尽量在业务低峰期操作。
  2. sync强制刷新文件系统缓存。
  3. 确认无正在进行的软件包安装或其他事务性操作。

重启后优先执行的验证命令:

uname -r

这个输出是最直接的证据,证明你的系统当前「真正运行」的内核版本。如果输出的版本和你预期的一致,说明切换成功。如果还是旧版本,优先回顾上一步的GRUB配置是否正确。

接下来还要看一下系统这次的启动信息里有没有异常:

dmesg -T | grep -iE 'error|fail|warn'

-T选项会把时间戳转换成可读格式。这条命令只是初步过滤,输出里可能会有些无关紧要的WARN信息,重点看有没有跟“CPU”“内存”“块设备”相关的高危错误。真正出大问题的时候,dmesg里往往有大段红色报错和Call Trace(内核调用栈)。

再做一个系统层面的状态确认:

systemctl status

如果有一个或多个服务处于失败状态,别急着下结论,先逐一查看服务的日志。比较常见的情况是:某些服务在旧内核上依赖的某个模块名变了,在新内核里改名或合并了,导致服务起不来。这种问题不是内核本身的毛病,但需要你去适配服务配置。

5. 内核升级后真正的坑:模块、驱动与回滚

5.1 用dmesg和lsmod排查驱动加载

内核升级后最容易出问题的,其实是驱动层。特别是那些依赖内核模块的硬件,比如网卡、RAID卡、GPU,一旦模块加载失败,直接影响业务。

排查模块加载是否正常,第一步看系统启动日志:

dmesg -T | grep -iE 'module|driver|firmware'

重点找有没有 “Failed to load module”、“Direct firmware load failed” 之类的关键词。这些提示通常意味着某个模块或固件文件没找到,或者因为内核版本API变化导致旧的二进制模块无法加载。

第二步确认关键模块确实在运行:

lsmod | grep <模块名>

比如你的机器用的是Intel网卡,就查一下i40e或者ixgbe这些模块是否已经加载。如果模块没加载,可以手动尝试加载:

modprobe <模块名>

手动加载如果报错,错误信息会直接告诉你原因,比如 “Invalid module format” 表示模块版本不匹配,“Unknown symbol” 表示依赖的某个符号在内核里不存在。前者说明你用的是旧版驱动模块,后者说明驱动版本太老或太新,需要换适配新内核的驱动版本。

5.2 第三方驱动的兼容性处理

在内核升级场景里,第三方驱动一直都是大头。尤其是GPU驱动和某些存储厂商提供的闭源驱动,它们和内核的耦合度极高,内核一换,驱动基本就得重装。

处理这类问题,最规范的方式是走DKMS机制。DKMS可以把驱动源码注册到系统里,每次内核更新后自动重新编译驱动模块,从而匹配新内核。如果你的第三方驱动源码支持DKMS,安装步骤通常是:

# 以网卡驱动为例,假设驱动源码在 /opt/driver 目录 cd /opt/driver make clean make make install

如果驱动包本身支持DKMS,则:

dkms add -m <模块名> -v <版本号> dkms build -m <模块名> -v <版本号> dkms install -m <模块名> -v <版本号>

没有DKMS支持的驱动就比较折腾了,需要手动确认它的构建脚本能否在当前内核下通过编译。这也是为什么我在前面强调:装内核的同时一定要装匹配版本的kernel-devel,没有头文件和构建目录,第三方驱动编译这一步根本走不下去。

对于从旧内核升级上来的机器,我的建议是:升级前先把当前使用的第三方驱动版本记录下来,去官网查一下它对新内核的支持情况,确认有对应适配版本再动手升级内核。否则新内核起来后发现驱动不支持,又得回滚,来回折腾非常不值当。

5.3 新内核翻车时的快速回滚方案

新内核引导失败怎么办?这种场景不需要慌张,因为你当初是用install方式装的新内核,旧内核妥妥还在。重启后GRUB菜单里会有多个启动项,分别是旧内核和新内核,只要选择旧内核的菜单项进入系统,就完成了“回滚”。

但如果GRUB菜单没有出现,或者你人在机房没法看屏幕,那就需要有非交互式的应对方案。

方案一:在GRUB界面按e进入编辑模式,找到linuxefilinux开头的行,把里面的内核路径临时改成旧内核路径,然后按 Ctrl+X 启动。这种方法是一次性生效,下次重启还是走默认配置。

方案二:如果你能进入单用户模式或通过某种方式挂载根文件系统,可以直接用grubby --set-default把旧内核重新设为默认,再写回GRUB配置:

grubby --set-default=/boot/vmlinuz-旧内核版本 grub2-mkconfig -o /boot/grub2/grub.cfg

方案三:如果连GRUB菜单都进不去,只能用安装介质进入救援模式,chroot到原系统根目录后再执行上述命令。

回滚之后系统会回到旧内核环境,此时要清楚一点:你机器上仍然留着那个有问题的新内核包。下次重启时如果默认配置没有改回来,可能又会进入错误内核。所以回滚后第一件事就是确认默认启动项,必要时直接把出问题的新内核包卸载掉,防止误入:

dnf remove kernel-问题版本号

6. 旧内核清理与长期维护策略

6.1 清理旧内核的正确打开方式

内核升级了几次之后,/boot分区里的vmlinuz、initramfs会越来越多,/usr/lib/modules下的模块目录也越来越多。这时候就该做清理了。但清理旧内核有一定风险,不能直接rm -rf /boot/vmlinuz-旧版本,因为GRUB配置、rpm数据库、模块目录都需要同步处理。最规范的方式是用包管理器清理。

在Anolis上,推荐用下面两种方式之一:

方式一,直接指定旧内核版本号卸载:

dnf remove kernel-4.19.132-1.an8.x86_64 kernel-devel-4.19.132-1.an8.x86_64

注意头文件和本体要一起清理,不然留下一个孤零零的开发包,下次编译模块时容易混淆。

方式二,使用dnf自带的保留策略自动清理:

dnf remove --oldinstallonly

这个命令会删除所有超过保留数量的旧内核,比较省事,但注意它只对标记为installonly的包生效,也可能把你想留的某个次新版本删掉,所以执行前建议先加--assumeno做个模拟:

dnf remove --oldinstallonly --assumeno

我已经把“清理前先模拟”这件事当成铁律了,因为内核清理误操作导致系统无法启动的案例,比内核升级本身翻车还多。

6.2 长期维护的“铁律”

内核维护不是一次性工作,需要形成习惯。我在龙蜥上长期管理多台服务器,总结出几条自己一直遵守的原则,供你参考。

第一条:机器上永远保留两个可用内核。新内核确认稳定运行一两周后,再考虑清掉旧内核。这个策略能保证在任何时刻,GRUB菜单里都有一个已知可用的备胎启动项。常用配置是把installonly_limit设置成2或3:

# /etc/dnf/dnf.conf 中添加以下配置 installonly_limit=3

这个参数意思是最多同时保留几个installonly包,限制后,系统会自动滚动清理最旧的版本,降低手动管理的负担。

第二条:升级前做好记录。我是习惯在维护文档里记下这么几项内容:当前内核版本、目标内核版本、为什么升、第三方驱动是否有对应适配版本、回滚方案是什么。这份记录在出问题时能帮你快速判断是回滚还是继续排查。

第三条:关注安全公告,但不要盲目跟风。内核修复安全漏洞的公告出来之后,不用当天就急着升,但要把这个事纳入近一周的工作计划。等第一批用户升级反馈稳定之后,再在自己的环境里做测试升级,风险会小很多。毕竟那些被历史反复验证的“升级事故”,大部分都是抢跑抢出来的。

第四条:升级前把业务验证脚本准备好。重启进新内核后,快速跑一遍核心业务路径或健康检查脚本,确认CPU、内存、磁盘IO、网络连接一切正常。宁可脚本多写两行,也别等业务报警了才意识到内核升级可能影响了什么。我自己管理的那批机器上,就放着一个简单的检查脚本,开机会自动记录关键指标,一旦内核升级后异常,我能第一时间从数据里看到端倪。

我在实际操作中的体会是,内核升级这件事,最大的风险其实不在技术本身,而在于准备不足和操作姿势不对。只要把前面说的查询、配置、安装、切换、验证这条链路走熟,并且始终坚持“留一个可回滚的旧内核”的底线,Anolis龙蜥的内核升级完全可以做到从容不迫。最后再分享一个小技巧:如果你经常需要在多台龙蜥机器上做内核同步升级,可以考虑把dnf install kernel kernel-devel kernel-headers这个命令和grubby --set-default写成一个shell脚本,参数化目标版本号,配合自动化批量工具一次性分发到所有目标机器上。这样既保证了操作的一致性,也减少了手动敲命令出错的概率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询