🔥个人主页:爱和冰阔乐
📚专栏传送门:《数据结构与算法》 、C++
🐶学习方向:C++方向学习爱好者
⭐人生格言:得知坦然 ,失之淡然
🏠博主简介
文章目录
- 前言
- 一、先看懂启动链:报错出现在哪一层
- 二、旧内核能启动,就先从旧内核进入系统
- 2.1 调出 GRUB 菜单
- 2.2 确认当前真正运行的内核
- 2.3 暂时不要删除旧内核
- 三、先留证据:不要只盯着最后一屏报错
- 3.1 查看启动历史
- 3.2 用当前正常启动作为对照
- 3.3 检查包管理是否中断
- 3.4 检查 `/boot` 和根分区空间
- 四、重建新内核的 initramfs 和 GRUB
- 4.1 initramfs 到底负责什么
- 4.2 确认目标内核版本
- 4.3 更新或重新创建 initramfs
- 4.4 查看 initramfs 里有没有关键模块
- 4.5 重新生成 GRUB 菜单
- 五、检查根文件系统 UUID、fstab 和启动参数
- 5.1 核对真实 UUID
- 5.2 检查 GRUB 传递的 `root=`
- 5.3 在 GRUB 中临时修改参数
- 六、DKMS:为什么新内核装好了,驱动却没跟上
- 6.1 DKMS 模块与内核版本绑定
- 6.2 检查 DKMS 构建日志
- 6.3 安装 headers 并重新构建
- 6.4 Secure Boot 也可能让模块“存在但加载失败”
- 总结
- 参考资料
前言
Ubuntu 更新内核后无法启动,最稳妥的处理方式不是马上删内核、重装驱动或反复强制关机,而是先保留一条能进入系统的路径。
这一篇主要处理旧内核仍然可以启动的情况。内容从启动链定位开始,依次检查失败日志、包管理状态、/boot空间、initramfs、根文件系统 UUID、GRUB 参数、DKMS 与 Secure Boot。
处理原则:先用旧内核恢复可操作环境,再根据证据修复新内核。旧内核在新内核完成验证前不要删除。
本文重点解决以下问题:
- 新内核启动失败后,怎样从 GRUB 进入旧内核;
- 怎样判断故障发生在 GRUB、内核、initramfs 还是驱动阶段;
- 怎样重建指定内核的 initramfs 和 GRUB;
- 怎样核对 UUID、
fstab与root=启动参数; - 怎样处理 DKMS、headers 与 Secure Boot 导致的模块故障。
一、先看懂启动链:报错出现在哪一层
Ubuntu 从按下电源到进入桌面,大致会经历下面几个阶段:
| 启动阶段 | 主要工作 | 常见故障表现 |
|---|---|---|
| UEFI/BIOS | 初始化硬件并寻找启动项 | 找不到启动盘、没有 Ubuntu 启动项 |
| GRUB | 显示内核菜单并传递启动参数 | GRUB 菜单消失、菜单损坏、选项错误 |
| Linux Kernel | 初始化 CPU、内存和基础设备 | 选择内核后立刻重启、Kernel Panic |
| initramfs | 加载早期驱动并找到根文件系统 | 掉进(initramfs)、找不到 UUID、无法挂载根分区 |
| 根文件系统与 systemd | 挂载磁盘、启动服务 | emergency mode、fstab挂载失败 |
| 驱动与桌面 | 加载显卡、网卡和外部模块 | 黑屏、无线网卡消失、VirtualBox/NVIDIA 模块不可用 |
先判断失败阶段,再决定使用什么工具。
- GRUB 没有菜单:检查 UEFI 启动项和 GRUB;
- 进入
(initramfs):优先检查根分区、UUID、存储驱动和 initramfs; - 进入 emergency mode:重点查看
/etc/fstab和 systemd 失败单元; - 桌面前黑屏:再考虑显卡模块、显示管理器和
nomodeset; - 新内核下网卡或虚拟化模块消失:检查 DKMS、headers 和 Secure Boot。
这一步看似简单,却能避免后面大量无效操作。
二、旧内核能启动,就先从旧内核进入系统
2.1 调出 GRUB 菜单
传统 BIOS 机器开机时可以尝试按住Shift,UEFI 机器通常连续按Esc。不同电脑的固件启动速度不同,按键时机可能需要试几次。
进入 GRUB 后选择:
Advanced options for Ubuntu
一般可以看到新旧内核及其 recovery mode,例如:
- Ubuntu, with Linux
6.x.y-new-generic - Ubuntu, with Linux
6.x.y-new-generic (recovery mode) - Ubuntu, with Linux
6.x.y-old-generic - Ubuntu, with Linux
6.x.y-old-generic (recovery mode)
先选择旧内核的普通启动项。只要旧内核还能进入系统,后面的检查和修复都会轻松很多。
2.2 确认当前真正运行的内核
进入系统后先执行:
uname-r不要只看 GRUB 菜单里选了哪个,uname -r才是当前真正运行的版本。
查看系统中已经安装的内核包:
dpkg-l'linux-image-*'|grep'^ii'再检查/boot中的新旧内核文件是否都存在:
ls-lh/boot重点关注:
vmlinuz-<version>:内核镜像;initrd.img-<version>:对应的 initramfs;config-<version>:内核配置;System.map-<version>:符号映射信息。
2.3 暂时不要删除旧内核
旧内核现在不是“占空间的旧文件”,而是系统最重要的恢复入口。
至少满足下面条件后,再考虑清理:
- 新内核已经连续正常启动;
- 网络、显卡、磁盘和虚拟化模块正常;
dkms status没有异常;- GRUB 中仍能看到可靠的回退项;
/boot和根文件系统没有错误。
执行自动清理前先看模拟结果:
sudoaptautoremove --dry-run确认不会删除当前运行内核和唯一可用的旧内核后,再决定是否执行:
sudoaptautoremove不要在唯一能够启动的内核上做“自动清理实验”。
三、先留证据:不要只盯着最后一屏报错
3.1 查看启动历史
在旧内核中执行:
journalctl --list-boots输出会列出最近几次启动记录。当前启动通常是0,上一次是-1,再上一次是-2。
查看上一次启动的内核日志:
sudojournalctl-b-1-k只看错误级别:
sudojournalctl-b-1-perr搜索常见关键字:
sudojournalctl-b-1-k|grep-Ei\'panic|error|fail|timeout|nvme|ata|ext4|xfs|btrfs|firmware|nvidia|dkms'如果故障发生得太早,系统可能还没来得及把日志写进 journal。此时屏幕报错、initramfs shell 中的输出、云服务器串口日志同样重要。
3.2 用当前正常启动作为对照
查看当前旧内核的启动信息:
sudodmesg-T|less重点观察存储、根分区、固件和模块:
sudodmesg-T|grep-Ei\'nvme|ata|root|firmware|module|secure|iommu'旧内核能识别、而新内核识别不到的设备,往往就是问题线索。
3.3 检查包管理是否中断
内核升级过程中断电、网络异常或磁盘写满,都可能留下“包已经解压,但还没有配置完成”的状态。
先检查:
sudodpkg--audit继续处理未完成配置:
sudodpkg--configure-a修复依赖:
sudoapt-get-finstall执行需要下载软件包的命令前,先确认网络和软件源可用。
3.4 检查/boot和根分区空间
/boot空间不足是内核升级失败的高频原因。系统可能已经安装了新内核包,却没能完整生成 initramfs。
df-h/boot /再检查 inode:
df-i/boot /如果更新过程中出现:
No space left on device不要只看/的剩余空间。单独挂载的/boot可能已经满了。
排查到这里时,先别急着重建所有东西。先确认磁盘空间、包状态和新内核目录完整,否则后面的
update-initramfs仍会失败。
四、重建新内核的 initramfs 和 GRUB
4.1 initramfs 到底负责什么
内核刚开始运行时,真正的根文件系统还没有挂载。initramfs 是一套临时的早期用户空间,里面通常包含:
- 找到磁盘所需的存储驱动;
- LVM、RAID、LUKS 等工具;
- 根文件系统驱动;
- 挂载根分区所需脚本;
- 把启动过程切换到真正根文件系统的逻辑。
如果 NVMe、AHCI、VirtIO、LVM、加密卷或文件系统驱动没有正确进入 initramfs,就可能出现:
Gave up waiting for root file system device ALERT! UUID=... does not exist Kernel panic - not syncing: VFS: Unable to mount root fs4.2 确认目标内核版本
查看模块目录:
ls/lib/modules假设故障内核是6.x.y-new-generic,可以先设置变量:
NEW_KERNEL='6.x.y-new-generic'检查目录是否存在:
test-d"/lib/modules/$NEW_KERNEL"&&echo"modules directory exists"再检查内核与 initrd:
ls-lh"/boot/vmlinuz-$NEW_KERNEL"\"/boot/initrd.img-$NEW_KERNEL"4.3 更新或重新创建 initramfs
更新已有 initramfs:
sudoupdate-initramfs-u-k"$NEW_KERNEL"如果对应 initrd 根本不存在,可以创建:
sudoupdate-initramfs-c-k"$NEW_KERNEL"-u是更新,-c是创建。不要为了“重来一次”直接手工删除/boot/initrd.img-*,否则包管理状态和实际文件更容易对不上。
完成后检查:
ls-lh"/boot/initrd.img-$NEW_KERNEL"4.4 查看 initramfs 里有没有关键模块
lsinitramfs"/boot/initrd.img-$NEW_KERNEL"|less搜索常见存储、加密和 LVM 组件:
lsinitramfs"/boot/initrd.img-$NEW_KERNEL"\|grep-Ei'nvme|ahci|virtio|dm-crypt|cryptsetup|lvm'这里不能仅凭“没搜到一个名字”就认定模块缺失。某些驱动可能直接编进内核,文件名也可能和预期不同。更可靠的做法是对比:
lspci-k以及旧内核对应 initramfs 的内容。
4.5 重新生成 GRUB 菜单
sudoupdate-grub正常情况下会看到类似输出:
Found linux image: /boot/vmlinuz-... Found initrd image: /boot/initrd.img-...如果只找到内核镜像,却没有对应 initrd,应先回头解决 initramfs 生成错误。
五、检查根文件系统 UUID、fstab 和启动参数
5.1 核对真实 UUID
lsblk-f或者:
sudoblkid查看系统配置:
cat/etc/fstab重点核对:
- 根分区
/; /boot;/boot/efi;- swap 或
resume=对应分区; - 额外数据盘。
UUID 发生变化的常见原因包括克隆磁盘、恢复快照、重建文件系统、调整 LVM、替换硬盘和手工改分区。
尽量不要在 fstab 中长期写死
/dev/sdaX、/dev/nvme0n1pX。设备枚举顺序变化后,名称可能改变,而 UUID 通常更稳定。
5.2 检查 GRUB 传递的root=
grep-n"linux.*root="/boot/grub/grub.cfg|headgrub.cfg一般由工具生成,不建议直接长期手改。应修正/etc/default/grub、/etc/fstab或相关脚本,再执行:
sudoupdate-grub5.3 在 GRUB 中临时修改参数
在 GRUB 菜单选中启动项后按e,找到以linux开头的一行。
常用的临时诊断操作:
- 删除
quiet splash,直接观察详细启动日志; - 加入
nomodeset,判断是否卡在显卡模式设置; - 检查
root=UUID=...是否与真实根分区一致; - 检查错误的
resume=、IOMMU、模块黑名单或显卡参数。
临时修改只对本次启动有效,不会自动写回配置。
nomodeset适合帮助进入系统和判断问题方向,但它通常不是显卡问题的最终解决方案。
六、DKMS:为什么新内核装好了,驱动却没跟上
6.1 DKMS 模块与内核版本绑定
NVIDIA、VirtualBox、ZFS 以及部分网卡驱动使用 DKMS。它们并不是跟着内核镜像天然存在,而是要针对每一个内核版本单独构建模块。
检查状态:
dkms status可能看到:
module/version, old-kernel, installed module/version, new-kernel, addedadded、built和installed不是一回事。要让新内核正常使用该模块,目标版本通常需要达到installed状态。
6.2 检查 DKMS 构建日志
日志一般位于:
/var/lib/dkms/<module>/<version>/build/make.log查找所有日志:
sudofind/var/lib/dkms-namemake.log-typef-print查看最近错误:
sudotail-n120\/var/lib/dkms/<module>/<version>/build/make.log常见原因:
- 没安装新内核 headers;
- 驱动版本不兼容新的内核 API;
- 编译器版本或构建环境不匹配;
- Secure Boot 阻止未签名模块;
/boot或/var空间不足;- 包配置流程中断。
6.3 安装 headers 并重新构建
检查 headers:
dpkg-l"linux-headers-$NEW_KERNEL"缺少时安装:
sudoaptinstall"linux-headers-$NEW_KERNEL"重新构建:
sudodkms autoinstall-k"$NEW_KERNEL"完成后重建 initramfs 和 GRUB:
sudoupdate-initramfs-u-k"$NEW_KERNEL"sudoupdate-grub6.4 Secure Boot 也可能让模块“存在但加载失败”
查看状态:
mokutil --sb-state查看内核日志:
sudodmesg|grep-Ei\'secure boot|verification failed|module verification'模块文件已经生成,却仍然无法加载,不一定是编译失败,也可能是签名和信任链问题。
关闭 Secure Boot 不是唯一答案。更合适的方案取决于机器的安全要求、驱动来源以及 MOK 签名流程。
总结
旧内核还能启动时,修复条件其实很好:系统文件、日志和包管理工具都还能正常使用。此时不要急着删除新内核,也不要把所有修复命令一起执行。
更稳的顺序是:
旧内核进入系统 → 保存失败日志 → 检查包与磁盘空间 → 重建 initramfs → 核对 UUID 和 GRUB 参数 → 修复 DKMS → 再测试新内核
完成修复后,至少保留一个已经验证可启动的旧内核。假如旧内核、普通模式和桌面环境都无法进入,就需要转向 initramfs shell、recovery mode 或 Live USB + chroot,具体操作放在下篇。
参考资料
- Ubuntu Kernel:https://ubuntu.com/kernel
- Ubuntu GRUB 2:https://help.ubuntu.com/community/Grub2
update-initramfs手册:https://manpages.ubuntu.com/manpages/jammy/en/man8/update-initramfs.8.html- DKMS:https://github.com/dell/dkms
- Linux Kernel initrd:https://docs.kernel.org/admin-guide/initrd.html