gongdear

gongdear的技术博客

欢迎大家参观我的博客
  menu
122 文章
89355 浏览
2 当前访客
ღゝ◡╹)ノ❤️

凌晨三点,我的 NVIDIA 驱动"炸"了:一次 Ubuntu 自动更新的惨案与彻底防御

凌晨三点,我的 NVIDIA 驱动"炸"了:一次 Ubuntu 自动更新的惨案与彻底防御

TL;DR

Ubuntu 的 unattended-upgrades 在后台静默升级了 NVIDIA 用户态库,但内核模块没跟上,导致 nvidia-smiDriver/library version mismatch。重装驱动只是治标,四层防护才是治本。


案发现场

机器开着没动,第二天早上 nvidia-smi 直接炸了:


Failed to initialize NVML: Driver/library version mismatch

经典的版本失配。dmesg 里躺着一条关键线索:


NVRM: API mismatch: the client has the version 580.xxx, but NVRM: this kernel module has the version 580.yyy.

用户态的 libnvidia 库被 apt 自动升级到了新版,但内核里的 nvidia.ko 模块还是旧版本——两者对不上,驱动直接拒绝工作。

根因锁定:Ubuntu 默认开启的 unattended-upgrades 服务,在凌晨静默执行了安全更新,把 NVIDIA 的用户态包偷偷升级了。


为什么重装驱动只是治标?

重装驱动(apt install --reinstall nvidia-driver-580)确实能让 nvidia-smi 恢复正常,但下一次自动更新到来时,同样的问题会再次上演。

真正的解决方案是:从源头掐断自动更新,并把关键包锁死。


四层防护体系

Layer 1:锁定内核包

自定义内核系统里没有 linux-image-generic 这类元包,只锁定实际存在的:

sudo apt-mark hold \
  linux-image-7.0.0-31-generic \
  linux-headers-7.0.0-31-generic \
  linux-modules-7.0.0-31-generic

强行锁定不存在的包(如** linux-modules-extra)只会收获一堆 **E: Unable to locate package,没必要。

Layer 2:锁定 NVIDIA 全家桶

sudo apt-mark hold \
  nvidia-driver-580 \
  nvidia-dkms-580 \
  libnvidia-common-580 \
  nvidia-utils-580

这四兄弟必须一起锁,缺一不可——libnvidia-common** nvidia-utils **就是上次半夜偷偷升级的罪魁祸首。

Layer 3:禁用自动更新服务

sudo systemctl stop unattended-upgrades
sudo systemctl disable unattended-upgrades

sudo systemctl stop apt-daily.timer
sudo systemctl disable apt-daily.timer

sudo systemctl stop apt-daily-upgrade.timer
sudo systemctl disable apt-daily-upgrade.timer

三重定时器全部掐断,从 systemd 层面杜绝后台偷跑。

Layer 4:APT 配置文件双重保险

/etc/apt/apt.conf.d/10periodic

APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
APT::Periodic::Unattended-Upgrade "0";

/etc/apt/apt.conf.d/20auto-upgrades

APT::Periodic::Unattended-Upgrade "0";

两层配置文件互相兜底,就算某一层被覆盖,另一层还能兜住。


额外操作:把 Snap 连根拔起

Ubuntu 26.04 的 Snap 生态对追求纯净系统的用户来说过于臃肿,一并清理:

# 批量卸载所有 snap 包(保留 snapd 本身先不删)
sudo snap remove --purge $(snap list | awk 'NR>1 && $1!="snapd" {print $1}')

# 卸载 snapd
sudo apt purge snapd

# 清理残留目录
sudo rm -rf /snap /var/snap /var/lib/snapd /var/cache/snapd ~/snap

# 锁定 snapd 防止被自动装回
sudo apt-mark hold snapd

snap** **命令彻底消失,系统清净了。


最终验证

$ apt-mark showhold
libnvidia-common-580
linux-headers-7.0.0-31-generic
linux-image-7.0.0-31-generic
linux-modules-7.0.0-31-generic
nvidia-dkms-580
nvidia-driver-580
nvidia-utils-580
snapd

$ systemctl is-active unattended-upgrades apt-daily.timer apt-daily-upgrade.timer
inactive
inactive
inactive

$ cat /etc/apt/apt.conf.d/10periodic
APT::Periodic::Update-Package-Lists "0";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "0";
APT::Periodic::Unattended-Upgrade "0";

全部通过。


总结

这套四层防护(包锁定 + 服务禁用 + 配置修改 + Snap 移除)让系统彻底免疫"半夜自动更新搞崩驱动"的问题。以后想更新时手动执行 apt update && apt upgrade,所有被 hold 的包都会被跳过,完全可控。

核心原则 :生产环境 / 工作站机器,永远不要让包管理器在后台静默执行任何操作。一切更新,必须经过你的手。

宝剑锋从磨砺出,梅花香自苦寒来.