1. 先把“装驱动”这件事拆开看
Ubuntu安装NVIDIA显卡驱动的难点从来不是敲几条命令,而是你得先弄清楚系统里到底有几个东西在抢同一块显卡的控制权。我见过太多人上来就apt install nvidia-driver-xxx,装完重启直接黑屏,然后开始怀疑人生。其实问题在装之前就埋下了:开源驱动 nouveau 已经被内核加载、闭源模块跟当前内核版本没对上、Xorg 的配置还停留在旧驱动上,这三件事任何一件没处理干净,重启就是灾难现场。
所以这篇内容我不打算给你一个“万能命令”,而是按我自己的习惯,把整个过程拆成勘察、决策、执行、验证、回滚五段。适合的人群很明确:手上有一台装 Ubuntu 的台式机或笔记本,需要跑图形渲染、深度学习训练、视频剪辑加速,或者干脆是显示器分辨率卡在 1024x768 调不上去;也包括那些买了新卡插上机器发现风扇狂转但屏幕没信号的。看完你至少能做到两件事,一是知道自己的卡该装哪个分支而不是随便挑个最大的版本号,二是在装崩之后能在十分钟内把系统救回来。
我在不同机器上折腾这个流程的次数已经数不清了,从十年前的 Kepler 老卡到最近的 Ada 架构,踩过的坑高度集中在几个固定位置,后面会逐条讲。先把底层关系理清楚,这是后面所有判断的基础。
1.1 nouveau、闭源模块与内核的三方关系
Ubuntu 装完之后,显卡默认由内核自带的 nouveau 驱动接管,它是开源的、逆向出来的、能点亮屏幕但性能基本为零的驱动。这个“能点亮”很关键,它保证了你在装闭源驱动失败时还有救命的图形界面或者至少一个可用的 TTY。但反过来,它也是冲突的源头,因为 nouveau 和 nvidia 闭源模块都要占用同一个 PCI 设备的驱动绑定位置,内核同一时刻只能挂一个。
闭源驱动在 Ubuntu 上以两种形态存在:一是仓库里的 deb 包,模块由 DKMS 机制在每次内核更新时自动重新编译;二是官方下载的.run文件,装的时候现场编译一次,之后内核换了它不会自己管自己。这两种形态的差异决定了后面维护成本的巨大差别,很多人图省事下了.run,半年后一次内核升级直接进不了图形界面,原因就在这里。
还有个容易被忽略的角色是nvidia-drm。较新的驱动把 KMS(内核模式设置)能力交给了这个模块,它在启动早期就要接管显示输出。如果初始化顺序不对,或者 initramfs 里没把它打进去,表现就是启动过程走到一半画面冻结、只剩一个光标在闪。所以“装完驱动要update-initramfs -u”这句话不是仪式感,是真的有物理意义。
1.2 版本三角:显卡架构、内核、CUDA 谁先定
绝大多数人的困惑是:仓库里躺着 470、535、550、570 好几个分支,到底装哪个?答案取决于三个约束条件的交集,而这三个条件的优先级是有顺序的。
第一优先是显卡架构。每一代驱动分支都会在某个时间点停止支持老架构,比如 Kepler 架构最后能用的分支停在 470 系列,Maxwell 和 Pascal 在 535 之后逐步退出。你要是给一张 GTX 750 Ti 硬装最新分支,包能装上,但模块加载时会直接报“no kernel module for this device”,然后退回 nouveau,你会以为装成功了。
第二优先是内核版本。闭源模块是外部模块,必须针对具体内核头文件编译。Ubuntu 的 HWE 内核更新比较激进,有时候最新驱动分支还没适配最新内核,编译就失败。这时候降内核或者退一个驱动分支都比硬扛省事。
第三优先才是 CUDA。如果你是为了跑训练,CUDA 工具链会声明一个最低驱动版本要求,比如 CUDA 12.x 一般要求 525 以上。反过来,驱动版本是可以向下兼容旧 CUDA 的,所以“驱动装新一点、CUDA 按框架要求选”这个策略通常不会错。需要注意的是,装了.run格式的驱动再单独装 CUDA 的.run,很容易把系统里两套驱动文件搞混,这个坑我后面会专门讲。
把这三个条件的判断做在前面,能省掉后面至少两小时的排障时间。我一般会先在纸上写下“卡型号 → 支持的最高分支 → 当前内核版本 → 是否有对应编译好的 deb”,四个信息凑齐了,方案基本就唯一了。
1.3 三类使用场景决定了完全不同的装法
同样叫“装驱动”,桌面用户、深度学习工作站、无头服务器这三类机器的做法差得很远,不能一套流程走到底。
桌面用户追求的是稳定和少折腾。这种情况我强烈建议走 Ubuntu 官方仓库的 deb 包加 DKMS,因为内核一升级它会自己重新编译,你什么都不用管。代价是仓库里的版本通常比官方最新版落后一两个小版本,但对日常使用毫无影响。真要追求最新特性再去考虑.run。
深度学习工作站的重点就变成了 CUDA、cuDNN 和驱动三者的版本对齐。这里最常见的错误是“先装最新驱动再装任意版本 CUDA”,结果跑起来报 driver version insufficient。正确顺序是先确认框架需要哪个 CUDA,再由 CUDA 反推最低驱动版本,最后选一个满足要求且比最低版本高一点的驱动分支。
无头服务器的做法又不一样,它压根不需要 Xorg、不需要 OpenGL 库,只需要内核模块和计算运行时。这种情况下装完整驱动包纯属浪费空间,还会带来一堆不必要的显示相关依赖。服务器上我一般只装计算部分,顺带把持久化模式打开,避免每次调用都要重新初始化设备上下文。
这三种场景在后面各有对应的实操章节,你可以直接跳到符合自己情况的那一节。但无论哪种,下一章的前置检查都必须做,不能跳。
2. 动手前的勘察与兜底准备
2.1 用五条命令摸清家底
在敲任何安装命令之前,我习惯先跑一轮信息采集,把机器的实际情况摸清楚。这几条命令都很轻,不改任何东西,但能避免后面 90% 的选错版本问题。
第一条看显卡型号和当前驱动绑定状态:
lspci -nnk | grep -A 3 -i vga输出里最关键的是Kernel driver in use:这一行。如果显示nouveau,说明开源驱动正占着位置;如果显示nvidia,说明闭源驱动已经生效,你可能是来升级或者排查问题的;如果什么都不显示,那可能是这台机器的显示输出走的是核显,独显处于未初始化状态,笔记本上很常见。
第二条看系统版本和内核:
lsb_release -a && uname -r内核版本这个信息一定要记住,后面判断 DKMS 编译能不能成功全靠它。Ubuntu 的 LTS 版本每隔一段时间会推送 HWE 内核,可能你装系统时是 5.15,某次更新后就变成 6.5 了,驱动分支的兼容列表跟着变。
第三条看仓库里到底有哪些可用分支:
ubuntu-drivers devices这条命令会列出所有检测到的设备,以及仓库里推荐的驱动包名,最后通常还会跟一句driver : nvidia-driver-XXX - distro non-free recommended。这个 recommended 是 Ubuntu 根据你的卡型号和系统版本算出来的,可信度很高,但不要盲从,先看一眼它的版本号是否满足你其他需求(比如 CUDA)。
第四条确认当前是否有残留的旧驱动文件,很多人机器上其实装过一半失败了:
dpkg -l | grep -i nvidia如果输出里有一堆rc状态(已卸载但残留配置)或者版本号互相冲突的包,那就得先清理干净再装新的。带rc的包虽然不影响运行,但会让新装的包在某些配置文件上产生冲突,属于典型的“看起来没问题、实际有隐患”。
第五条看一眼 Secure Boot 状态,这个后面 2.3 会详细说:
mokutil --sb-state把这五条命令的输出记下来,尤其是显卡型号、内核版本、推荐分支这三个,后面选方案就直接照着填。我习惯把它们贴在一个临时文本里,配置崩了进不去桌面时,靠手机拍的照片也能快速判断该回滚什么。
2.2 给系统留一条后路
装显卡驱动是所有 Linux 日常操作里最容易把图形界面搞挂的一类,所以兜底手段必须在动手前就准备好,而不是出事之后现场想办法。
最基础的兜底是确认 TTY 可用。在图形界面还正常的时候,按Ctrl+Alt+F3到F6试试能不能切到一个纯文本登录界面。能切进去并且能登录,说明系统底子是好的,最坏情况也只是图形界面起不来,你还能通过命令行修复。这一步很多人从来没试过,真出事的时候才发现键盘组合键没反应,只能长按电源键。
第二层兜底是准备一个 Ubuntu 的 Live USB。不用特意做,平时装机用的那个就行。它能让你在系统完全进不去的情况下挂载硬盘分区、检查日志、甚至 chroot 进去修复。我自己的 U 盘常年插在抽屉里,虽然一年用不上一次,但用上的那一次能救回整台机器。
第三层是系统快照。如果你用的是 btrfs 或者 zfs 根分区,装驱动前打一个快照,出事直接回滚,三十秒解决。如果是 ext4,可以用 timeshift 之类工具做一次系统备份,或者至少把/etc/X11/、/etc/modprobe.d/、/etc/default/grub这三个目录下的文件复制一份出来。这三个位置是驱动安装最容易改动的地方,恢复它们往往就能让系统重新进桌面。
第四层是记下当前内核版本号。万一新驱动导致内核模块加载失败,你可以在 GRUB 菜单里选择旧内核启动,然后在旧内核下卸载驱动。Ubuntu 默认会在 GRUB 的“Advanced options”里保留两三个历史内核,这是个很实用的救命通道,别把它清理掉。
提示:动手之前务必确认你能用 root 权限登录 TTY,有些系统配置了自动登录,反而让你忘了自己的密码。这条听起来很傻,但我确实遇到过。
2.3 Secure Boot 与 nouveau 黑名单的取舍
这两个东西经常被教程一句话带过,但它们是两类不同的失败原因,得分开理解。
Secure Boot 是固件层面的校验机制,它只允许加载有签名的内核模块。闭源驱动模块是没有官方签名的(部分发行版做了签名但覆盖不全),所以在开启 Secure Boot 的机器上装完驱动,模块会被拒绝加载,表现就是nvidia-smi报 "No devices were found" 或者干脆模块没加载。处理方式有两种:一是在 BIOS 里关掉 Secure Boot,简单粗暴,代价是失去这层保护;二是走 MOK 签名流程,安装过程中会弹出一个蓝底白字的界面让你设置密码,重启后在同样的界面里输入密码完成注册。第二种方式更规范,但流程繁琐,而且不同主板厂商的界面细节有差异。
我的实际取舍是:个人开发机直接关掉,省事;如果是别人托管的机器或者有安全要求的,就走 MOK。判断标准很简单,看mokutil --sb-state输出是 enabled 还是 disabled,enabled 就得处理,disabled 可以跳过。
nouveau 黑名单则是另一个层面的问题。即使你装好了闭源驱动,如果 nouveau 在启动早期先一步抢占了设备,闭源模块就加载不上。所以安装流程里通常会有一步生成/etc/modprobe.d/blacklist-nouveau.conf,内容是把 nouveau 加入黑名单,然后update-initramfs -u让这个设置进入启动镜像。
这里有个细节很多人做错:只在/etc/modprobe.d/里写黑名单是不够的,因为 nouveau 可能在 initramfs 阶段就已经被加载了,而 initramfs 是独立于根文件系统的一个小镜像。必须执行update-initramfs -u重新生成,黑名单才会真正生效。另外,部分系统上内核命令行里还带着nouveau.modeset=1之类的参数,那得去改 GRUB 配置并update-grub。判断方法很简单,装完驱动重启后如果lsmod | grep nouveau还有输出,说明没黑干净。
还有一种情况是装驱动前忘了黑 nouveau,结果安装程序检测到 nouveau 占用设备直接拒绝安装,报错信息大意是 "You appear to be running the NVIDIA driver from the nouveau driver"。遇到这个不用慌,按上面的方法黑掉、重启进文本模式、再装一次就行。
3. 四种安装路径的完整实操
3.1 路径一:ubuntu-drivers 自动推荐,最省心但要看版本
如果你对自己的需求没有特殊要求,只是想让显示器正常分辨率、跑个普通的图形应用,这条路是最优解。它背后的逻辑是 Ubuntu 维护了一份“显卡型号到驱动分支”的映射表,结合你当前的内核版本挑出一个兼容性最好的包,用 DKMS 管理模块编译。
具体操作分两步。先看推荐结果:
ubuntu-drivers devices输出里会有一行带recommended标记的,记下那个包名。然后执行自动安装:
sudo ubuntu-drivers autoinstall它会把推荐包和所有依赖一起装上。如果你像固定某个具体版本,也可以手动指定:
sudo apt install nvidia-driver-535装完之后不要立刻重启,先执行一次 initramfs 更新,让黑名单和模块信息进入启动镜像:
sudo update-initramfs -u然后重启。这条路最大的优势是后续维护零成本,每次内核更新 DKMS 会自动重新编译模块,编译失败的话系统会在下次启动时自动回退到上一个能用的模块,不会直接把你锁在门外。
但它的局限也很明显:版本受仓库限制。Ubuntu 22.04 的仓库里可能最高只有 535 分支,而你需要 550 才支持的某个特性,那就得换路径二或路径三。另外,如果你之前手动装过.run包,ubuntu-drivers的检测可能会被干扰,得先彻底卸载干净。
我的习惯是先跑这条路,装完验证一下版本号是不是满足需求,不满足再换方案。因为 deb 包的安装和卸载都是干净的,来回切换成本很低,比一上来就整.run安全得多。
3.2 路径二:apt 指定分支手动安装
路径一是让系统替你选,路径二是你自己选。适用于你已经查清楚需要某个特定分支,而仓库里恰好有这个包的情况。命令本身和路径一的小节一样,区别在于你要自己承担选错版本的责任。
选分支的判断逻辑我按优先级排一下:显卡架构支持的范围内选一个较新的分支,再确认这个分支的驱动支持你需要的 CUDA 版本,最后看这个分支有没有针对当前内核编译好的包。这三步里最容易出错的是第三步,仓库里的包名通常不带内核信息,但装的时候 DKMS 会现场编译,如果内核太新,编译会失败。
编译失败的表现很有特征,apt install过程本身是成功的,但重启后nvidia-smi报错,dmesg | grep -i nvidia里能看到 "module verification failed" 或者 "Unknown symbol" 之类的信息。这时候不要急着删了重装,先看一眼/var/lib/dkms/nvidia/版本号/build/make.log,编译错误的具体原因都在这份日志里。常见的是缺少内核头文件:
sudo apt install linux-headers-$(uname -r)装上头文件再重新编译一次就行:
sudo dkms autoinstall还有一种情况是内核版本太新,驱动源码里引用了已经被移除的内核 API,那就没救了,只能退内核或者等驱动更新。这也是我为什么强调装之前一定要记下内核版本。
装完后同样要update-initramfs -u再重启。重启后第一件事是跑nvidia-smi,正常的话会输出一张表格,包含驱动版本、CUDA 版本、显卡型号、显存占用等信息。同时跑一下lsmod | grep nvidia,应该能看到nvidia、nvidia_modeset、nvidia_drm、nvidia_uvm几个模块,缺nvidia_uvm的话 CUDA 跑不起来,缺nvidia_drm的话显示可能有问题。
3.3 路径三:官方 .run 包安装,含内核模块编译细节
这条路适合两种情况:仓库里的版本太旧满足不了需求,或者你干脆想完全自己掌控版本。代价是后续每次内核更新你都得手动重新编译一次,这是一个必须提前接受的心理成本。
第一步是准备编译环境。.run包安装时会现场编译内核模块,所以 gcc、make、内核头文件一个都不能少:
sudo apt install build-essential dkms linux-headers-$(uname -r)第二步是彻底卸载已有的驱动,包括仓库装的 deb 包和更早的.run包。这一步不能省,两套驱动文件混在一起是后面很多诡异问题的根源:
sudo apt purge '^nvidia-.*' '^libnvidia-.*' sudo apt autoremove第三步是处理 nouveau,前面 2.3 讲过,这里给出完整配置:
sudo tee /etc/modprobe.d/blacklist-nouveau.conf <<'EOF' blacklist nouveau options nouveau modeset=0 EOF sudo update-initramfs -u第四步是切到纯文本模式再装,因为在图形界面运行安装程序会导致 Xorg 正在使用显卡,模块替换会失败。切 TTY 之后停掉显示管理器:
sudo systemctl stop gdm3不同系统上可能是lightdm或sddm,用systemctl status display-manager可以确认。
第五步是给安装文件加执行权限并运行。这里有一组参数值得说清楚,很多人是照抄来的但不知道含义:
chmod +x NVIDIA-Linux-x86_64-*.run sudo ./NVIDIA-Linux-x86_64-*.run --dkms --no-x-check --no-nouveau-check--dkms让安装程序注册 DKMS,后续内核更新时能自动重编,这是强烈建议加上的,不加的话内核一升级你就得手动重装一遍。--no-x-check跳过对运行中 X server 的检查,因为你已经停了显示管理器,检查反而是干扰。--no-nouveau-check同理,你已经手动黑掉了 nouvelle,不需要它再检查一遍。另外还有个--no-opengl-files参数,作用是跳过安装 OpenGL 库文件,通常用在服务器或者你想用系统自带的 Mesa 库的场合;桌面用户一般不要加这个参数,加了可能某些图形应用会出问题。
安装过程中会问你要不要注册 DKMS、要不要安装 32 位兼容库,按需回答即可。如果你的系统是纯 64 位且不跑 32 位游戏,32 位库可以不装,能省几百兆空间。
装完重启,验证方式同上。这条路的风险点在于内核更新后忘记重编,表现是某天重启突然掉到低分辨率,nvidia-smi报 "Failed to initialize NVML: Driver/library version mismatch"。这时候不用慌,重新跑一次安装文件,或者用dkms install nvidia/版本号 -k $(uname -r)重新编译就行。
3.4 路径四:无头服务器只装计算组件
服务器场景下这套流程可以砍掉一大半。没有显示器、不需要 Xorg、不需要 OpenGL,只跑训练或者推理任务,那就只装内核模块和计算运行时。
最简的做法是用仓库的 headless 包:
sudo apt install nvidia-headless-535-server nvidia-utils-535-server带headless的包不包含 Xorg 相关组件和显示相关的配置文件,体积小、依赖少、启动时不会去初始化显示输出。带-server后缀的是长期支持分支,版本更新慢但稳定性好,适合跑那种一跑几周不停的任务。
装完之后做两件配置。一是开启持久化模式,避免每次进程退出后设备上下文被销毁,下次启动要重新初始化,对于频繁调用的小任务能明显降低延迟:
sudo nvidia-smi -pm 1想让它开机自动生效,可以把这条命令写进 systemd 服务或者 udev 规则里,不同发行版细节不同,我这里通常用最简单的一行 systemd oneshot 服务搞定。
二是设置功耗上限,多卡机器上能有效控制温度:
sudo nvidia-smi -pl 250这个数值要根据卡的实际 TDP 来定,不要照抄。设太低会导致性能明显下降,设太高散热跟不上反而会降频。我的经验是从默认值的 80% 开始试,观察一段时间温度稳定在 75 度以下就可以。
服务器上还要注意的一点是,不要装nvidia-driver-xxx这种完整包,它会拖进来一堆 Xorg 依赖,在某些精简版系统上甚至会因为缺少包而安装失败。用 headless 包能避开这些麻烦。
4. 装完不等于装对:验证与调优
4.1 nvidia-smi 输出的六个关键读数
nvidia-smi是判断驱动是否装对的第一道关卡,但很多人只看它有没有报错,忽略了输出里的信息。我一般会盯六个位置。
右上角的Driver Version是实际加载的驱动版本,这个数字必须和你打算装的一致。如果显示的是一个明显更旧的数字,说明系统加载的是残留的旧模块,得清理重来。旁边的CUDA Version是驱动支持的最高 CUDA 运行时版本,注意它不等于你系统里装的 CUDA 工具链版本,很多人在这里搞混,以为自己装的 CUDA 12.4 变成了 12.2,其实只是驱动支持的版本不同。
表格里的Name是显卡型号,要确认和物理卡一致。多卡机器上会列出多行,如果只显示一张但你插了两张,可能是其中一张没被识别,或者 PCI 插槽供电问题。
Fan和Temp是散热状态,装完驱动后风扇转速应该能被系统读取和控制,如果显示N/A,说明风扇控制接口没被接管,用nvidia-settings也调不了转速。这在笔记本上比较常见,通常需要额外的配置。
Perf是性能状态,从 P0 到 P12,P0 是最高性能,空闲时一般是 P8。如果你发现它一直停在 P0 但没跑任务,可能是持久化模式开着或者有进程在占着设备,用nvidia-smi下方会列出占用进程。
Memory-Usage是显存占用,空闲时应该是个很小的数字。如果空闲时就占了几百兆,说明有后台进程在跑,训练前记得清理,不然会遇到显存不足的报错。
还有一个不在nvidia-smi里但同样重要的检查:glxinfo | grep "OpenGL renderer",它告诉你 OpenGL 渲染实际走的是哪块 GPU。笔记本上这里经常显示集成显卡,那是正常的 PRIME 卸载渲染机制,但如果台式机独显机器上也显示核显,说明渲染没交给独显,需要调整。
4.2 笔记本双显卡与 PRIME 卸载渲染
笔记本是显卡驱动问题的高发地,因为大部分机器有两块 GPU,核显负责日常显示省电,独显按需启用。这套机制在 Linux 上叫 PRIME,驱动装好之后还需要额外配置才能让独显真正参与工作。
先看当前模式:
prime-select query可能输出nvidia、intel、on-demand三种。intel是只用核显,独显完全关闭,最省电但性能为零。nvidia是全程用独显,性能最好但耗电,散热压力大。on-demand是默认用核显,需要时唤醒独显,是最平衡的选择。
切换用sudo prime-select nvidia之类的命令,切完要注销重新登录才生效。需要注意的是,模式切换依赖于驱动正确安装,如果prime-select报错找不到配置文件,说明驱动没装对,得回去检查。
on-demand模式下的关键问题是:程序怎么知道要用独显?以启动一个图形应用为例,需要显式指定:
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia 你的程序这两个环境变量分别告诉系统“把这个进程的渲染卸载到独显”和“用 nvidia 的 GL 实现”。不指定的话,程序还是用核显跑。跑训练任务的话通常不需要这个,因为 CUDA 会自己选设备,但如果你的训练脚本里带了可视化窗口,不加这两个变量可能会卡在核显上。
还有一个常被吐槽的问题:装了独显之后笔记本续航断崖式下跌。原因通常是独显没有真正进入休眠,即使prime-select设成了intel或者on-demand,独显可能还在通电待机。检查方法是用nvidia-smi看有没有进程占用,以及用cat /proc/acpi/bbswitch(如果装了 bbswitch)看独显电源状态。彻底解决要看具体机型,有些需要配置内核参数,有些需要调整 ACPI 相关设置,这块各家差异很大,我一般建议先接受这个代价,毕竟能用独显才是主要目的。
4.3 持久化模式与功耗封顶
这两件事在台式机上也值得做,不只是服务器。持久化模式上面提过,作用是让驱动保持设备初始化状态,代价是一直占着一小块显存。桌面用户其实用不太上,因为桌面环境本身一直在用 GPU,但对于那些需要频繁启动短任务的场景(比如批量跑推理脚本),开着能省掉每次几百毫秒的初始化时间。
功耗封顶在台式机上主要是为了控制噪音和温度。具体做法是先看卡的默认功耗:
nvidia-smi -q -d POWER输出里Power Limit就是当前上限。调低用sudo nvidia-smi -pl 数值,数值单位是瓦。我自己的经验是,把功耗降到默认的 75% 左右,性能损失通常在 5% 到 10% 之间,但温度能降十几度,风扇噪音明显变小。对于长期开机跑任务的机器,这个取舍很划算。
想让它开机自动生效,写一个 systemd 服务是最干净的方式:
sudo tee /etc/systemd/system/nvidia-powerlimit.service <<'EOF' [Unit] Description=Set NVIDIA power limit After=nvidia-persistenced.service [Service] Type=oneshot ExecStart=/usr/bin/nvidia-smi -pl 250 [Install] WantedBy=multi-user.target EOF sudo systemctl enable --now nvidia-powerlimit.service注意这个服务必须在驱动加载完成之后执行,After里的依赖要按你系统实际情况调整。如果开机后限制没生效,大概率是执行顺序的问题,看一眼systemctl status的输出就能定位。
5. 故障现场:六个高频问题的排查顺序
5.1 黑屏、循环登录与 TTY 抢救
这三个现象是装驱动翻车最典型的表现,但成因完全不同,处理方式也不一样。
黑屏指的是启动过程走完、应该出登录界面的时候屏幕是黑的,可能有个光标在闪。这通常是显示模块初始化失败,最直接的判断方式是切 TTY,按Ctrl+Alt+F3,如果能切进去看到登录提示,说明系统其他部分都正常,只是图形层挂了。这时候登录进去,先看日志:
journalctl -b -1 -p err-b -1表示上一次启动,-p err只显示错误级别以上的。如果日志里能看到 nvidia 相关的报错,基本就锁定了。临时救急的办法是在 GRUB 里给内核加nomodeset参数启动,这样会跳过显卡的模式设置,用最基础的显示方式进桌面,进去之后再慢慢修驱动。
循环登录指的是输入密码后画面闪一下又回到登录界面,这个现象特别有迷惑性,很多人以为是密码错了。实际原因通常是 Xorg 启动失败后自动重启,或者是用户主目录的权限配置出了问题。判断方法同样是切 TTY 登录,然后看~/.xsession-errors。如果这个文件里有 Xorg 的报错,那是驱动问题;如果是权限相关的报错,那可能是之前用 root 跑过图形程序导致配置文件的属主变成了 root:
ls -la ~ | grep -E 'Xauthority|ICEauthority'属主不对的话改回来就行:
sudo chown $USER:$USER ~/.Xauthority ~/.ICEauthority还有一种是显存或者设备被占用导致的循环登录,nvidia-smi会显示有僵尸进程,杀掉就好。
完全黑屏、连 TTY 都切不进去的情况最麻烦,只能靠 Live USB 救援。挂载根分区后 chroot 进去,卸载驱动或者改 GRUB 参数。这个流程比较长,但只要按照挂载分区、绑定系统目录、chroot、修复的顺序做,一般都能救回来。
注意:切 TTY 的快捷键在不同键盘布局下可能不同,
Fn键组合也有影响。如果Ctrl+Alt+F3没反应,试试加按Fn,或者换成F4、F5。
5.2 内核一升级驱动就掉了
这是.run包安装方式的经典后遗症,也是我建议尽量走 deb 加 DKMS 的核心原因。现象很明确:系统用得好好的,某天自动更新重启后,分辨率掉到很低,nvidia-smi报 "Driver/library version mismatch" 或者干脆说找不到设备。
根因是新的内核版本加载的还是旧内核编译的模块,版本号对不上。检查方法:
uname -r modinfo nvidia | grep vermagic两个输出里的内核版本如果不一致,就确认了。
修复分两种情况。如果你装驱动时加了--dkms参数,那 DKMS 应该会自动重编,但可能因为缺少新内核的头文件而失败,装上头文件重新触发一次即可:
sudo apt install linux-headers-$(uname -r) sudo dkms autoinstall如果没加 DKMS 参数,那就得手动重跑安装文件,而且必须先卸载旧模块:
sudo ./NVIDIA-Linux-x86_64-*.run --uninstall sudo ./NVIDIA-Linux-x86_64-*.run --dkms更省事的做法是干脆换成 deb 包方案,一劳永逸。切换的时候注意先彻底卸载.run装的版本,否则两套文件会打架。
还有一种情况是内核升级后 GRUB 默认启动项变了,启动到了旧内核,但旧内核里没有驱动模块。这种表现是新内核装好了驱动却用不上,检查uname -r是不是你以为的那个版本就行。GRUB 的默认启动项可以用grub-set-default调整,或者直接改/etc/default/grub里的GRUB_DEFAULT。
5.3 速查表:现象、根因、处置
排查的时候我习惯按现象快速定位,下面这张表是我这些年攒下来的高频组合,可以直接对照。
| 现象 | 最可能的原因 | 处置方式 |
|---|---|---|
| 启动黑屏但能切 TTY | 显示模块初始化失败 | 加nomodeset启动,检查journalctl -b -1 |
| 循环登录 | Xorg 启动失败或权限问题 | 检查.xsession-errors和家目录权限 |
nvidia-smi报 "No devices were found" | Secure Boot 拒绝加载模块 | 关闭 Secure Boot 或走 MOK 签名 |
nvidia-smi报版本不匹配 | 内核更新后模块未重编 | dkms autoinstall或重跑安装文件 |
| 分辨率只有 1024x768 | 驱动没生效,退回 nouveau | lsmod | grep nouveau确认后黑名单重启 |
| 训练时报显存不足但显存充足 | 有其他进程占着设备 | nvidia-smi看进程列表,结束残留进程 |
| 笔记本风扇狂转、续航骤降 | 独显未进入休眠 | 检查prime-select模式和独显电源状态 |
| 安装时提示 nouveau 正在运行 | 黑名单未生效或未更新 initramfs | 重新配置黑名单并update-initramfs -u |
| DKMS 编译失败 | 缺少内核头文件或内核太新 | 装头文件,或退回旧内核/旧驱动分支 |
| 图形应用启动崩溃 | 32 位兼容库缺失 | 安装libnvidia-gl-xxx:i386等兼容包 |
这张表不是穷举,但覆盖了我遇到的绝大多数情况。遇到表里没有的,第一反应应该是去看三个地方的日志:journalctl -b、/var/log/Xorg.0.log、dmesg | grep -i nvidia。这三个地方基本能覆盖 95% 的驱动问题。
还有一类问题不在表里,就是“看起来装好了,但性能很差”。这种情况先确认nvidia-smi里的Perf状态在跑任务时是不是 P0,如果不是,可能是功耗限制或者温度墙导致的降频。用nvidia-smi -q -d PERFORMANCE能看到具体原因,常见的是SW Power Cap或者HW Slowdown。前者是设置的功耗上限太低,后者是硬件保护,通常是温度过高,得从散热角度解决。
6. 卸载、回滚与长期维护习惯
6.1 三种安装方式对应三种卸载
卸载不干净是导致后续各种疑难杂症的根源,所以这块必须说清楚。三种安装方式对应的卸载命令完全不同,混用会留下残留。
deb 包安装的卸载最标准:
sudo apt purge '^nvidia-.*' '^libnvidia-.*' sudo apt autoremove sudo apt autoclean引号里的通配符会匹配所有 nvidia 相关的包。执行完之后再检查一遍dpkg -l | grep -i nvidia,正常应该只剩空的。如果还有rc状态的包,用dpkg --purge 包名清掉。
.run包安装的卸载要用安装文件自己:
sudo ./NVIDIA-Linux-x86_64-*.run --uninstall如果安装文件已经删了,那就得手动清理,步骤包括删除/usr/lib/modules/$(uname -r)/kernel/drivers/video/nvidia*、/usr/lib/x86_64-linux-gnu/libnvidia*、/etc/modprobe.d/nvidia*等等,然后update-initramfs -u。这个过程很容易漏文件,所以我建议装.run版本的时候把安装文件留一份在手边,别删。
卸载完之后都要做两件事:恢复 nouveau 黑名单(如果还想用开源驱动),以及重新生成 initramfs:
sudo rm /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u重启后应该能回到装驱动之前的状态。如果卸载后还是黑屏,那可能是残留的/etc/X11/xorg.conf在作怪,这个文件是驱动安装时生成的,里面写死了用 nvidia 驱动,删掉它让系统自动检测就行。
6.2 把驱动版本钉死的几个做法
生产环境或者多人共用的机器上,驱动版本随便变动是灾难。你今天装好的版本,别人一个apt upgrade就给你升到新的,然后某个依赖特定版本的训练脚本就跑不了了。
第一个做法是apt-mark hold:
sudo apt-mark hold nvidia-driver-535这样apt upgrade时会跳过这个包。要解除就unhold。这个方法的局限是它只管住这个包本身,相关的库包如果依赖关系变了还是可能被升级,所以要 hold 一整套。
第二个做法是配置 APT 的版本锁定,在/etc/apt/preferences.d/下写一个优先级规则,把 nvidia 相关包的版本钉住。这个方式更彻底,但写起来稍微麻烦,适合有运维经验的场景。
第三个做法是把整台机器的状态做成镜像。用容器跑训练的团队可以直接把驱动版本和 CUDA 版本写进基础镜像,容器内的环境与宿主机驱动解耦,只要宿主机驱动版本不低于容器要求就能跑。这是目前比较主流的做法,隔离性好,一台机器上能跑多个不同版本需求的团队。
我自己维护的几台机器是这么分的:日常开发机走 deb 加自动更新,不用管;跑长期任务的那台用apt-mark hold钉住版本,除非有明确需求否则不升级;还有一台是纯测试用途,专门用来验证新版本驱动,装崩了就重装系统,反正是测试机。
另外提一句长期维护的建议:装完驱动、验证通过之后,花两分钟把关键信息记录下来,包括显卡型号、驱动版本、内核版本、安装方式、验证命令的输出。半年后你再回来看这台机器,这些信息能帮你快速回忆起来当时是怎么配的。我自己是在~/notes/下按机器名建文件,纯文本记录,比什么都方便。
我个人在实际操作中的体会是,Ubuntu 装显卡驱动这件事,真正花时间的从来不是那几条安装命令,而是装之前的判断和装之后的验证。命令网上到处都是,但“我这台机器该用哪个分支”这个判断,需要你把显卡、内核、用途三个信息对上才行。我见过太多人跳过这一步直接复制粘贴,然后在黑屏的屏幕前面耗掉整个下午。慢一点,先把家底摸清,把后路备好,后面反而快。