news 2026/10/22 2:49:55

欧拉系统多内核共存:GRUB2默认启动项配置实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
欧拉系统多内核共存:GRUB2默认启动项配置实战指南

上个月给一批虚拟服务器升级内核,从5.10的某个小版本升到了新小版本。命令执行得很顺利,下载、安装、重启一气呵成。结果十几台机器重启完,uname -r一敲,全还是旧内核版本。那一刻我意识到,在欧拉25.09系统里,“新内核装好了”和“新内核成为第一启动项”完全是两件事。

欧拉25.09的引导器是GRUB2,它默认启动哪个内核,由/boot/grub2/grub.cfg里的 default 项和grubenv里的saved_entry共同决定,而不是“哪个版本新就引导哪个”。内核包安装时只是往 /boot 目录和 grub 菜单里增加了一个候选启动项,默认启动项并不会自动跟着新内核走。

这篇文章想把这件事彻底讲透。系统里有多个内核、需要精确指定默认启动版本的场景太常见了:生产环境内核升级要分阶段验证、业务软件依赖特定内核的 kabi 接口、RT 实时内核作为主力、排查故障时需要临时回滚旧内核,全都离不开启动项顺序的手动配置。我会从底层原理拆解到具体命令实操,再把我实际踩过的几个坑完整复盘一遍,你可以直接照着操作。

1. 默认启动项为什么不能想当然:一次升级后仍旧内核启动的真实场景

1.1 从一段平淡无奇的升级经历说起

先还原那个让我印象深刻的场景。某天下午,我把一台测试机从软件源里升级内核,新内核的 RPM 包安装完成后,我习惯性地敲了reboot。大概半分钟后机器回来,我执行uname -r,看到的还是旧版本号。第一反应是升级没生效,于是又用rpm -qa | grep kernel查了一遍,新内核的包明明已经装好了,ls /boot/vmlinuz-*也能看到新内核文件,这就让人有点迷惑。

后来才反应过来,引导层决定启动哪个内核,根本不是“哪个新就用哪个”。具体来说,内核安装包的 post-install 脚本会检测当前系统的 grub 菜单并重新生成 grub.cfg,往菜单列表里插入新内核对应的 menuentry,但默认项的处理逻辑是保留系统当前的 default 设定。也就是说,如果之前配置的是set default="${saved_entry}",而saved_entry还停留在旧内核的名称上,那新内核虽然出现在菜单第二项、第三项,默认选中的仍然是旧内核。

这个逻辑本身是合理的,它给系统保留了版本切换的自主权。但对刚接触多内核管理的人来说,确实容易产生“装完新内核就应该自动用新内核”的错觉。本文后面所有操作,本质上都是在把这种选择权拿回自己手里。

1.2 GRUB2的启动顺序到底由谁决定

要搞懂怎么改,先得搞懂 GRUB2 的启动顺序由谁决定。核心文件是/boot/grub2/grub.cfg,里面每个 menuentry 就是一个可启动项。开机时 GRUB 先读 grub.cfg,找到set default=...这一行,确定默认选中哪一个菜单项。常见写法有三种:

  • set default="0":硬编码选第一个菜单项。
  • set default="openEuler (5.10.0-153.xx) 25.09":按菜单名称指定。
  • set default="${saved_entry}":从 grubenv 里的 saved_entry 变量读取。

第三种写法最常见,因为它配合“记录上次启动项”的功能使用,灵活性最好。而grub2-set-default命令,本质上就是修改/boot/grub2/grubenv里的saved_entry;grubby则是直接操作 grub.cfg 和 grubenv 中对应的默认项配置。

这个机制可以用一个生活类比来记:GRUB2 是小区门卫,菜单里的内核候选是住户,saved_entry是门卫手里的默认放行名单。新住户搬进来(安装新内核),门卫并不会自动把名单换成新住户,只有你明确告诉他“以后默认叫这个住户”,他才会照做。这个类比虽然简单,但能解释绝大多数“改了不生效”的疑问——你很可能只是改了某一处配置,而门卫实际读的是另一处。

1.3 哪些场景必须手动干预启动顺序

不是每台机器都要手动设置启动顺序,单内核环境的服务器完全不用操心。但下面几类场景一定会用到。

第一,生产环境分批次内核升级。典型流程是先让一两台测试机把新内核设为首选,观察运行状态稳定之后,再逐步扩大到其他机器。如果默认启动项不跟着新内核走,批量切换就无从谈起。

