Ubuntu下NVIDIA驱动安装:apt+DKMS最稳,runfile易翻车
简介针对Ubuntu系统安装NVIDIA显卡驱动的常见痛点这份PDF指南给出了清晰、可照做的解决路径尤其适合初学者和需要手动安装驱动的用户。资源共1个文件格式为PDF包体仅489KB内容紧凑、便于随时查阅。文档以GTX970M为例完整覆盖从获取显卡型号、前往NVIDIA官网筛选兼容驱动版本到通过PPA方式安装nvidia-384、重启后验证安装结果的全过程同时针对安装报错、已有驱动冲突、nouveau占用等问题提供了排查建议能有效降低循环登录等安装失败风险。该资料发布以来已有18858人学习下载实用性已得到较多验证。对于在Ubuntu 16.04/17.10等版本上配置NVIDIA驱动的用户这份资料可以作为简洁的起步参考帮助节省搜索和踩坑时间。1. 装 nvidia 驱动翻车的人多半不是装不上而是选错了“简单”的方向在 Ubuntu 下装 nvidia 显卡驱动这件事网上教程永远分成两派一派让你去官网下 runfile 手动装一派让你敲一串 apt 命令。我在某实验室帮同事装过的驱动加起来超过两位数得出的结论和标题一致——真正简单的方法反而被大多数人忽略了。所谓“简单”不是功能最全、也不是性能调得最狠而是让你的机器从开机到跑起 CUDA 程序全程不碰黑屏、不碰循环登录、不碰内核模块手工编译。这篇文章不会让你成为驱动编译专家但会让你避开那些让新手翻车的深水区用最不容易出错的方式把显卡驱动装好、装稳、装到能干活。适合谁刚接触 Ubuntu、被驱动折腾过一次、以及网上教程看得越多越不知道选哪条路的人。2. 三种安装方式对比为什么“简单”两个字最容易被误解2.1 nvidia 驱动在 Ubuntu 里的三种形态如果你搜索过安装教程会发现网上主流方案大致归为三类我先把它们摆出来后面所有操作都围绕这张表展开。安装方式命令/入口优点缺点维护难度图形界面安装“软件和更新”里的 Additional Drivers点几下鼠标就完成系统自动匹配版本无法精细控制驱动分支低apt 命令行安装sudo apt install nvidia-driver-XXX不用上官网自动处理依赖需要自己选择或确认包名低官网 runfile 安装sudo sh NVIDIA-Linux-*.run版本可控可加参数内核模块要自己编译遇到内核升级容易失效高先说结论绝大多数人应该选第一种或第二种而不是 runfile。很多教程之所以推荐 runfile是因为它的“可控性”最强能指定某个 exact 版本、能加--no-opengl-files这类参数。但可控的另一面是你需要自己面对内核头文件、gcc 版本、nouveau 冲突、Secure Boot 签名这些前置条件。每一样单独看都不难叠在一起就是对耐心的极大考验。我见过最典型的翻车现场某开发者在官网下载了最新驱动在 Ubuntu 桌面环境下直接sudo sh执行跑到一半提示“The kernel module failed to build”。原因通常是内核头文件没装或者 gcc 版本和内核编译时用的不一致。而图形界面的安装方式本质上调用的还是 apt 仓库里的驱动包这些包在打包时已经做过了大量兼容性测试Ubuntu 的维护者替你挡住了大部分坑。2.2 判断机器该走哪条路先查硬件和现有驱动状态不管是哪种方式装之前先花五分钟把系统状态摸清楚这五分钟能省下后面几小时。我会依次跑三条命令把显卡型号、当前是否加载了开源驱动、以及系统推荐哪个版本这三个信息拿到手。# 查看显卡硬件型号和 PCI 设备信息 lspci | grep -i nvidia # 查看当前是否已经加载了 nouveau开源驱动或 nvidia 闭源驱动 lsmod | grep -iE nouveau|nvidia # 查看 apt 仓库里有哪些 nvidia 驱动包以及系统推荐版本 ubuntu-drivers devices先说第一条lspci | grep -i nvidia它会输出一行类似VGA compatible controller: NVIDIA Corporation ...的信息括号里的型号就是你的显卡。这个命令的作用是确认系统确实识别到了显卡如果这条命令没有输出说明显卡没插好、PCI 通道被占用或者机器根本是双显卡且 nvidia 卡被屏蔽了。后两种情况先去 BIOS 里确认暂不需要继续装驱动。第二条lsmod | grep -iE nouveau|nvidia很关键。nouveau是 Linux 社区逆向工程出来的开源 nvidia 驱动它和闭源驱动不能共存。如果这条命令输出了大量的nouveau字样说明当前系统正在使用开源驱动装闭源驱动前必须屏蔽它否则两个驱动会抢设备轻则装不上重则开机黑屏。如果输出了nvidia字样说明你已经装过驱动这时候再装一次之前最好先卸载。第三条ubuntu-drivers devices是核心中的核心。它会扫描你的显卡然后列出 apt 仓库里所有可用的驱动版本并标注哪一个是 recommended。我见过很多人在网上问“我该装 470 还是 525”其实 Ubuntu 已经替你选好了看 recommended 那一行就行。2.3 内核模块是怎么被加载的搞明白“装驱动”到底在装什么能帮你理解后续每一步操作的目的。nvidia 显卡驱动不是一个普通的应用程序它分成两部分一部分是用户态的库比如libnvidia-gl、libcuda.so应用程序通过它们调用显卡能力另一部分是内核模块就是nvidia.ko这个文件它负责和显卡硬件直接通信。内核模块必须加载进内核里才能工作。每次开机时系统会去/lib/modules/$(uname -r)/这个目录下找对应的.ko文件然后通过modprobe nvidia之类的方式加载。这就是为什么“升级内核后驱动失效”几乎是必然事件——你的内核从 5.15 升到了 6.2模块目录变了原来编译好的nvidia.ko还在旧内核目录里新内核里没有自然就加载失败。GPU 的工作方式也决定了驱动的特殊性。显卡不像硬盘或网卡那样有一个标准协议每个型号的指令集都有差异驱动必须针对具体型号做适配。这也就是为什么命令行安装时包名里会带着分支号比如 470、525 之类的。这些分支号对应的是不同的硬件代际。理解了这一层你再去看那些“装完驱动重启黑屏”的帖子就能很快定位到问题范围——要么是内核模块没编译成功要么是模块和内核版本不匹配要么是被开源驱动抢占了设备。3. 用“软件和更新”装 nvidia 驱动图形界面下最小的操作路径3.1 先决条件更新系统索引和确认 nouveau 状态图形界面安装听起来是“点鼠标”但点鼠标之前我还是建议先打开终端做两件小事。第一件事是更新软件源索引因为 apt 仓库里的驱动包列表是本地缓存的不更新的话可能看不到最新版本甚至可能因为索引太老而误装一个已经不被当前内核支持的驱动。# 更新软件源索引让 apt 认识最新的驱动包 sudo apt update # 顺便把系统已有的软件包升级一遍避免依赖不匹配 sudo apt upgrade -y第二件事就是重复上一节提到的lsmod检查。如果在输出里看到了nouveau先不要急着进图形界面装驱动。你可以先看后面 5.1 节怎么屏蔽它也可以直接往下走——图形界面的安装流程里Ubuntu 的安装器会自动处理部分 nouveau 冲突但为了获得最稳妥的结果我习惯手动先把 nouveau 屏蔽掉。需要说明的是sudo apt upgrade -y这一步不是必须的但强烈建议。原因是 nvidia 驱动包对内核版本有依赖旧内核上的驱动装完之后一旦系统后续自动升级内核驱动就可能失效。提前把系统升到当前版本可以减少这种滞后性带来的麻烦。3.2 打开 Additional Drivers 选对应版本完成上面的准备后按Super键打开活动概览输入“software”会看到两个入口一个是“Software Center”另一个是“Software Updates”。我们要进的是后者。进去之后切到“Additional Drivers”标签页它会自动扫描硬件几秒钟后列出可用的驱动列表。这个列表长什么样通常会有几项nvidia-driver-XXX (proprietary, tested)、nvidia-driver-XXX-open (proprietary)、以及nouveau (open source)。我的建议是优先选“tested”字样的那一项不要一上来就选 open 版本。-open后缀代表 NVIDIA 的开源内核模块这玩意儿从某个版本之后性能已经追上了闭源模块但兼容性历史更短在 CUDA 生态里也偶尔有玄学问题。生产力环境我一般选“tested”。选中后点击“Apply Changes”系统会开始下载并安装。这个过程和你用apt install是一样的但它会自动处理依赖你不需要手动装nvidia-kernel-common或者dkms这些配套包。安装完成后它会提示重启。重启是整个流程里最容易让新手紧张的一步但只要你前面没有跳过检查步骤基本就是顺滑开机。3.3 验证安装结果和重启后第一件事重启后别急着跑任何程序先打开终端验证三件事。第一件事是确认内核模块加载成功第二件事是确认驱动和 CUDA 运行时能通信第三件事是确认桌面会话还在正常跑。这三件事一条命令就能覆盖大部分# 查看 nvidia 驱动版本、CUDA 版本、显存占用和当前 GPU 进程 nvidia-smi # 如果 nvidia-smi 输出正常再确认模块加载状态 lsmod | grep nvidianvidia-smi如果正常输出你会看到驱动版本号、支持的 CUDA 版本以及一张当前进程表。看到这些你基本上可以放心了。如果这条命令报错NVIDIA-SMI has failed because it couldnt communicate with the NVIDIA driver说明内核模块没有加载成功不要慌先跑lsmod | grep nvidia确认模块在不在。模块在但nvidia-smi失败一般是设备节点权限问题模块不在就要回到后面的排查章节。还有一个细节重启后如果你发现桌面分辨率不正常或者窗口卡顿先不要急着判死刑。可能是因为驱动装好了但显示服务器还没完全切到新驱动上这时注销一次再登录问题通常就消失了。3.4 为什么这个方法对新手最友好图形界面安装最大的价值在于它替你把“依赖关系”这个黑匣子处理掉了。nvidia 驱动包在 Ubuntu 仓库里不是一个孤零零的二进制文件而是一组包的集合nvidia-driver-XXX会依赖nvidia-kernel-XXX、nvidia-utils-XXX、libnvidia-gl-XXX等。手动用 dpkg 或者 runfile 装的时候漏掉任何一个包都可能导致编译失败或者运行报错。另外通过“软件和更新”安装时Ubuntu 会自动启用 DKMS。这意味着以后你升级了内核dkms会自动重新编译 nvidia 模块并放到新内核目录下。这是我推荐这个方案的核心原因——它让“驱动维护”这件事从手工劳动变成了自动化。我在某公司帮 A 同学处理过一次环境问题他装的是官网 runfile三个月后自己升了一次内核重启后发现不仅显卡不工作了连本地软件源的签名都乱了最后花了整个下午才救回来。如果走图形界面这条路那个下午本来可以省掉。4. 命令行路线apt 安装与 DKMS 在升级时的取舍4.1 用 ubuntu-drivers 自动推荐版本不是所有人都喜欢图形界面。有些人拿到的是无桌面版 Ubuntu Server有些人需要通过 SSH 远程装驱动还有些人就是习惯终端操作。这时候命令行安装就是主路。命令行安装的核心命令其实只有两条# 查看你的显卡和系统推荐的驱动包 ubuntu-drivers devices # 直接安装系统推荐的版本推荐命名规则里带 recommended 标注 sudo ubuntu-drivers installsudo ubuntu-drivers install做的事很简单它把ubuntu-drivers devices里 marked as recommended 的包安装上。好处是你不用自己记包名坏处是它装的永远是当前推荐版本如果你需要特定分支比如某个 CUDA 版本只支持特定驱动分支就得自己指定包名。指定包名的命令长这样但记住XXX要替换成你实际想装的版本号# 手动指定驱动分支安装XXX 请替换为具体分支号 sudo apt install nvidia-driver-XXX这里有个关键点nvidia-driver-XXX是虚拟包apt 会把它解析成一组具体的二进制包。所以不要担心自己只装了一个包不够apt 会自动把nvidia-kernel-dkms、nvidia-utils-XXX、libnvidia-gl-XXX这些依赖一起拉下来。装完之后同样重启重启后跑nvidia-smi验证流程和图形界面方案一致。4.2 手动指定驱动版本时怎么避免装错手动指定版本常见于两种情况一种是你有特定 CUDA 版本的要求另一种是你查过 nvidia 官方文档知道某个分支对你的显卡支持得最好。但手动指定也容易翻车最常见的错误是随便选了一个最新分支结果和显卡代际对不上。怎么避免有一个笨但可靠的办法先看ubuntu-drivers devices的完整输出。如果你的显卡年代比较老recommended 往往不是最新分支而是停留在某个更稳定、驱动功能更匹配的版本上。比如某系列老卡最新驱动分支已经停止支持了Ubuntu 仓库里的 recommended 会帮你选到最后一个可用版本。另外一个建议是安装前先查一下分支和显卡的支持矩阵。这种事可以在 nvidia 驱动发布说明里找到打开搜索你的显卡型号看它是否在 Supported Products 列表里。如果不在就别装这个分支。这个步骤听起来繁琐但实际上三分钟就能确认却可以避免你重复经历“装完随机花屏”的折磨。4.3 DKMS 是什么内核升级后驱动不失效的关键DKMSDynamic Kernel Module Support值得单独拿出来讲因为它决定了你的驱动在系统升级后面临什么命运。DKMS 的设计思路很简单当你安装了某个内核模块时它不会只把.ko文件放到当前内核目录而是把模块源码存在/usr/src/下。以后每次系统安装新内核DKMS 都会自动为新内核重新编译一份模块。这意味着什么意味着只要驱动的内核模块源码还在内核从 5.15 升到 6.2你的 nvidia 驱动也会在新内核里重新生成一份可加载的模块。这就是为什么 apt 安装的驱动在内核升级后通常还能正常工作而官网 runfile 安装的驱动却经常失效——runfile 本质上不依赖 DKMS它把模块编译好直接放进当时的内核目录里新内核安装时它不会自动触发重建。验证 DKMS 是否生效的命令# 查看 dkms 管理的模块列表和当前内核下的状态 dkms status如果输出里能看到nvidia/XXX, 6.2.0-XX-generic, x86_64: installed这样的行说明模块已经注册到 DKMS 里并且为当前内核编译好了。如果你用 runfile 装驱动dkms status很可能什么都不会显示这也是判断当前驱动是 apt 装还是 runfile 装的快速方法之一。4.4 从 runfile 切回 apt 版的后悔药如果你已经用 runfile 方式装了驱动现在想切回 apt 版需要两步走。第一步是卸载现有驱动第二步是清理残留文件。直接执行 apt 安装会让两个驱动打架出现各种不可预料的符号冲突。# 第一步如果有 runfile 安装的驱动用官方卸载脚本清除 sudo /usr/bin/nvidia-uninstall # 第二步把 apt 历史遗留的 nvidia 包一起清掉如果之前混装过 sudo apt purge nvidia-* # 第三步清理完检查是否彻底无输出代表干净了 lsmod | grep nvidia执行完这三步之后系统会回到没有闭源驱动的状态。此时如果你重启Ubuntu 会自动加载 nouveau 开源驱动桌面还能用。然后再按 4.1 节的sudo ubuntu-drivers install重新装就能切到 apt 版了。这个“后悔药”的操作顺序很关键先卸载再清理再重装顺序错了容易留下libnvidia之类的残留库导致新装的驱动调用到旧库行为就会变得诡异。5. 黑屏、循环登录、驱动失效5 条高频踩坑与排查5.1 开机黑屏nouveau 没屏蔽的典型症状现象装完驱动重启屏幕亮一下 Logo 就彻底黑了或者卡在紫屏/黑屏界面不动但机器好像还在运行风扇在转。原因nouveau 开源驱动和 nvidia 闭源驱动抢占了同一个设备两个驱动都试图初始化显卡最终导致显示输出失败。解决进恢复模式把 nouveau 屏蔽掉再重新装驱动。# 修改 modprobe 配置把 nouveau 加入黑名单 sudo bash -c echo blacklist nouveau /etc/modprobe.d/blacklist-nvidia-nouveau.conf # 生成新的内核 initramfs让黑名单在开机早期就生效 sudo update-initramfs -u # 移除已加载的 nouveau 模块如果当前还加载着 sudo modprobe -r nouveau我特别强调一下第二行update-initramfs -u。很多人只改黑名单文件不重建 initramfs重启后发现一样黑屏就是因为 initramfs 里已经把 nouveau 模块打包进去了开机早期它还是会被加载。重建之后nouveau 从启动一开始就不会被加载闭源驱动才能独占设备。这个操作在图形界面安装和命令行安装之前做都可以做了它黑屏概率会大幅下降。5.2 循环登录驱动和显示管理器打架现象输入密码后屏幕闪一下又回到登录界面反复循环进不了桌面。有的机器还能看到类似“/dev/nvidia0: No such file or directory”的报错写在某个日志里。原因大部分情况是显示管理器GDM/LightDM启动时加载了 nvidia 模块失败或者加载了不完整的 nvidia 库导致 X server 崩溃重启。解决路径分两步。先按Ctrl Alt F2切到纯命令行 TTY登录后用下面命令查看 X server 日志里的关键错误# 查看 X server 日志里 nvidia 相关的报错方便定位是哪个环节崩了 grep -iE nvidia|drm|failed /var/log/Xorg.0.log | tail -n 40如果报错指向Failed to load module nvidia说明内核模块和 X server 之间的层没对好。常见做法是重装一次nvidia-driver-XXX同时确认配套的libnvidia-gl版本和驱动分支一致。如果报错指向No devices detected则可能是 Secure Boot 把模块挡了看 5.4 节的排查。这个问题的本质是驱动组件的版本一致性图形界面安装不太容易触发但手动指定分支安装时偶尔会遇到。5.3 内核升级后 nvidia-smi 消失现象某次系统更新完之后nvidia-smi报错或者直接提示 command not foundlsmod | grep nvidia也没有任何输出。原因内核升级了新内核目录下没有编译好的 nvidia 模块而驱动没有通过 DKMS 注册所以系统不知道要为新内核重新编译。解决先确认当前驱动是不是 apt 版如果是 apt 版但 DKMS 没生效手动触发一次重建# 查看 dkms 状态确认 nvidia 模块是否存在且已安装 dkms status # 如果模块存在但状态为 built 而不是 installed手动安装到当前内核 sudo dkms install nvidia -k $(uname -r)$(uname -r)会自动取出当前内核版本号比如6.2.0-26-generic。这个命令会把已经编译过的模块注册到当前内核目录下。如果dkms status里根本没有 nvidia 的记录那说明驱动不是 DKMS 方式装的大概率是 runfile 装的老驱动。这时候要么重新跑一遍 runfile安装器会为新内核重编要么干脆按 4.4 节切到 apt 版一劳永逸。这个坑其实是最冤枉的系统升级本来是好意驱动却因此在重启后静默失效。自从我养成了装完驱动后顺手看一眼dkms status的习惯就再没踩过这个坑。5.4 Secure Boot 挡住模块加载现象装机时开启了 Secure Boot驱动装完重启后进系统一切正常但nvidia-smi报Unable to determine the device handle或者模块加载时提示Key was rejected by the kernel。原因UEFI 安全启动只允许加载经过签名认证的内核模块而 apt 仓库里的 nvidia 驱动模块默认不带有被主板信任的签名。解决最省事的办法是进 BIOS 关掉 Secure Boot。不过有些机器关闭后 Windows 引导可能会受影响如果你双系统共存更稳妥的做法是给模块签名。麻烦的是签名需要自己生成私钥并把公钥注册到主板这个流程对新手很不友好我一般建议纯 Ubuntu 单系统就直接关 Secure Boot双系统有顾虑的检查mokutil --sb-state的状态如果显示 enabled再决定是否走注册流程。# 检查 Secure Boot 当前状态 mokutil --sb-state如果显示SecureBoot enabled而你已经装好驱动但模块加载失败最简单的路径是重启进入 BIOS 关闭它然后回来执行sudo update-initramfs -u重建 initramfs。这不算投机取巧Ubuntu 的第三方驱动在 Secure Boot 下本来就是一道附加题普通开发环境没必要在这上面死磕。5.5 PPA 和 runfile 混装的依赖混乱现象驱动装完nvidia-smi能跑但一运行 CUDA 程序就报libcuda.so.XXX: cannot open shared object file或者提示driver version is insufficient。原因系统中存在多个来源的 nvidia 库文件比如你之前加过某个 PPA后来又从官网装过 runfileapt 的 dpkg 数据库里记录的是 PPA 的库而运行时 load 的是 runfile 的库两条链的版本不一致。解决把系统里所有 nvidia 相关的东西全部清理干净然后只从单个来源安装。我的建议是统一走 apt代码已经放在 4.4 节。这个坑的高发人群是喜欢“多教程交叉验证”的探索型用户——A 教程说加 PPA 能拿到新驱动B 教程说官网 runfile 最原汁原味两边都试一遍之后系统自己都分不清该听谁的。清理时有一个细节sudo apt purge nvidia-*的通配符会把很多包一起删掉但不会清理/usr/local/cuda里的内容。CUDA Toolkit 本身不建议通过 apt 卸载它和驱动是两层东西。CUDA Toolkit 的影响面没那么大但如果你之前手动把 toolkit 的libcuda.so链接到系统库目录里那卸载驱动后这个链接会变成悬空跑 CUDA 程序时的报错会很迷惑。所以我建议清理驱动后检查一下/usr/lib/x86_64-linux-gnu/下是否有遗留的libcuda.so*软链接有就用sudo rm清掉避免后续误用。6. 从“装上”到“跑满”验证性能与固化一个验证习惯6.1 nvidia-smi 的完整用法大多数人验证驱动就是跑一下nvidia-smi看到版本信息就关机走人。这个习惯不算错但不够。nvidia-smi最值钱的参数是-l它可以每间隔几秒刷新一次实时状态让你在跑负载时直接看到 GPU 利用率、显存占用、温度和功耗的变化。# 每 2 秒刷新一次 GPU 状态适合跑程序时实时观察 nvidia-smi -l 2 # 和系统监控合流查询完整 JSON 格式的状态信息方便写脚本解析 nvidia-smi --query-gpuutilization.gpu,memory.used,temperature.gpu --formatcsv第一条命令适合人肉观察第二条适合写进监控脚本。我一般会在跑模型训练或者渲染任务时挂一个终端窗口执行nvidia-smi -l 2一旦发现某个进程把显存占满但 GPU 利用率只有个位数就能立刻意识到程序可能没有真正用到显卡算力而是把数据搬运卡在了 CPU 侧。6.2 负载是否真正落到 GPU 上驱动装好了不代表你的程序一定在用 GPU。有个快速验证方法用一个带 GPU 加速的矩阵运算库跑一次较大规模的计算同时观察 GPU 利用率。在 Python 里可以这样验证import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0)) a torch.randn(4096, 4096, devicecuda) b torch.randn(4096, 4096, devicecuda) for _ in range(10): c a b torch.cuda.synchronize() print(GPU compute check passed)这段代码先确认 CUDA 可用再在 GPU 上做矩阵乘法。跑这段代码的时候另一侧开着nvidia-smi -l 1如果能看到 utilization 跳到 90% 以上说明驱动和 CUDA 运行时之间整条链路是通的。如果torch.cuda.is_available()返回False但nvidia-smi正常问题大概率出在 CUDA Toolkit 版本和驱动分支不匹配需要去核对分支支持矩阵而不是怀疑驱动装坏了。6.3 把验证装进肌肉记忆最后分享一个我踩过无数次坑后形成的习惯每次升级内核后重启完干的第一件事不是打开浏览器、不是启动开发环境而是跑一条dkms status加一条nvidia-smi。这两条命令加起来不到五秒钟但它们能在我开始工作前就把“驱动是否还活着”这个不确定性清零。有一次我升级完内核后忘了验证直接启动训练任务跑了二十分钟才发现程序一直在 CPU 上跑浪费时间不说机器温度还莫名升高。后来我把这两条命令写成了一个 shell 函数登录终端后敲两个字就能触发检查。自那以后驱动失效变成了一件“开机后立刻知道”的事而不是“程序跑到一半才发现”的事。我给这个方案的评价是如果你使用 Ubuntu 的场景是深度学习、视频编解码或日常 GPU 计算那么图形界面或 apt 路线已经覆盖了绝大部分需求。官网 runfile 留给那些需要特定分支、或者在做驱动定制的人就好普通人用它只会增加维护成本。希望这篇文章帮你把驱动这件事从“玄学”变成“日常操作”装一次就安稳用下去。本文还有配套的精品资源点击获取