1. 为什么需要更改默认启动内核
1.1 内核版本与硬件兼容性的现实矛盾
deepin 作为一款基于 Linux 的国产桌面操作系统,其内核更新节奏相对保守,通常跟随上游稳定版本。但问题在于,系统默认启动的内核并不一定是最适合你当前硬件的那一个。我遇到过太多次这样的情况:系统更新后自动拉取了一个新内核,结果重启后显卡驱动挂了、无线网卡识别不到、外接显示器不亮,甚至直接卡在启动画面进不去桌面。这时候你需要的不是重装系统,而是回退到之前那个能正常工作的内核版本。
另一种场景是硬件太新。比如你刚换了一块新出的独立显卡或者主板,默认内核里的驱动太老,根本带不动。你手动编译或安装了新内核,但系统每次启动还是默认进旧的那个,新内核躺在/boot目录里吃灰。这时候就得把默认启动项改过来。
还有一种情况是开发调试需求。某些特定软件或驱动模块只兼容特定内核版本,你需要固定使用某个内核来保证工作环境的一致性。比如做嵌入式开发时,交叉编译工具链对内核头文件版本有严格要求,内核一换,整个编译环境就得重新配。
1.2 deepin 的启动引导机制简述
deepin 默认使用 GRUB2 作为引导加载器。GRUB2 的配置文件主要分布在两个位置:/boot/grub/grub.cfg是自动生成的主配置文件,不建议直接编辑,因为每次内核更新或执行update-grub时它都会被覆盖;真正需要修改的是/etc/default/grub和/etc/grub.d/目录下的脚本。
系统启动时,GRUB2 会读取grub.cfg,展示一个菜单(如果配置了显示的话),然后根据GRUB_DEFAULT参数决定加载哪个菜单项。deepin 默认可能将菜单隐藏,直接启动默认项,所以很多用户根本看不到选择界面,也就无从切换内核。
理解这个机制之后,更改默认启动内核的思路就很清晰了:要么修改GRUB_DEFAULT的值指向你想要的内核菜单项,要么调整菜单项的顺序让目标内核排到第一位。两种方式各有适用场景,下面会详细拆解。
注意:在动手之前,务必确认你的系统里至少有两个可用的内核版本。如果只有一个内核,改来改去没有意义,反而可能把引导搞坏。用
dpkg --list | grep linux-image可以查看已安装的内核包。
2. 操作前的准备工作与风险认知
2.1 确认当前内核与可用内核列表
第一步永远是摸清现状。打开终端,执行:
uname -r这个命令输出当前正在运行的内核版本,比如5.15.0-30-generic或5.10.0-amd64-desktop。记下这个版本号,这是你的“安全底线”——万一改出问题,至少知道哪个内核是能用的。
接着查看系统里安装了哪些内核:
dpkg --list | grep linux-image输出会列出所有已安装的内核镜像包。通常你会看到类似linux-image-5.15.0-30-generic、linux-image-5.10.0-amd64-desktop这样的条目。注意区分linux-image(内核镜像)和linux-headers(内核头文件),后者是编译模块用的,不影响启动。
然后查看/boot目录下实际存在的内核文件:
ls -lh /boot/vmlinuz-*每个vmlinuz-xxx文件对应一个可启动的内核。如果某个内核包已安装但/boot下没有对应的vmlinuz文件,说明安装不完整,不能作为启动项。
2.2 备份关键配置文件
改引导配置之前,备份是铁律。需要备份的文件有两个:
sudo cp /etc/default/grub /etc/default/grub.bak sudo cp /boot/grub/grub.cfg /boot/grub/grub.cfg.bak/etc/default/grub是你即将修改的文件,/boot/grub/grub.cfg是自动生成的结果文件。两个都备份,万一改错了可以直接还原。
提示:备份文件建议加上日期后缀,比如
grub.bak.20250101,这样多次修改后还能追溯到具体哪一版出了问题。
2.3 了解 GRUB_DEFAULT 的取值规则
GRUB_DEFAULT这个参数支持几种不同的写法,理解它们是用好这个功能的关键:
| 取值方式 | 示例 | 含义 | 适用场景 |
|---|---|---|---|
| 数字索引 | GRUB_DEFAULT=0 | 第1个菜单项 | 菜单顺序固定时 |
| 数字索引 | GRUB_DEFAULT=2 | 第3个菜单项 | 知道目标内核排第几 |
| 菜单项标题 | GRUB_DEFAULT="deepin, with Linux 5.10.0" | 按标题精确匹配 | 菜单顺序会变时更可靠 |
| 保存的默认项 | GRUB_DEFAULT=saved | 使用上次选择的项 | 配合grub-set-default使用 |
数字索引从 0 开始计数,对应 GRUB 菜单中从上到下的顺序。但问题是,每次内核更新后菜单顺序可能变化,所以用数字索引不够稳健。更推荐用菜单项标题的方式,只要标题不变,不管菜单怎么排序都能准确命中。
菜单项标题从哪里看?执行:
grep -E "menuentry|submenu" /boot/grub/grub.cfg输出会显示所有菜单项和子菜单的标题。deepin 的菜单结构通常是两层:顶层是“deepin”子菜单,里面才是具体的内核版本。所以完整的菜单项标识可能是"deepin>with Linux 5.10.0-amd64-desktop"这种形式,中间用>连接。
3. 更改默认启动内核的完整实操
3.1 方法一:通过修改 GRUB_DEFAULT 指定内核
这是最直接的方法。用你习惯的编辑器打开/etc/default/grub:
sudo nano /etc/default/grub找到GRUB_DEFAULT这一行。如果前面有#注释掉了,把#去掉。然后把它改成你想要的内核对应的菜单项标识。
假设你想默认启动5.10.0-amd64-desktop这个内核,而它在 GRUB 菜单中的完整路径是"deepin>with Linux 5.10.0-amd64-desktop",那么应该写成:
GRUB_DEFAULT="deepin>with Linux 5.10.0-amd64-desktop"注意引号不能省,因为标题里有空格和特殊字符。如果标题里包含>符号,GRUB 会把它解析为子菜单分隔符,这正是我们需要的。
改完之后保存退出,执行:
sudo update-grub这个命令会重新生成/boot/grub/grub.cfg,把新的默认项写进去。输出信息里会列出它检测到的所有内核,你可以核对一下目标内核是否在列。
注意:
update-grub在 deepin 上可能需要用sudo grub-mkconfig -o /boot/grub/grub.cfg代替,具体看系统版本。如果update-grub命令不存在,就用后者。
3.2 方法二:调整菜单顺序让目标内核排第一
如果你不想折腾菜单项标题的精确匹配,还有一种更“笨”但更直观的方法:把目标内核的菜单项调到第一位,然后设置GRUB_DEFAULT=0。
GRUB 的菜单顺序由/etc/grub.d/目录下脚本的执行顺序决定。具体来说,10_linux脚本负责生成 Linux 内核菜单项,它按照内核版本号从高到低排序。如果你想让某个低版本内核排到前面,需要修改这个脚本的排序逻辑,或者用30_os-prober之类的脚本手动插入。
这种方法比较绕,而且每次内核更新后顺序又会变,维护成本高。我个人不推荐这种方式,除非你有特殊需求必须让某个内核固定排第一。
3.3 方法三:使用 grub-set-default 配合 saved 模式
这是最灵活的一种方式。首先修改/etc/default/grub:
GRUB_DEFAULT=saved GRUB_SAVEDEFAULT=trueGRUB_DEFAULT=saved告诉 GRUB 使用上次保存的默认项,GRUB_SAVEDEFAULT=true则让 GRUB 在每次启动时自动保存当前选择。然后执行:
sudo update-grub接下来用grub-set-default命令指定默认项:
sudo grub-set-default "deepin>with Linux 5.10.0-amd64-desktop"这个命令会把选择写入/boot/grub/grubenv文件。之后每次启动都会默认进这个内核,直到你再次用grub-set-default修改。
这种方式的优势在于:你可以在启动时临时选择其他内核,而且这个选择会被记住。比如某次你需要用新内核测试一个功能,重启时在菜单里选了新内核,之后系统就默认进新内核了,不用再改配置文件。对于需要频繁切换内核的开发者来说,这个方案最省事。
3.4 验证更改是否生效
改完之后不要急着重启,先检查一下grub.cfg里默认项是否已经更新:
grep -A2 "set default" /boot/grub/grub.cfg或者直接看grubenv文件:
sudo grub-editenv list输出里会显示saved_entry=后面跟着的菜单项标识。确认无误后再重启:
sudo reboot重启后再次执行uname -r,看看输出的内核版本是不是你期望的那个。如果不是,说明配置没生效,需要回头检查。
4. 常见问题与排查技巧实录
4.1 改完重启后仍然进入旧内核
这是最常见的问题。原因通常有三个:
第一,update-grub没有成功执行。检查命令输出有没有报错,特别是权限问题。有些 deepin 版本需要sudo才能写入/boot/grub/grub.cfg。
第二,菜单项标题写错了。GRUB 对标题的匹配是精确匹配,多一个空格、少一个字符都不行。建议直接从grep menuentry /boot/grub/grub.cfg的输出里复制粘贴,不要手动输入。
第三,GRUB_DEFAULT被其他配置覆盖了。检查/etc/default/grub.d/目录下有没有其他配置文件,以及/etc/grub.d/里的脚本有没有硬编码默认项。deepin 有时会在这些地方做定制。
4.2 启动菜单不显示,无法手动选择
deepin 默认可能设置了GRUB_TIMEOUT=0和GRUB_TIMEOUT_STYLE=hidden,导致菜单一闪而过或者根本不显示。如果你想在启动时看到菜单,修改/etc/default/grub:
GRUB_TIMEOUT=5 GRUB_TIMEOUT_STYLE=menuGRUB_TIMEOUT=5表示菜单显示 5 秒后自动启动默认项,GRUB_TIMEOUT_STYLE=menu强制显示菜单。改完记得sudo update-grub。
如果开机时连 GRUB 界面都看不到,可能是主板启用了快速启动或者 UEFI 直接引导了内核。这种情况下需要在 BIOS/UEFI 设置里关闭快速启动,或者调整启动顺序。
4.3 目标内核在菜单中不存在
如果你在grub.cfg里找不到想要的内核菜单项,说明这个内核没有被 GRUB 识别。可能的原因:
- 内核包安装了但
/boot/vmlinuz-xxx文件缺失,重新安装内核包即可。 - 内核包安装了但
initrd.img-xxx文件缺失,同样重新安装。 - 内核版本太旧,被
10_linux脚本过滤掉了。可以检查/etc/grub.d/10_linux里的过滤逻辑。
重新安装内核的命令:
sudo apt install --reinstall linux-image-5.10.0-amd64-desktop4.4 更改后系统无法启动
这是最坏的情况,但也不用慌。重启时按住Shift键(BIOS 启动)或Esc键(UEFI 启动),强制显示 GRUB 菜单,然后手动选择之前能用的内核进入系统。进去之后把/etc/default/grub还原成备份版本,再sudo update-grub即可。
如果连 GRUB 菜单都进不去,就需要用 deepin 的安装 U 盘启动,进入 Live 环境修复引导。具体操作是挂载原系统根分区,chroot 进去,然后还原配置文件并重新生成grub.cfg。
提示:平时养成保留至少两个可用内核的习惯。每次内核更新后,不要急着删除旧内核,等新内核稳定运行一段时间后再清理。这样万一新内核有问题,随时可以回退。
4.5 常见问题速查表
| 问题现象 | 可能原因 | 排查命令 | 解决方法 |
|---|---|---|---|
| 重启后仍进旧内核 | GRUB_DEFAULT 未生效 | grep default /boot/grub/grub.cfg | 检查标题拼写,重新 update-grub |
| 菜单不显示 | TIMEOUT 为 0 或 hidden | grep TIMEOUT /etc/default/grub | 改为 5 和 menu |
| 目标内核不在菜单 | 内核文件缺失 | ls /boot/vmlinuz-* | 重装内核包 |
| 系统无法启动 | 默认项指向了坏内核 | 强制显示 GRUB 菜单 | 手动选旧内核,还原配置 |
| grub-set-default 报错 | grubenv 文件损坏 | sudo grub-editenv list | 重建 grubenv 或改用 GRUB_DEFAULT |
5. 内核管理的一些进阶经验
5.1 内核锁定与版本固定
如果你确定某个内核版本最适合你的硬件,可以把它“锁定”,防止系统更新时自动升级。方法是用apt-mark命令:
sudo apt-mark hold linux-image-5.10.0-amd64-desktop linux-headers-5.10.0-amd64-desktop这样apt upgrade时就不会动这两个包。需要解锁时用sudo apt-mark unhold。这个技巧在硬件驱动不兼容新内核时特别有用,我自己的几台老机器就是这么锁定的。
5.2 清理旧内核的正确姿势
deepin 不会自动清理旧内核,时间长了/boot分区容易被撑满。清理时注意不要删除当前正在运行的内核和默认启动的内核。安全做法是先确认:
uname -r grep default /boot/grub/grub.cfg然后删除其他不需要的内核包:
sudo apt remove linux-image-5.15.0-30-generic linux-headers-5.15.0-30-generic删完之后再执行一次sudo update-grub,让菜单同步更新。
注意:不要手动删除
/boot下的文件,一定要用包管理器删除。手动删文件会导致包管理器状态不一致,后续更新可能出问题。
5.3 多内核共存时的模块管理
不同内核版本对应的驱动模块(比如显卡驱动、无线网卡驱动)是分开编译的。如果你手动安装了第三方驱动,切换内核后可能需要重新编译模块。以 DKMS 为例,切换内核后执行:
sudo dkms autoinstall这个命令会为当前运行的内核自动编译并安装所有 DKMS 模块。如果某个模块编译失败,检查内核头文件是否已安装:
sudo apt install linux-headers-$(uname -r)5.4 个人实操心得
我在多台 deepin 机器上折腾过内核切换,总结下来最稳的方案是:用GRUB_DEFAULT=saved配合grub-set-default。原因很简单,这种方式不依赖菜单顺序,也不怕内核更新后标题变化。你只需要在需要切换时执行一次grub-set-default,之后系统就记住了。
另外,每次改完配置后,我都会先用sudo grub-script-check /boot/grub/grub.cfg检查一下语法有没有问题。这个命令能提前发现大部分配置错误,避免重启后才发现进不去系统。
最后再分享一个小技巧:如果你只是临时想用某个内核启动一次,不需要改任何配置,重启时在 GRUB 菜单里直接选那个内核就行。GRUB 默认会记住这次选择(如果启用了GRUB_SAVEDEFAULT),下次启动还是它。想恢复原来的默认项,再执行一次grub-set-default即可。