第二,业务软件与内核版本强绑定。某分布式存储的驱动模块、某高性能网卡驱动、某数据库的安全组件,都可能在安装时检测内核版本,或者依赖某个具体内核版本的 kabi 接口。这些业务系统要求机器重启后必须精确回到那个内核版本,其他版本一概不能引导。

第三,实时系统与普通内核共存。需要低延迟响应时,RT 内核是主力,普通内核只能当备用。机器重启后必须默认进 RT 内核。

第四,故障排查与回滚。新内核引发 panic 或者业务异常,需要快速回到上一个已知可用的版本。这时默认启动项必须能一键指向备份内核。

这些场景的共同点是系统里永远不止一个内核,但默认启动项必须精确命中其中一个。下面就从查看现状开始,一步步把配置做起来。

2. 操作前先确认三件事:看内核、看菜单、看当前默认值

2.1 摸清系统里装了几个内核

不管你想设置哪个内核为第一启动项,第一步都应该是把系统里的内核家底摸清楚。我常用的命令是三个组合:

rpm -qa | grep kernel | sort ls /boot/vmlinuz-* uname -r

第一条列出所有与内核相关的包,会看到 kernel、kernel-core、kernel-modules、kernel-tools 等一批。数量看着不少,但真正决定启动项的只有 vmlinuz 文件。第二条列出 boot 目录下所有内核文件,这是最直观的版本清单。第三条显示当前运行的内核版本。

三条命令都跑一遍,你就能知道“系统里装了几个候选内核、现在跑的是哪个”。这一步花不了半分钟,但真的能避免后面改错目标。我把它们固定成一条组合命令,需要时直接执行:

echo "--- 已装内核包 ---" && rpm -qa | grep kernel | sort && echo "--- boot目录内核文件 ---" && ls /boot/vmlinuz-* && echo "--- 当前运行内核 ---" && uname -r

2.2 整理GRUB启动菜单的真实顺序

RPM 包清单只是候选名单,真实生效的启动菜单要看 grub.cfg。用 awk 从 grub.cfg 里提取所有 menuentry 的名称和顺序:

awk -F\' '/menuentry / {print $2}' /boot/grub2/grub.cfg

输出大致是这样:

openEuler (5.10.0-153.xx) 25.09 openEuler (5.10.0-136.xx) 25.09 openEuler (5.10.0-136.xx with kdump) 25.09

注意一个细节:同一个内核版本可能对应多个菜单项,比如with kdump、with debug,它们实际是不同的引导参数组合。所以描述“启动哪个内核”时,更准确的说法是“启动哪个 menuentry”。菜单项名称差一个后缀,实际引导出来的参数集就不一样。

这份菜单清单是你后面所有设置的基础。无论用grub2-set-default按名称匹配,还是用grubby按内核文件定位,都以这份清单为参照。我建议把这份输出保存到一个临时文件里,后续操作时反复对照。

2.3 确认当前默认启动项是谁

动手改之前,还得知道当前默认启动的到底是哪一项。查看 grubenv 中的记录:

grub2-editenv list

输出可能是:

saved_entry=openEuler (5.10.0-136.xx) 25.09

这说明默认启动项由 grubenv 里的saved_entry控制。grubenv 是一个持久化的环境变量文件,专门用来保存 GRUB 运行时的状态。

如果输出里没有 saved_entry 这一条,那默认项就看 grub.cfg 里的set default行:

grep '^set default' /boot/grub2/grub.cfg

这一行的内容决定了默认启动逻辑。看到set default="0"就是固定第一个菜单项;看到set default="${saved_entry}"则是从 grubenv 读取。

还有个容易忽略的点:UEFI 引导模式下,grub.cfg 的实际路径可能是/boot/efi/EFI/openEuler/grub.cfg,而 BIOS 模式是/boot/grub2/grub.cfg。大多数传统服务器走 BIOS 或者 Legacy 方式,但如果你管理的是 UEFI 启动的机器,查看和生成配置时要注意路径差异。可以用find /boot -name grub.cfg来定位真实文件。

提示:本章的确认工作不是可选项。我见过太多人跳过这一步直接执行设置命令,结果把默认项配到了错误的目标上,重启后才傻眼。

3. 改默认启动项的三类主流操作与各自适用场景

3.1 grub2-set-default:按菜单名称指定

这是最直观的命令,语义直白:设置当前系统的默认启动项。

grub2-set-default "openEuler (5.10.0-153.xx) 25.09"

引号里的内容必须和 grub 菜单里的 menuentry 名称完全一致,大小写、空格、括号、版本号都不能差。执行成功后,用grub2-editenv list验证,能看到saved_entry被改成了目标菜单项。

