前言
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和根文件系统没有错误。
执行自动清理前先看模拟结果:
sudo apt autoremove --dry-run
确认不会删除当前运行内核和唯一可用的旧内核后,再决定是否执行:
sudo apt autoremove
不要在唯一能够启动的内核上做“自动清理实验”。
三、先留证据:不要只盯着最后一屏报错
3.1 查看启动历史
在旧内核中执行:
journalctl --list-boots
输出会列出最近几次启动记录。当前启动通常是 0,上一次是 -1,再上一次是 -2。
查看上一次启动的内核日志:
sudo journalctl -b -1 -k
只看错误级别:
sudo journalctl -b -1 -p err
搜索常见关键字:
sudo journalctl -b -1 -k | grep -ei \ 'panic|error|fail|timeout|nvme|ata|ext4|xfs|btrfs|firmware|nvidia|dkms'
如果故障发生得太早,系统可能还没来得及把日志写进 journal。此时屏幕报错、initramfs shell 中的输出、云服务器串口日志同样重要。
3.2 用当前正常启动作为对照
查看当前旧内核的启动信息:
sudo dmesg -t | less
重点观察存储、根分区、固件和模块:
sudo dmesg -t | grep -ei \ 'nvme|ata|root|firmware|module|secure|iommu'
旧内核能识别、而新内核识别不到的设备,往往就是问题线索。
3.3 检查包管理是否中断
内核升级过程中断电、网络异常或磁盘写满,都可能留下“包已经解压,但还没有配置完成”的状态。
先检查:
sudo dpkg --audit
继续处理未完成配置:
sudo dpkg --configure -a
修复依赖:
sudo apt-get -f install
执行需要下载软件包的命令前,先确认网络和软件源可用。
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 fs
4.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:
sudo update-initramfs -u -k "$new_kernel"
如果对应 initrd 根本不存在,可以创建:
sudo update-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 菜单
sudo update-grub
正常情况下会看到类似输出:
found linux image: /boot/vmlinuz-... found initrd image: /boot/initrd.img-...
如果只找到内核镜像,却没有对应 initrd,应先回头解决 initramfs 生成错误。
五、检查根文件系统 uuid、fstab 和启动参数
5.1 核对真实 uuid
lsblk -f
或者:
sudo blkid
查看系统配置:
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 | head
grub.cfg 一般由工具生成,不建议直接长期手改。应修正 /etc/default/grub、/etc/fstab 或相关脚本,再执行:
sudo update-grub
5.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, added
added、built 和 installed 不是一回事。要让新内核正常使用该模块,目标版本通常需要达到 installed 状态。
6.2 检查 dkms 构建日志
日志一般位于:
/var/lib/dkms/<module>/<version>/build/make.log
查找所有日志:
sudo find /var/lib/dkms -name make.log -type f -print
查看最近错误:
sudo tail -n 120 \ /var/lib/dkms/<module>/<version>/build/make.log
常见原因:
- 没安装新内核 headers;
- 驱动版本不兼容新的内核 api;
- 编译器版本或构建环境不匹配;
- secure boot 阻止未签名模块;
/boot或/var空间不足;- 包配置流程中断。
6.3 安装 headers 并重新构建
检查 headers:
dpkg -l "linux-headers-$new_kernel"
缺少时安装:
sudo apt install "linux-headers-$new_kernel"
重新构建:
sudo dkms autoinstall -k "$new_kernel"
完成后重建 initramfs 和 grub:
sudo update-initramfs -u -k "$new_kernel" sudo update-grub
6.4 secure boot 也可能让模块“存在但加载失败”
查看状态:
mokutil --sb-state
查看内核日志:
sudo dmesg | grep -ei \ 'secure boot|verification failed|module verification'
模块文件已经生成,却仍然无法加载,不一定是编译失败,也可能是签名和信任链问题。
关闭 secure boot 不是唯一答案。更合适的方案取决于机器的安全要求、驱动来源以及 mok 签名流程。
总结
旧内核还能启动时,修复条件其实很好:系统文件、日志和包管理工具都还能正常使用。此时不要急着删除新内核,也不要把所有修复命令一起执行。
更稳的顺序是:
旧内核进入系统 → 保存失败日志 → 检查包与磁盘空间 → 重建 initramfs → 核对 uuid 和 grub 参数 → 修复 dkms → 再测试新内核
完成修复后,至少保留一个已经验证可启动的旧内核。假如旧内核、普通模式和桌面环境都无法进入,就需要转向 initramfs shell、recovery mode 或 live usb + chroot,具体操作放在下篇。
以上就是linux内核升级后启动失败的解决方案的详细内容,更多关于linux内核升级后启动失败的资料请关注代码网其它相关文章!
发表评论