在CentOS系统中,如果你升级了内核后发现系统不稳定或者某些驱动不兼容,最直接有效的回滚方式就是通过GRUB2引导加载器设置默认启动的内核版本。具体操作就是修改/etc/default/grub配置文件中的GRUB_DEFAULT参数,指向你想要启动的旧内核条目,然后重新生成grub.cfg配置文件并重启系统即可。整个过程不需要复杂的命令,几分钟就能完成,下面我会把每一步都讲透。
很多运维人员在做内核升级后遇到问题,第一反应是去卸载新内核或者重新编译,其实完全没必要。GRUB2本身就支持多内核共存和选择启动,你只需要告诉它"下次开机用哪个内核"就行。这篇文章会从查看当前内核、修改默认启动项、生成配置、验证回滚效果等完整流程来讲,同时也会覆盖一些特殊场景和常见坑。
一、先搞清楚你当前有哪些内核可以选在动手修改之前,你必须先知道系统里装了哪些内核版本。CentOS 7和CentOS 8/Stream的内核管理方式略有不同,但查看方法都很简单。
先查看当前正在运行的内核版本:
uname -r
然后查看系统中安装了哪些内核包:
rpm -qa | grep kernel
或者更直观地看boot目录下有哪些内核镜像:
ls /boot/vmlinuz-*
你会看到类似这样的输出:
/boot/vmlinuz-3.10.0-1160.el7.x86_64 /boot/vmlinuz-3.10.0-1127.el7.x86_64 /boot/vmlinuz-5.4.0-42-generic
每一个vmlinuz文件对应一个内核版本。记住你要回滚到的那个版本号,后面要用到。如果你用的是CentOS 8或Stream,内核包名可能带有kernel-core字样,查看方式一样。
二、查看GRUB2菜单里的启动项顺序GRUB2的启动菜单里会列出所有可用的内核,它们的排列顺序决定了默认启动哪个。你需要先看一下当前的菜单结构。
查看GRUB配置文件:
cat /boot/grub2/grub.cfg
或者在CentOS 7上:
cat /boot/grub2/grub.cfg | grep menuentry
你会看到类似这样的条目:
menuentry 'CentOS Linux (3.10.0-1160.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-xxx' {
...
}
menuentry 'CentOS Linux (3.10.0-1127.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1127.el7.x86_64-advanced-xxx' {
...
}
注意,这些menuentry是按顺序排列的,第一个就是默认启动项。你需要确认你要回滚的内核在菜单里的位置,是第0项、第1项还是第几项。
三、修改GRUB_DEFAULT参数设置默认内核这是核心步骤。打开GRUB的默认配置文件:
vi /etc/default/grub
找到GRUB_DEFAULT这一行。它有几种设置方式,我逐一说明:
第一种:按索引号设置。比如你要启动菜单里的第二个内核(索引从0开始),就写:
GRUB_DEFAULT=1
第二种:按内核名称精确指定。这种方式最稳妥,不怕菜单顺序变化:
GRUB_DEFAULT="CentOS Linux (3.10.0-1127.el7.x86_64) 7 (Core)"
注意,这里的名称必须和grub.cfg里menuentry后面的标题完全一致,包括空格和括号。你可以直接从grub.cfg里复制过来。
第三种:设置为saved,配合GRUB_SAVEDEFAULT使用,这样可以在启动时临时选择一次,之后就固定用那个内核。适合你想临时测试某个内核的场景:
GRUB_DEFAULT=saved GRUB_SAVEDEFAULT=true
另外还有一个常用参数GRUB_TIMEOUT,控制菜单等待时间,单位是秒。如果你设成0或者-1,系统会直接启动默认项不显示菜单。生产环境建议设成5到10秒,方便紧急情况下手动选择:
GRUB_TIMEOUT=5
修改完成后保存退出。
四、重新生成GRUB2配置文件改了/etc/default/grub之后,必须重新生成grub.cfg才能生效。不同系统生成方式不同。
CentOS 7(BIOS引导):
grub2-mkconfig -o /boot/grub2/grub.cfg
CentOS 7(UEFI引导):
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
CentOS 8 / Stream(BIOS):
grub2-mkconfig -o /boot/grub2/grub.cfg
CentOS 8 / Stream(UEFI):
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
执行完后会看到输出类似"done"的提示,表示生成成功。你可以再cat一下grub.cfg确认你设置的内核确实排到了第一位。
五、重启验证回滚效果配置好之后直接重启:
reboot
系统重启后,登录进去第一件事就是确认内核版本:
uname -r
如果显示的是你指定的旧内核版本,说明回滚成功。如果没有自动切换,检查一下GRUB_DEFAULT的写法是否正确,特别是引号和空格有没有问题。
还有一种情况需要注意:如果你的系统用的是UEFI引导,而且有多个引导条目(比如同时装了CentOS和其他系统),你可能需要用efibootmgr来确认引导顺序:
efibootmgr -v
确保CentOS的引导项是BootOrder里的第一项。
六、如果新内核导致系统无法启动怎么办有些时候内核升级后直接进不了系统,连GRUB菜单都看不到。这时候你需要用救援模式或者Live CD来修复。
方法一:开机时按Esc或Shift键(UEFI下可能是F12或F2)进入GRUB菜单,手动选择旧内核启动。进去之后再按上面的步骤修改默认配置。
方法二:用CentOS安装盘进入Rescue模式,挂载原系统的根分区,然后chroot进去修改:
mount /dev/sda2 /mnt chroot /mnt vi /etc/default/grub grub2-mkconfig -o /boot/grub2/grub.cfg exit umount /mnt reboot
方法三:如果是UEFI系统且引导项丢失,可以在救援模式下重新注册引导:
grub2-install /dev/sda grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
这三种方法基本能覆盖所有"内核升级后开不了机"的场景。
七、关于永久删除问题内核的补充建议回滚成功后,你可能想把有问题的新内核删掉,避免以后误选。CentOS 7下可以用yum:
yum remove kernel-xxx
但更安全的做法是先确认旧内核工作正常,再删除新内核。删除后记得重新生成grub配置:
grub2-mkconfig -o /boot/grub2/grub.cfg
CentOS 8/Stream上用dnf:
dnf remove kernel-xxx
注意,千万不要把所有内核都删了,至少保留两个以上,防止万一某个内核也有问题时没有备用选项。
八、一些容易踩的坑和实战经验第一,GRUB_DEFAULT设置索引号时,如果你的grub.cfg里有submenu(子菜单),索引号的计算会变复杂,建议直接用内核名称指定,最不容易出错。
第二,CentOS 8和Stream默认可能没有安装grub2-mkconfig命令,需要先装:
dnf install grub2-tools grub2-tools-efi
第三,如果你的系统是用云主机,有些云平台的镜像会自定义GRUB行为,修改后可能被覆盖。这种情况建议联系云平台技术支持或者在镜像层面做配置。
第四,做内核操作之前,强烈建议先备份grub配置:
cp /etc/default/grub /etc/default/grub.bak cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak
出了问题随时能恢复。这是运维的基本素养,不管多熟练都要养成习惯。
第五,如果你经常需要在内核之间切换测试,可以考虑用grubby工具,它比手动改配置文件更方便:
grubby --set-default /boot/vmlinuz-3.10.0-1127.el7.x86_64
这个命令会自动更新grub配置,不需要你手动跑mkconfig。CentOS 7和8都支持,是生产环境里很实用的小工具。
九、总结CentOS通过GRUB2回滚内核版本,本质上就是三步:确认目标内核、修改GRUB_DEFAULT、重新生成配置。整个过程风险很低,只要你不乱删内核文件、不改错引导项,基本不会出问题。关键是要熟悉自己系统的引导方式(BIOS还是UEFI),以及grub.cfg的结构。掌握这些,以后不管内核怎么升级,你都能快速回退到稳定状态。运维的核心能力之一就是"能升级也能回滚",别只会往前冲,留好退路才是真正的专业。