这条命令的优势是直接用菜单名称定位,人类可读性好。缺点是你的操作对象是“名称”,一旦菜单里有多个相似名称,或者名称写错,它会在 grubenv 里写入一个无法精确匹配的条目,启动时 GRUB 可能自动回退到第一个菜单项。所以用这条命令之前,最好把 grub.cfg 里的菜单名称完整复制出来,不要手敲。

3.2 grubby:按内核文件指定

grubby 是系统级引导配置工具,它不关心菜单显示名称,而是直接操作内核文件和启动条目。查看所有启动项的完整信息:

grubby --info=ALL

输出会列出每个启动项的信息,包括 index、title、kernel、initrd 等字段。想设置某个内核文件为默认项,直接用文件路径:

grubby --set-default=/boot/vmlinuz-5.10.0-153.xx

grubby 会根据这个 vmlinuz 文件找到它对应的菜单项,并调整默认配置。还可以按菜单索引设置:

grubby --set-default-index=1

在脚本化批量管理时,grubby 往往比 grub2-set-default 更可靠,因为它以内核文件路径为锚点,不依赖菜单名称的格式稳定性。我自己的习惯是:交互式操作用 grub2-set-default,写脚本或批量操作时用 grubby。

3.3 /etc/default/grub文件级配置

如果你的系统要求长期稳定地把某个内核作为默认启动项,推荐走文件配置路线。打开/etc/default/grub:

vim /etc/default/grub

找到GRUB_DEFAULT这一行,当前值可能是saved,也可能是0。改成目标内核的数字编号或完整菜单名称:

GRUB_DEFAULT=2

或者更稳妥的写法:

GRUB_DEFAULT="openEuler (5.10.0-153.xx) 25.09"

改完不等于生效,必须重新生成 grub.cfg。这里先说清不同写法的后续影响:GRUB_DEFAULT=saved表示始终读取 grubenv 中的 saved_entry,适合配合 grub2-set-default 做动态切换;写死数字表示固定第几个菜单项,简单但脆弱,一旦内核顺序调整就跟着错;写菜单名称最稳定,即使菜单顺序变了,名称不变就不会错,缺点是新内核升级后名称也需要同步更新。

3.4 生成配置与验证

改完文件必须执行配置生成,让/etc/default/grub的改动真正落到 grub.cfg 里:

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

这条命令会扫描 /boot 目录下的 vmlinuz 和 initramfs,结合/etc/default/grub里的选项和/etc/grub.d/下的脚本,重新生成一份完整的 grub.cfg。

验证分两步。第一步看默认项是否对准目标:

grub2-editenv list grep '^set default' /boot/grub2/grub.cfg

第二步确认目标内核的菜单项确实存在于 grub.cfg 中:

awk -F\' '/menuentry / {print $2}' /boot/grub2/grub.cfg | grep '5.10.0-153'

注意:grub2-mkconfig 在 UEFI 系统上有时需要指定输出路径,比如/boot/efi/EFI/openEuler/grub.cfg。不确定平台的话,先用grub2-mkconfig --help看一下帮助,或者直接查当前系统 grub.cfg 的真实路径再动手。

我把三类方式整理成一张表,方便对照选型:

方式适用场景优势注意事项
grub2-set-default临时切换、交互式操作命令直接,改 grubenv 即时生效菜单名称必须完全一致
grubby按内核文件定位、脚本批量操作不依赖菜单名称格式,稳定需先确认内核文件路径
/etc/default/grub长期固定默认项配置持久化,重启后不被覆盖必须配合 grub2-mkconfig 执行

4. 实测替换过程:从修改配置到重启确认的完整链路

4.1 一个完整实例:把RT内核设为默认启动

空讲不如走一趟。某台测试机上同时装了普通内核和 RT 实时内核,目标是把 RT 内核设成默认启动项。整个过程分四步。

第一步定位。执行uname -r确认当前内核,ls /boot/vmlinuz-*看候选版本,grub2-editenv list记录当前默认值。

第二步设置。因为 RT 内核的菜单名称可能带着rt或者preempt_rt这类标识,名称又长又容易记岔,我用 grubby 按内核文件路径设置更省心:

grubby --set-default=/boot/vmlinuz-5.10.0-153.rt.xx

第三步确认。执行grub2-editenv list,输出里saved_entry已经变成 RT 内核对应的 menuentry。

第四步重启验证:

reboot

