Ubuntu 开机 Kernel Panic:HWE 内核升级失败 + NVIDIA DKMS 踩坑实录
环境:Ubuntu 24.04.2 LTS(Noble)· NVIDIA GeForce RTX 4090 · 驱动 570.211.01(DKMS)
时间:2026-07
关键词:
kernel panic、unattended-upgrade、HWE、initrd、nvidia-dkms
写在前面
这台工作站某天突然开机即崩。从 Advanced Options 选了一个旧内核(非 recovery)后,SSH 还能连上,于是把问题从头到尾查清楚并修掉了。
这篇记录的是:现象 → 证据 → 根因 → 修复 → 经验。如果你也在 Ubuntu 上开着无人值守升级,并且装了 NVIDIA 闭源驱动,很可能迟早会碰到同类坑。
一、现象
- 正常开机:直接 kernel panic / 起不来
- GRUB → Advanced options → 选旧内核(没有勾 recovery):可以进系统,网络和 SSH 正常
- 机器用途允许重启,但修复前需要先摸清原因
表面看像"内核坏了",实际更常见的是:默认引导项指向了一个半残的新内核。
二、诊断思路(只读排查)
按这个顺序查,通常很快能定位:
- 当前到底跑的哪个内核、
/boot里有什么 - 上一次/最近的
apt/unattended-upgrade有没有失败 - 新内核是否缺
initrd、包是不是half-configured - 有没有 NVIDIA DKMS / crash 报告
2.1 关键发现
当时系统实际运行的是可用旧核:
text
6.17.0-40-generic
但 /boot 里已经出现了新内核 7.0.0-28-generic,同时:
| 检查项 | 结果 |
|---|---|
/boot/vmlinuz |
指向 vmlinuz-7.0.0-28-generic |
/boot/initrd.img |
指向 initrd.img-7.0.0-28-generic |
initrd.img-7.0.0-28-generic 文件本身 |
不存在 |
linux-image-7.0.0-28-generic |
install ok half-configured |
| GRUB | GRUB_DEFAULT=0,TIMEOUT=0(默认静默进第一项) |
也就是说:默认启动 7.0,但 7.0 的 initrd 根本没生成。 这足以导致开机阶段直接失败;很多用户会把它笼统叫成 "kernel panic"。
2.2 是谁装上的 7.0?
/var/log/apt/history.log 里写得很清楚:
text
Start-Date: 2026-07-21 08:28:49
Commandline: /usr/bin/unattended-upgrade
Install: ... linux-image-7.0.0-28-generic ...
Upgrade: linux-generic-hwe-24.04 ... 6.17.0-40 → 7.0.0-28
Error: Sub-process /usr/bin/dpkg returned an error code (1)
不是人手敲的 apt upgrade,而是 systemd 定时触发的无人值守升级。
对应配置大致是:
/etc/apt/apt.conf.d/20auto-upgrades里APT::Periodic::Unattended-Upgrade "1"apt-daily-upgrade.timer每天自动跑50unattended-upgrades里允许noble/noble-security- 黑名单里本可排除
linux-,但那一行默认是注释掉的 ,所以 HWE 内核元包会被自动升级
2.3 为什么安装会失败?
/var/crash/ 里有一份可读的 NVIDIA DKMS 崩溃报告,核心是:
nvidia-dkms-570(570.211.01)在内核7.0.0-28-generic上编译失败典型报错涉及内核 API 变化(例如
dma_map_ops/map_resource相关)
连锁反应是:
- HWE 元包把系统带到 7.0
- 安装/配置阶段触发 DKMS 给新核编 NVIDIA 模块 → 失败
linux-image/ headers 停在 half-configured- initrd 没有正确生成 ,但
/boot符号链接和 GRUB 默认项已经指向 7.0 - 下次开机默认进 7.0 → 崩
- 选旧的
6.17.0-40→ 正常(旧核上 NVIDIA 模块本来就是好的)
一句话根因:
无人值守升级把 HWE 升到了与当前 NVIDIA 570 DKMS 不兼容的 7.0 内核,安装半残且缺 initrd,又成了默认引导项。
三、修复方案(本次采用的方案 A)
原则很简单:
- 先让机器稳定回到已知可用内核
- 清掉半残的 7.0
- 关掉会再次自动挖坑的无人值守升级
- 把当前可用内核 hold 住,并屏蔽 7.0
注意:下列操作需要 root。生产机操作前先确认有旧内核可回退,并征得重启许可。
3.1 关闭无人值守安全更新
写入 /etc/apt/apt.conf.d/20auto-upgrades:
text
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::Unattended-Upgrade "0";
并禁用相关定时器/服务:
bash
systemctl disable --now apt-daily-upgrade.timer
systemctl disable --now apt-daily.timer
systemctl mask apt-daily-upgrade.service
systemctl mask apt-daily.service
systemctl disable --now unattended-upgrades.service
3.2 用 apt pin 挡住 7.0(可选但推荐)
创建 /etc/apt/preferences.d/block-linux-hwe-7.0.pref
(必须带 .pref 后缀,否则 apt 会直接忽略):
text
Package: linux-generic-hwe-24.04 linux-image-generic-hwe-24.04 linux-headers-generic-hwe-24.04
Pin: version 7.0.*
Pin-Priority: -1
Package: linux-image-7.0.0-* linux-headers-7.0.0-* linux-modules-7.0.0-* linux-modules-extra-7.0.0-* linux-tools-7.0.0-* linux-hwe-7.0-*
Pin: version *
Pin-Priority: -1
3.3 清除半残 7.0 及相关元包
bash
export DEBIAN_FRONTEND=noninteractive
apt-get -y purge \
linux-generic-hwe-24.04 \
linux-headers-generic-hwe-24.04 \
linux-image-generic-hwe-24.04 \
linux-tools-7.0.0-28-generic \
linux-headers-7.0.0-28-generic \
linux-image-7.0.0-28-generic \
linux-modules-7.0.0-28-generic \
linux-hwe-7.0-tools-7.0.0-28 \
linux-hwe-7.0-headers-7.0.0-28
若仍有包卡在 half-configured,可再对单个包强制清理(谨慎使用):
bash
dpkg --remove --force-remove-reinstreq --force-depends <包名>
dpkg --purge --force-remove-reinstreq --force-depends <包名>
清理残留文件(如仍存在):
bash
rm -f /boot/vmlinuz-7.0.0-28-generic \
/boot/initrd.img-7.0.0-28-generic \
/boot/System.map-7.0.0-28-generic \
/boot/config-7.0.0-28-generic
rm -rf /lib/modules/7.0.0-28-generic
3.4 恢复可用内核引导
确认 linux-image-6.17.0-40-generic 仍在,然后:
bash
update-initramfs -c -k 6.17.0-40-generic
# 或
update-initramfs -u -k 6.17.0-40-generic
ln -sfn vmlinuz-6.17.0-40-generic /boot/vmlinuz
ln -sfn initrd.img-6.17.0-40-generic /boot/initrd.img
适当放开 GRUB 菜单,方便以后再翻车时手动选内核:
bash
# /etc/default/grub
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=3
update-grub
3.5 hold 当前可用内核
bash
apt-mark hold \
linux-image-6.17.0-40-generic \
linux-modules-6.17.0-40-generic \
linux-modules-extra-6.17.0-40-generic \
linux-headers-6.17.0-40-generic \
linux-hwe-6.17-headers-6.17.0-40 \
linux-hwe-6.17-tools-6.17.0-40 \
linux-tools-6.17.0-40-generic
3.6 重启验证
重启后确认:
bash
uname -r
# 期望:6.17.0-40-generic
ls -l /boot/vmlinuz /boot/initrd.img
nvidia-smi
systemctl is-enabled apt-daily-upgrade.timer # disabled
apt-mark showhold | grep linux
本次修复后,机器已用 6.17.0-40-generic 正常启动,nvidia-smi 正常,无人值守升级保持关闭。
四、Recovery 还是旧内核?
这类"新内核装坏了导致默认开机失败"的问题:
| 入口 | 建议 |
|---|---|
| Advanced → 旧内核(不要 recovery) | 首选。多用户、可联网、可 SSH、方便跑 apt |
| recovery mode | 兜底。适合根分区只读、需要 fsck、连旧核正常模式都进不去时 |
| Live USB | 上面都不行再上 |
经验法则:先找一个"已知能干活"的旧内核正常启动,再修包;不要一上来就 recovery。
五、一点历史:其实坑埋得更早
回看这台机器 2026 年初的日志,会发现同类问题早就出现过:
- 2026-02-11 :无人值守把 HWE 从
6.14拉到6.17.0-14,dpkg 失败 - 2~3 月 :
linux-image长期half-configured,自动任务天天重试失败 - 3 月中旬:NVIDIA 570 小版本升级也碰过 DKMS 问题
- 当时更多是靠旧内核继续开机,后来某次自动重试碰巧把包状态配平,并没有像这次这样系统性关掉自动升级
所以这次不是"突然第一次坏",而是:
同一个模式(自动升 HWE + NVIDIA DKMS)反复发作;这次刚好撞上 7.0,且缺 initrd,破坏力更大。
六、可复用的排查命令速查
bash
# 当前内核与启动参数
uname -a
cat /proc/cmdline
# /boot 是否缺 initrd、符号链接是否悬空
ls -l /boot/vmlinuz* /boot/initrd.img*
# 包是否半残
dpkg -l 'linux-image-*' | awk '/^i[^i]/ || /half/'
dpkg --audit
# 最近是谁升级的内核
less /var/log/apt/history.log
less /var/log/unattended-upgrades/unattended-upgrades.log
# DKMS / NVIDIA
dkms status
ls /var/crash/
七、经验总结
- Ubuntu Desktop/工作站若装了 NVIDIA DKMS,慎开"自动安装安全更新到内核"。 安全源也会推 HWE 内核元包。
- 内核升级失败最危险的状态不是"没装上",而是"装了一半还成了默认项"。 尤其要盯
/boot/initrd.img-*是否真实存在。 - 开机崩了,优先选旧内核正常模式,而不是 recovery。
- 修完要做三件事:清半残包、修 GRUB/符号链接、阻止再次自动升到不兼容内核。 只"能开机"不够。
preferences.d里的 pin 文件必须用.pref后缀,否则 apt 会忽略。
八、后续可选方向(未在本次执行)
如果你之后仍想跟进 HWE 新内核,更稳妥的路径通常是:
- 先确认 NVIDIA 驱动版本已明确支持目标内核
- 再手动升级内核,观察 DKMS 与 initrd
- 成功后再考虑是否重新打开有限的自动更新(并建议把
linux-加入 unattended 黑名单)
本次选择是:先稳定在 6.17.0-40,关掉自动升级,把记录留下。 对工作站来说,这往往比"永远最新内核"更重要。
附录:问题因果链(简图)
text
apt-daily-upgrade.timer
│
▼
unattended-upgrade
│
▼
linux-*-hwe-24.04 6.17 → 7.0
│
▼
nvidia-dkms-570 编译失败(API 不兼容)
│
▼
linux-image-7.0 half-configured
initrd 未生成,但默认引导已指向 7.0
│
▼
默认开机失败 / kernel panic
│
▼
Advanced 选 6.17.0-40(非 recovery)→ 可修复
记录完毕。若你也遇到"自动更新后开机即崩",先别急着重装:Advanced 里找旧内核,查 /boot 的 initrd 和 dpkg 半残状态,十有八九能救回来。