从网线插上却没有反应那一刻起,我就知道又要跟网卡驱动打交道了。Ubuntu下有线网卡的问题,说难不难,说简单也绝不简单:有时候是内核自带的驱动不对,有时候是厂商给的源码编译完没生效,还有时候是网卡本身被模块冲突给顶掉了。这篇文章把我这些年折腾各类有线网卡驱动、以及驱动装完后配置系统网络的经验完整整理了一遍,覆盖芯片识别、模块加载、源码编译、netplan配置和故障排查,适合刚把Ubuntu装上发现没法上网的新手,也适合在服务器上遇到过网卡丢失或掉速的老手。
1. 从网线插上却没有反应开始排查
很多人遇到“有线网卡无法上网”后的第一反应,是去网上下载驱动安装包。这个思路本身没错,但如果连网卡芯片是哪家都没搞清楚,下载来的驱动大概率白装。我的建议是:先花两分钟判断问题出在物理层、驱动层,还是网络配置层,不要上来就编译。
1.1 先排除物理层和系统层的干扰
网卡不工作的现象有好几种:网口指示灯完全不亮、指示灯亮但系统里看不到网卡、能看到网卡但拿不到IP地址。这三种情况的排查方向差别很大。
指示灯完全不亮,先换根网线试试,再把网线插到路由器或者交换机的另一个端口。我遇到过很多次“网卡坏了”,最后是网线或者交换机端口的问题。如果换了线和端口仍然不亮,这时候才怀疑网卡硬件或驱动。
系统里看不到网卡,指的是执行ip link或者ifconfig -a时,列表中压根没有类似eth0、enp3s0这样的网口。这种情况大概率是驱动没加载,或者设备被系统禁用了。
能看到网卡但无法获取IP,那是另一类问题,多半和DHCP客户端的配置或网络环境有关,不一定需要动驱动。先把这几个层次分清楚,后面做起来才不至于瞎折腾。
1.2 为什么说“先看芯片,再谈驱动”
网卡能不能用,决定因素是网卡控制器芯片的型号,而不是网线接口的牌子。一块网卡上能看到的是品牌Logo,但真正写入硬件ID的,是板载的以太网控制器芯片。比如主板盒子上可能印着某某网络方案品牌,但实际用的有可能是Realtek、Intel、Broadcom等不同厂商的控制芯片。
搞清楚芯片型号,你才知道该去哪里找驱动。同系列的不同芯片,驱动还是有区别:你以为下载了一个通用驱动包,结果编译时发现根本不支持你的硬件。所以“先看芯片,再谈驱动”这句话,我放在最前面讲,因为它真的能帮你省掉大量时间。
2. 识别网卡芯片:lspci、lsusb 和硬件清单的使用方法
2.1 一条命令精确定位网卡型号
在Ubuntu终端里执行:
lspci -nnk | grep -A 3 -i ethernet这条命令会把PCI设备列表里与以太网相关的行打印出来,-nnk参数的意思是同时显示设备ID和已加载的内核模块。输出通常会是这样:
01:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller [10ec:8168] Subsystem: Realtek Semiconductor Co., Ltd. Motherboard [10ec:8168] Kernel driver in use: r8169 Kernel modules: r8169中间的10ec:8168是设备的vendor ID和device ID,10ec代表Realtek,8168代表具体芯片型号。如果你看到硬件ID但Kernel driver in use显示为N/A,就说明系统没有成功给这块网卡绑定驱动,这就是问题的核心。
如果是USB接口的网卡,则用lsusb查看:
lsusb输出中会列出类似的ID格式,比如0bda:8156,其中0bda是Realtek的USB设备厂商ID,8156是RTL8156的型号。再用lsusb -t可以查看设备挂在哪个USB总线上。
2.2 各厂商有线网卡驱动的获取渠道差异
不同厂商对Linux驱动的开源态度差别很大,这直接决定了你的安装方式。
Intel的绝大多数有线网卡,驱动都已经集成在Linux内核里,比如e1000e、igb、ixgbe这些模块,通常不需要额外装驱动。只要内核版本别太老,即插即用,最多需要安装firmware-linux或linux-firmware软件包来补充固件。
Realtek的情况要复杂一些。老款RTL8111/8168系列用的r8169模块兼容性尚可,但部分主板上会出现掉速、断流、偶尔不识别的问题。Realtek官方也提供源码包,但下载下来需要自己编译,而且版本和内核的匹配经常有坑。不过,新一代的RTL8125/RTL8126 2.5G网卡,在内核5.9以后基本也能用r8169驱动顶住,只有在特定主板型号或追求高性能时才建议用官方的r8125驱动。
Broadcom的有线网卡相对少见,通常出现在一些服务器板卡或老笔记本上,有时候需要tg3模块,配合firmware-bnx2之类的固件包才能正常工作。如果实在找不到驱动,最常见的解决办法是换一块兼容性最好的USB转网卡,而不是继续死磕。
我建议把所有查询结果截图或者记下来,尤其是硬件ID和内核模块名。后面不管是编译源码还是查资料,都要靠这几个关键字段去比对。
3. 三种安装方式:内核自带、源码编译与DKMS封装
3.1 内核模块是否已在内核里
前面lspci -nnk输出中,最后一行Kernel modules: r8169表示这块网卡对应的内核模块名称。你可以先确认模块是否存在:
modinfo r8169如果显示出版本、描述、依赖等一长串信息,说明模块文件已经在系统里了。这时候只需要加载它:
sudo modprobe r8169然后执行ip link确认网卡是否出现。如果modinfo报错说找不到模块,那就说明内核里没有这个驱动,你才需要走源码编译或者安装额外内核模块的路线。
这里有个极易踩的坑:某些驱动模块的名字和芯片系列名完全不匹配。比如RTL8125对应的模块叫r8169,而不是r8125;Intel I225-V网卡对应的模块叫igc,和老的igb不是一回事。网卡能搜索到的最新驱动资料里,如果没搞清楚模块名,后面怎么折腾都是白费。
3.2 厂商源码编译的标准流程
如果你的网卡确实需要厂商驱动,比如某些2.5G/5G网卡,官方会提供一个tar.gz源码包。解压后通常能看到autorun.sh和源码目录,但我不建议直接跑autorun.sh,因为它的过程不可控,装完也不知道加载了哪个模块。我习惯手动编译:
tar -xzf r8125-9.012.02.tar.gz cd r8125-9.012.02 make clean make sudo make install sudo modprobe r8125编译之前必须先安装编译工具链和内核头文件,否则在make那一步就会报一堆找不到头文件的错误:
sudo apt update sudo apt install build-essential linux-headers-$(uname -r)linux-headers-$(uname -r)要装和你当前内核完全一致的版本。很多人以为装一个通用linux-headers-generic就行,但源码编译时真正引用的是/usr/src/linux-headers-$(uname -r)这个具体目录,版本不匹配一样会失败。
编译安装完成后,用modinfo查一下新模块是否被系统识别,再modprobe加载。如果此前模块已经存在,得先卸载旧模块再加载新的:
sudo modprobe -r r8169 sudo modprobe r8125不过,手动编译有个麻烦:每次内核升级之后,模块都需要重新编译。这也是我要单独说DKMS的原因。
3.3 DKMS 让驱动在每次内核升级后自动重建
DKMS(Dynamic Kernel Module Support)的设计目的就是解决内核升级后第三方模块失配的问题。你把源码注册给DKMS,它会在每次安装新内核时自动重新编译并安装模块。
以Realtek官方驱动为例,如果厂商源码包里带了DKMS支持文件,可以直接这样注册:
sudo make dkms_install如果源码包没有现成的DKMS配置,也可以自己手动创建。在源码目录下新建一个dkms.conf:
PACKAGE_NAME="r8125" PACKAGE_VERSION="9.012.02" BUILT_MODULE_NAME[0]="r8125" DEST_MODULE_LOCATION[0]="/kernel/drivers/net/ethernet/realtek" AUTOINSTALL="yes" MAKE[0]="make" CLEAN="make clean"然后执行:
sudo dkms add . sudo dkms build -m r8125 -v 9.012.02 sudo dkms install -m r8125 -v 9.012.02我强烈建议所有非内核自带的网卡驱动都走DKMS。很多服务器管理员遇到过这样的问题:重启机器后发现网卡没了,后来才发现是内核自动更新导致第三方模块丢失。用DKMS之后,这个问题基本不会再出现。
4. 系统层面启用网卡:接口命名、netplan 与 NetworkManager
4.1 网卡命名从 eth0 变成了 enp3s0 的故事
老Linux玩家都习惯看eth0,但在现代Ubuntu上,网卡接口名变成了enp3s0这种格式。这其实是systemd的命名规范:en代表以太网,p3s0代表PCI总线3、插槽0。这么改的目的是保证接口名稳定,不会因为开机顺序变化导致eth0和eth1互换。
如果你不习惯这种命名方式,并不建议强行改回eth0,因为很多现代配置工具已经默认适配新命名规则。你真正需要记住的,是自己机器上的实际接口名。执行一次ip link看清楚,后面的所有配置都以这个为准。
在某些网卡驱动没加载的情况下,接口名压根不出现。所以判断驱动是否成功,最直观的方法就是看ip link里有没有新接口出现。
4.2 用 netplan 配置 DHCP 和静态 IP
Ubuntu从18.04开始默认使用netplan管理网络,配置文件在/etc/netplan/目录下,通常是01-network-manager-all.yaml或者50-cloud-init.yaml。查看当前配置:
ls /etc/netplan/基础配置长这样:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: true改完配置后,执行:
sudo netplan apply配置静态IP时,把dhcp4: true替换成具体地址:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: false addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 223.5.5.5 - 8.8.8.8YAML文件对缩进极其敏感,ethernets下面必须和enp3s0对齐,多一个空格或少一个空格,netplan apply就会报语法错误。碰到配置文件报错时不要慌,执行sudo netplan generate先检查语法,它不会真的改动当前网络,只是验证配置。
有一个容易忽略的地方:如果系统装了桌面版,很大概率渲染器是NetworkManager,而不是networkd。这两种渲染器管理网络的方式完全不同,不能混用。在桌面环境下想用nmcli查看设备状态,应该执行:
nmcli device status如果用的是NetworkManager渲染,静态IP也可以通过nmcli完成:
nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.100/24 nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1 nmcli con mod "Wired connection 1" ipv4.method manual nmcli con up "Wired connection 1"4.3 临时测试不落盘:ip 命令的实战用法
有时候你只是临时测一下驱动是否正常工作,并不想动配置文件。这时直接用ip命令给网卡配地址就行,重启后配置自动消失,相当于临时实验:
sudo ip link set enp3s0 up sudo ip addr add 192.168.1.100/24 dev enp3s0 sudo ip route add default via 192.168.1.1 dev enp3s0检查是否生效:
ip addr show enp3s0 ping -c 4 192.168.1.1这种不落盘的方式特别适合刚编译完驱动后的连通性验证。确认链路通了,再回头写netplan或nmcli配置,能减少很多“驱动其实已经装好,但配置文件有问题导致上不了网”的错觉。
5. 驱动安装后的性能核查与隐患处理
很多人装完驱动,看到ip link里有网卡了,就以为完事大吉。但驱动加载成功不等于网卡工作在最佳状态。我建议再做几项检查,尤其是2.5G以上网卡,这些检查能帮你避免莫名其妙的掉速和断流。
5.1 ethtool 查速率和双工协商
确认网卡能在正确速率和双工模式下工作,使用ethtool:
sudo ethtool enp3s0输出中重点看Speed和Duplex。千兆网卡应该显示Speed: 1000Mb/s,2.5G网卡显示Speed: 2500Mb/s,双工应该为Full。如果显示100Mb/s甚至10Mb/s而不支持更高的自协商速度,首先要怀疑网线质量或交换机端口限制,其次才是驱动设置。
如果驱动本身支持,可以手动指定速率来测试是否稳定,但我不建议长期固定,因为自动协商才是正常状态:
sudo ethtool -s enp3s0 speed 1000 duplex full autoneg off恢复自动协商:
sudo ethtool -s enp3s0 autoneg on另外,ethtool -S enp3s0可以查看网卡统计信息,重点观察rx_crc_errors、tx_errors、rx_length_errors这些计数器。数值持续增长,说明物理链路或驱动有潜在问题。
5.2 MTU、Ring Buffer 与 offload 的常见坑
MTU(最大传输单元)默认为1500,这是以太网的标准值。如果你在跑NAS或者需要传输大包,可以考虑把MTU调高到9000,也就是巨帧模式。但要注意,交换机也必须支持相同MTU,否则会出现“能通但打不开网页”的怪现象。一般来说,普通家用环境不建议乱改MTU。
Ring Buffer是网卡的收发队列缓冲区。某些网卡默认值偏小,高负载时容易丢包,可以调大:
sudo ethtool -G enp3s0 rx 4096 tx 4096不同网卡支持的最大值不同,先用sudo ethtool -g enp3s0查看当前值和上限值再调整。
Offload功能是让网卡硬件分担一部分协议处理工作,比如checksum校验、TCP分段卸载。多数情况下开着是好事,但某些驱动实现得不够完善,在开启GRO/GSO后会出现断流或转发异常。如果你发现网卡在高流量下不稳定,可以尝试关闭卸载功能再对比:
sudo ethtool -K enp3s0 rx-checksumming off sudo ethtool -K enp3s0 tx-checksumming off sudo ethtool -K enp3s0 gro off gso off注意这些命令只对当前会话有效,重启后恢复默认。确认某种配置更稳定后,可以把它写到systemd服务或者netplan的post-up脚本里,确保开机自动执行。
5.3 网络突然掉线的排查链路
网卡时断时续,是很让人崩溃的。我的排查顺序基本固定:
第一步,看物理链路,换线换口排除法,观察网口指示灯是否闪烁正常。第二步,看dmesg日志,执行:
dmesg -T | grep -i "enp3s0\|r8169\|r8125"关注有没有Link is down、Reset adapter、TX timeout之类的字样。TX timeout是驱动层面很典型的异常,多半说明驱动与硬件之间存在兼容问题,或者网卡过热。
第三步,查看中断和IRQ冲突。多网卡设备上,某些驱动默认使用相同的中断号,可能导致收包中断被抢占。这时可以尝试调整irqbalance服务状态:
sudo systemctl status irqbalance sudo systemctl restart irqbalance第四步,检查电源管理。笔记本或者支持节能的主板上,设备可能被自动切换进低功耗状态,导致网卡掉线。用ethtool --show-pause或者查一下网卡的电源管理属性,必要时通过内核参数pcie_aspm=off来关闭PCIe节能:
sudo nano /etc/default/grub找到GRUB_CMDLINE_LINUX_DEFAULT,在引号里追加pcie_aspm=off,然后执行:
sudo update-grub sudo reboot我遇到过一台机器,平时使用一切正常,但只要CPU进入深度休眠再唤醒,网卡必然丢包。加了pcie_aspm=off之后,问题彻底消失。
6. 驱动安装时的Secure Boot签名问题与救援思路
跳过这个坑,会省你至少半小时。现在UEFI主板默认开启Secure Boot,凡是未签名的内核模块,系统都会拒绝加载。你手动编译的第三方驱动,几乎肯定没有签名,所以modprobe时没有任何报错,但模块就是加载不了,或者重启后网卡消失,这类现象十有八九跟Secure Boot有关。
验证方法:
mokutil --sb-state输出如果显示SecureBoot enabled,那就需要使用Machine Owner Key来签名模块。
最简单的临时方案,是在BIOS里关闭Secure Boot,但并不是所有环境都允许这么做。更优雅的做法是用系统自带的工具,将编译好的模块签名后重新安装。方式是对模块文件做签名,在用DKMS安装的模块上,路径一般在/lib/modules/$(uname -r)/updates/dkms/:
sudo kmodsign sha512 /var/lib/dkms/mok.key /var/lib/dkms/mok.pem r8125.ko不过具体文件路径和签名工具在不同系统上略有差异,实际操作时先find /var/lib/dkms -name "*.ko"找到对应模块,再套用签名命令。如果不想处理签名,也可以直接利用Ubuntu的MOK管理功能,在第一次重启时进入蓝色配置界面,登记你生成的密钥。这个流程我在几台机器上走过一遍,确实可行,但对新手来说复杂度不低。
还有一类情况是网卡在安装系统时是好的,但重启之后就没了。这时候不要急着重装系统,先利用Ubuntu安装U盘的“试用”模式启动到Live环境,在Live环境里把硬盘上的系统根目录挂载出来,再用chroot进入系统修复:
sudo mount /dev/sda2 /mnt sudo mount /dev/sda1 /mnt/boot/efi sudo chroot /mnt进入chroot之后,重新安装一遍DKMS模块或者更新initramfs:
sudo update-initramfs -u sudo update-grub然后把Live环境里能用的驱动模块复制到硬盘系统对应目录,重启拔掉U盘,网卡经常就能恢复。
这类“重启掉网卡”的案例,根源基本都是内核版本升级后模块没跟上,或者Secure Boot签名失效。我之前在一台机器上折腾了三天,最后查出来是主板固件里伪造的MAC地址和驱动模块冲突,非常冷门,但这提醒我们:在彻底放弃之前,多看一眼dmesg和BIOS设置总没错。
7. 配置过程中的常见问题快查表
我整理一张速查表,覆盖上面提到的核心故障场景和解决路径,方便你对照处理:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
ip link没有网卡接口 | 驱动未加载或模块缺失 | modinfo查模块,modprobe加载 |
| 模块加载但报错 | Secure Boot阻止未签名模块 | 关闭Secure Boot或使用MOK签名 |
| 网卡显示但无法获取IP | DHCP配置错误或网络环境问题 | 检查netplan配置文件、网线、交换机 |
| 网卡千兆协商成百兆 | 网线质量差或驱动强制速率 | 换线;用ethtool查看协商状态 |
| 高负载掉包 | Ring Buffer太小或offload兼容问题 | 调大ring buffer,临时关offload测试 |
| 重启后网卡消失 | DKMS未安装或内核升级模块失配 | 用DKMS管理第三方驱动 |
| 网卡频繁断流 | PCIe ASPM节能模式 | 内核参数加pcie_aspm=off |
| 编译时报找不到头文件 | 内核头文件版本不匹配 | 安装linux-headers-$(uname -r) |
这张表不能覆盖所有极端情况,但它能覆盖我这些年遇到的八成以上问题。遇到表上没有的情况,我的建议是:不要慌,先用lspci -nnk和dmesg把信息抓全,再考虑下一步。排查驱动问题,最忌讳的就是信息不完整就开始乱改。
最后说一个我个人的体会:网卡驱动安装这件事,熟练之后你会发现,真正花时间的不是编译本身,而是判断“到底该不该编译”。很多网卡在官方仓库里都有现成的固件包,先用apt search firmware和apt search r8168这样的命令查一下,很多时候一行sudo apt install firmware-realtek就能解决问题。官方源码编译永远是最后的选择,而不是第一选择。这和修水管是一个道理,先看看总阀开了没有,再决定要不要拆墙。