机器起来后马上uname -r,输出5.10.0-153.rt.xx,和预期一致,RT 内核成功成为第一启动项。整个过程从执行到确认不超过两分钟,真正耗时间的反而是前期判断哪个菜单项对应哪个内核文件。

4.2 翻车现场一:菜单里两个几乎一样的内核项

最近同事就栽在这个坑上。他执行grub2-set-default,明明指定了一个版本号,重启后 grub 默认选中的却是另一个。我上去排查,发现 grub.cfg 里同一个版本号其实对应两个 menuentry:一个是标准引导,另一个带with kdump后缀。两个项的名称只有尾部几个字符不一样,而他复制的名称恰好少了一小块。

排查命令还是那几条。用grubby --info=ALL把每个 menuentry 对应的 kernel 文件路径列出来,才发现同名不同质。

这类问题的根治办法是用grubby --set-default=/boot/vmlinuz-xxx,以文件路径为锚点。文件名在 boot 目录里是唯一的,不会出现两个 vmlinuz 同名的情况。从这次之后,我给自己用的操作脚本一律改成 grubby,再也没有遇到过菜单名称匹配出错的问题。

4.3 翻车现场二:内核可以启动但外部模块加载失败

把内核设为第一启动项只是第一步,内核能不能正常干活,还得看外部模块兼容性。

有一次我把某台机器切到新内核,启动顺序没问题,系统也正常起来了,但业务方很快就反馈异常。查看 dmesg 和 journald 日志,发现某网卡驱动模块加载失败,错误信息直指内核 kabi 接口不匹配。这台机器上的业务是某分布式存储集群,网卡驱动是硬件厂商后装的,对内核版本有严格绑定。新内核临时启动可以,但驱动模块加载不了,网络就断了,存储节点在集群里基本处于不可用状态。

我的处理方式:先grub2-set-default切回旧内核,等业务恢复正常,然后去硬件厂商确认该网卡驱动支持的内核版本范围,再规划下一步升级路径。这次事故给我的经验是:切换内核之前,把机器上所有外部安装的驱动、数据库、安全组件梳理一遍,凡是和内核版本绑定较深的,都要先确认兼容性再行动。

4.4 翻车现场三:重启后默认项悄悄回到老内核

比同名菜单更隐蔽的坑是:配置时一切正常,saved_entry 也改对了,重启后却回到老内核。我第一次遇到时一度怀疑 grubenv 被什么机制重置了,后来排查才发现,问题根源在于配置来源不一致。

在欧拉25.09里,grubenv 的 saved_entry 确实被改成了新内核,但 grub.cfg 里的set default这一行写的不是${saved_entry},而是一个写死的数字。这个数字正好对应旧内核的菜单顺序。于是重启时 GRUB 只看 grub.cfg 的 default 行,根本不关心 grubenv 被改成了什么样。

这个坑的排查顺序我再理一遍:

  1. grep '^set default' /boot/grub2/grub.cfg,看它到底引用 saved_entry 还是写死数字。
  2. grub2-editenv list看 saved_entry 当前值。
  3. 如果 default 行是数字,用grubby --set-default-index或改/etc/default/grub来修正,不要只依赖 grub2-set-default。

配置来源统一之后,重启再没出过问题。

4.5 救援补救:GRUB启动失败时的命令行操作

最坏的情况是改完默认启动项之后,重启进入不了系统,grub 菜单直接卡住或者报错。这时候还有最后一招:GRUB2 的命令行和编辑模式。

如果 grub 菜单还能显示,直接按e进入编辑模式,找到以linux开头的行,改成你希望引导的内核和根分区:

linux /vmlinuz-5.10.0-136.xx root=/dev/mapper/root ro initrd /initramfs-5.10.0-136.xx.img

按Ctrl+X引导进入系统。

如果 grub 菜单直接黑了,要在 grub 提示符下用ls列出分区,找到存放 vmlinuz 的分区,再手动指定内核文件和 initramfs 来引导。这些操作在系统手册里都有,但真到机器起不来的那天,人很容易手忙脚乱。所以我建议把这条救援流程提前写到本地笔记里,出了问题照着敲就好。

进系统后不要急着重复之前的错误配置,先恢复默认项到已知可用的内核,重新生成 grub.cfg,确认无误后再做下一步调整。

5. 多内核长期共存的几条经验

5.1 保留内核版本要克制

多内核共存是常态,但保留多少版本需要克制。boot 分区空间一般不会成为瓶颈,问题在于内核版本囤积会让 grub 菜单越来越长。菜单项多了,默认项配置的错误率会上升,重启时需要人工确认的场景也会增加。

