声明
和GLM-5.2对话debug的记录总结而来
以下为GLM-5.2总结原文,GLM总结的还是好颠啊,修改了一点(😐)
Ubuntu 更新 NVIDIA 驱动后网卡消失/无法开机的避坑指南
在 Ubuntu 上更新 NVIDIA 驱动后,可能遇到过重启后网卡掉驱动,经过一番排查,发现根因藏在 Ubuntu 的内核包依赖链与版本管理机制中。
本文将复盘这次问题的发生路径,剖析背后的原理,并给出一套“闭眼更新”的终极安全方案。
一、 问题复现与快速诊断
1. 故事的开端:一次寻常的驱动更新
在 Ubuntu 22.04 机器上,为了支持新显卡,我执行了:
1
| sudo ubuntu-drivers install
|
系统提示安装成功,顺带更新了一批内核相关的包。当时并未在意,直接重启。结果重启后, nvidia-smi 能用,但网卡彻底消失了(无网络连接),而另一次类似的操作后,系统直接进不去了(Kernel Panic / 卡在 initramfs)。
2. 快速诊断与情景发现
在通过 GRUB 的 “Advanced options” 强制启动旧内核(幸好旧内核还在)恢复网络后,我开始排查问题。通过 dpkg -l 查看内核包状态,发现了两个致命问题:
问题 A:网卡丢失的元凶 —— linux-modules-extra 缺失
Ubuntu 的内核驱动分为三个包:
linux-image:内核镜像本体。
linux-modules:核心模块(如基础文件系统、调度器)。
linux-modules-extra:额外模块(包含 r8169、iwlwifi 等绝大多数网卡驱动和额外文件系统支持)。
ubuntu-drivers install 依赖预编译的 linux-modules-nvidia-xxx 包,该包只硬依赖 linux-image 和 linux-modules。**它不会主动拉取 linux-modules-extra**。新内核启动时找不到网卡驱动模块,自然就断网了。
问题 B:无法开机的元凶 —— 跨大版本源污染
在尝试离线修复时,我误从 Ubuntu 24.04 (noble) 的机器上下载了同版本号(6.8.0-134)的 .deb 包,强装到了 Ubuntu 22.04 (jammy) 机器上。
- Noble 包版本号:
6.8.0-134.134
- Jammy 包版本号:
6.8.0-134.134~22.04.1
虽然主版本号一样,但底层 ABI 和签名链不完全兼容,导致新内核启动时直接崩溃。
二、 破局修复:清理污染与补齐模块
如果你也遇到了类似问题,可以通过以下步骤在旧内核下进行修复:
在grub界面通过Advanced选项用旧内核启动。
1. 清理错误的内核包
彻底卸载被污染的 134 内核三件套(包括不匹配的 noble 版本):
1 2 3 4
| sudo apt purge linux-image-6.8.0-134-generic \ linux-modules-6.8.0-134-generic \ linux-modules-extra-6.8.0-134-generic sudo apt --fix-broken install
|
2. 重新安装正确的 HWE 内核全家桶
让 apt 从 22.04 的官方源中重新拉取带有 ~22.04.1 后缀的包,并确保 linux-modules-extra 被一并安装:
1 2 3 4 5 6 7 8
| sudo apt install \ linux-image-6.8.0-134-generic \ linux-headers-6.8.0-134-generic \ linux-modules-6.8.0-134-generic \ linux-modules-extra-6.8.0-134-generic \ linux-modules-nvidia-595-open-6.8.0-134-generic \ linux-image-generic-hwe-22.04 \ linux-headers-generic-hwe-22.04
|
3. 强制重建 initramfs 与 GRUB
内核包更新后,必须重新生成 initramfs,否则极易启动失败:
1 2
| sudo update-initramfs -u -k 6.8.0-134-generic -t sudo update-grub
|
重启后,在 GRUB 手动选择 134 内核,网卡和显卡将同时恢复正常。
三、 终极防御:构建安全更新自动化
1. 配置 GRUB 记忆启动项(忽略。。。)
让 GRUB 记住你上次成功启动的内核。如果新内核崩溃,重启后会自动退回旧内核;如果新内核成功,以后就默认走新内核。
1 2 3 4 5 6
| sudo sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/' /etc/default/grub grep -q '^GRUB_SAVEDEFAULT' /etc/default/grub || \ echo 'GRUB_SAVEDEFAULT=true' | sudo tee -a /etc/default/grub sudo sed -i 's/^GRUB_TIMEOUT_STYLE=.*/GRUB_TIMEOUT_STYLE=menu/' /etc/default/grub sudo sed -i 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=5/' /etc/default/grub sudo update-grub
|
2. 编写 safe-reboot-check.sh 检查脚本
该脚本会在你更新驱动/内核后、重启前自动运行,检查并补全缺失的模块和 initramfs。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #!/bin/bash set -e echo "===== 内核安全检查 ====="
LATEST=$(ls /lib/modules/ | sort -V | tail -1) CURRENT=$(uname -r) echo "当前运行内核: $CURRENT" echo "系统最新内核: $LATEST" if [ "$LATEST" = "$CURRENT" ]; then echo "⚠️ 当前已运行最新内核,无需检查。" exit 0 fi
echo "" echo "===== 检查 $LATEST 的模块包 =====" for pkg in linux-image linux-headers linux-modules linux-modules-extra; do if dpkg -s "${pkg}-${LATEST}" >/dev/null 2>&1; then VER=$(dpkg -s "${pkg}-${LATEST}" | awk '/^Version:/{print $2}') echo " ✅ ${pkg}-${LATEST} ($VER)" else echo " ❌ ${pkg}-${LATEST} 缺失!" MISSING=1 fi done if [ -n "$MISSING" ]; then echo "" echo "🔧 正在补装缺失的包..." sudo apt install -y \ linux-image-${LATEST} \ linux-headers-${LATEST} \ linux-modules-${LATEST} \ linux-modules-extra-${LATEST} fi
echo "" echo "===== 检查 initramfs =====" if [ -f "/boot/initrd.img-${LATEST}" ]; then SIZE=$(stat -c%s "/boot/initrd.img-${LATEST}" 2>/dev/null || echo 0) if [ "$SIZE" -gt 1000000 ]; then echo " ✅ initrd.img-${LATEST} 存在 ($((SIZE/1024/1024))MB)" else echo " ⚠️ initramfs 过小,重新生成..." sudo update-initramfs -c -k "$LATEST" fi else echo " ❌ initramfs 不存在,正在生成..." sudo update-initramfs -c -k "$LATEST" fi
echo "" echo "===== 检查旧内核兜底 =====" if dpkg -s "linux-image-${CURRENT}" >/dev/null 2>&1; then echo " ✅ 旧内核 ${CURRENT} 仍在,可作退路" else echo " ❌ 旧内核 ${CURRENT} 已被删除!没有安全网了" echo " 建议: sudo apt install linux-image-${CURRENT}" fi echo "" echo "===== 检查完成 =====" echo "💡 重启后请在 GRUB Advanced 中手动选 ${LATEST} 验证。" echo " 如果失败,选回 ${CURRENT} 即可。"
|
3. 日常安全更新 SOP(标准作业程序)
以后更新驱动,只需遵循这三步:
1 2 3 4 5 6 7
| sudo ubuntu-drivers install
chmod +x safe-reboot-check.sh ./safe-reboot-check.sh
sudo reboot
|
总结
Ubuntu 的包依赖机制虽然强大,但在处理内核与驱动的复杂关系时仍有盲区(如 linux-modules-extra 不被强依赖)。跨大版本(如 22.04 和 24.04)安装内核包更是大忌。
通过理解依赖链的运作方式,并配合安全检查脚本与GRUB 兜底机制,我们可以放心地进行内核和驱动的升级,彻底告别“升级一时爽,重启火葬场”的困境。