我个人的习惯是保留最近两到三个稳定内核版本:当前正式使用一个,回滚备用一个,再留一个应急的旧版本。这样既能覆盖大多数故障场景,又不会让配置复杂度失控。如果你发现系统里已经堆了七八个内核,建议先按下一节的方式清理一轮,再考虑默认项的设置。

5.2 卸载旧内核的正确姿势

不需要的内核应该清理,但清理时要讲顺序。第一步确认当前运行的内核不在清理列表里:

uname -r

第二步卸载旧内核包:

dnf remove kernel-5.10.0-136.xx

卸载命令会同步删除对应的 vmlinuz 和 initramfs 文件,并尝试更新 grub.cfg。为了保险,卸载完成后手动再生成一次配置:

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

然后检查 grub 菜单,确认被卸载版本对应的 menuentry 已经消失。再检查 grubenv 和/etc/default/grub里的默认项,确保它们指向的内核仍然存在。

提示:如果默认项指向了一个已被卸载的内核,重启后 GRUB 会从第一个可用菜单项启动。这多数时候能兜底,但可能不是你想要的。所以清理前务必检查默认项。

5.3 变更前的备份与回滚思路

内核启动项配置的变更,单看每一步都不复杂,但生产环境里还是要有回滚预案。我的做法是先备份当前配置:

cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak.$(date +%F) grub2-editenv export > /boot/grub2/grubenv.bak.$(date +%F)

如果切到新内核后发现问题,只要能进 grub 菜单,就先选择备用的旧内核启动项把机器带起来,然后恢复备份的 grub.cfg 和 grubenv,重新生成配置,再重启。

这套思路其实和软件发布的灰度策略一个逻辑:先保证能回退,再往前推进。配置启动项这种看似低风险的操作,在规模化的服务器环境里也值得当成一次发布来对待。我后来把所有服务器的内核切换都纳入了这个流程之后,再没有因为配置启动项这件事在半夜爬起来救过机器。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 2:49:20

从Few-Shot到可解释性:2024提示工程架构实践指南

1. 重新定义提示工程:架构师视角下的“翻译”与“契约”这几年圈子里都在说“大模型能力到顶了”,但我在一线带着团队做落地项目,最大的感受恰恰相反:模型的底座是固定的,真正决定一个AI系统能用不能用、好用不好用的&…

作者头像 李华
网站建设 2026/10/22 2:49:19

AI Agent在智能城市安全监控中的角色与落地实践

去年我在某园区做了一套视频监控系统的智能化改造,核心是在原有算法仓库上面挂了一层AI Agent。项目收尾那天我从监控中心往外走的时候,脑子里只有一句话:原来值班员每天面对几十路实时画面,是真的看不过来。这也是今天想聊“AI A…

作者头像 李华
网站建设 2026/10/22 2:49:03

高铁与城镇化因果推断:PSM-DID模型全流程实操解析

高铁与城镇化之间的关系,远不是"开通了、变化了、所以是高铁的功劳"这么简单。我自己在处理一批地级市多年面板数据时,第一版回归结果就栽了跟头:高铁开通变量的系数时正时负,换两个控制变量就从显著变成不显著&#xf…

作者头像 李华
网站建设 2026/10/22 2:48:14

PSO优化神经网络股票预测:提升方向准确率与实盘鲁棒性

简介:本资源是一套面向人工智能与量化投资初学者的实战项目资料,聚焦于利用粒子群优化(PSO)算法提升神经网络在股票价格预测中的建模精度。针对传统神经网络易陷入局部最优、参数调优依赖经验等问题,该方案提供从数据预…

作者头像 李华
网站建设 2026/10/22 2:46:27

AI Agent产品化实战指南:从需求定义到项目沉淀的完整方法论

开头说说我最近的体会。带过几个AI Agent项目之后,我越来越觉得,很多团队的问题不是技术不行,而是忙了一整圈,最后拿不出东西来。需求会开了无数轮,技术方案改了七八版,Demo也能跑,但一问“这个…

作者头像 李华
网站建设 2026/10/22 2:46:12

SpringCloud+Vue+小程序:在线图书阅读打卡系统实战复盘

做一个在线阅读打卡系统,最难的部分往往不是“能看书”,而是把阅读行为转成可量化的数据,再推动用户持续参与。最近我把「书洞图书在线阅读打卡系统」从零到一落地,整套东西刚好把SpringBoot、Vue、SpringCloud和小程序四块拼图串…

作者头像 李华