
如果一台 Ubuntu 20.04 默认装了系统网卡叫ens3、enp4s0这类名字而你的业务脚本、防火墙规则、授权文件里全写的是eth0那你大概能理解我为什么非要把网卡名“钉死”成eth0。这篇文章就是把我在 Ubuntu 20.04 上通过 udev 规则修改网卡名称的全过程写清楚包括原理、实操、Netplan 联动以及那些不跑一遍绝对不知道的坑。适合刚接触 Linux 网络配置的新手也适合在云主机和物理服务器之间反复迁移的老手参考。1. 为什么 Ubuntu 20.04 默认网卡不叫 eth0 了1.1 从传统 eth0 到可预测命名规则很多人第一次登录 Ubuntu 20.04 会愣一下ip link看到的不是eth0而是ens3、enp2s0、eno1这种组合。这其实是 systemd 和 udev 从很早之前就引入的“可预测网络接口命名”机制。传统 Linux 内核给网卡命名很简单内核按驱动加载顺序和硬件探测顺序老老实实地给第一个网络设备叫eth0第二个叫eth1。这种命名方式听着舒服也有历史感情但问题很大——如果你插入了多块网卡或者换了 BIOS 设置、重新插拔 PCIe 设备内核的探测顺序可能变化于是原本的eth0可能变成eth1eth1变成eth0所有依赖名字的配置全部失效。为了解决这种“网卡漂移”systemd 从 v197 开始默认启用可预测命名规则。udev 根据硬件信息生成稳定名字规则可以拆解来看en前缀表示以太网o1表示板载网卡s1表示 PCIe 热插拔接口上的设备p3s0表示 PCI 总线 3、槽位 0 上的设备USB 网卡则通常命名成enx加上 MAC 地址。所以ens3的意思就是“PCIe 槽位 3 上的以太网卡”enp2s0就是“PCI 总线上某位置的一张网卡”。这套命名很科学稳定、信息量大一个名字就能看出设备位置。但对老运维来说最大的问题是所有按eth0写的脚本和配置都废了。1.2 什么时候必须改回 eth0其实大多数场景你根本不需要把网卡名改成eth0可预测命名本身就是现代 Linux 的默认方案。但下面这些需求会让“改回 eth0”变成刚需遗留系统的迁移原系统跑在 CentOS 6、Ubuntu 14.04 上里面脚本全部写死eth0迁移到 Ubuntu 20.04 后网卡名变了防火墙、备份、监控告警全部失灵。硬件授权绑定有些商业软件 License 绑定了网卡名和 MAC 地址网卡名一变授权就作废。团队文档和教程习惯新同事看教程操作教程里全是eth0机器上却是ens3排查问题时容易绕晕。双网卡绑定 Bond做bond0的时候需要明确指定 slave 网卡。如果两块物理网卡的开机命名顺序不稳定slave 就会互换业务 VLAN 直接错乱。我在给客户做迁移时遇到过最典型的情况原系统有两张网卡分别对应eth0和eth1一个是内网一个是外网。迁到云主机后系统给的名字变成ens3和ens4客户的安全审计脚本、iptables 规则、网卡启动脚本全部失效当天晚上紧急处理到凌晨。从此我养成了一个习惯在新机器落地后第一件事不是配环境而是先把网卡名这件事定下来。要特别说明的是改网卡名只是改用户态看到的设备名不会改变硬件 MAC、链路速率、MTU 这些底层属性也不会影响数据包收发。你改的是“门牌号”不是“房子的地基”。2. 动手前要做的三个判断2.1 判断机器的网卡身份信息写 udev 规则之前必须先拿到网卡的完整身份信息。最常用的两条命令# 查看当前网卡列表和 MAC 地址 ip link # 查看某张网卡在 udev 数据库中的详细属性 sudo udevadm info -a /sys/class/net/ens3先看ip link确认你要改的网卡叫什么MAC 是什么。然后一定要用udevadm info -a展开父设备链路因为在实例输出里网卡设备本身和它的父设备PCI 设备都有可能包含ATTR{address}、KERNELS等字段。我自己常踩的坑是直接udevadm info -a /sys/class/net/ens3得到一大段内容里面有多个KERNELS和多个ATTR{address}。到底拿哪个去匹配经验是——使用与设备自身同一层级的那组值通常在输出后面带有ATTR{address}...的那部分而父 PCI 设备上的KERNELS0000:03:00.0则用来定位物理槽位。还要注意 MAC 地址的大小写。udev 匹配时默认按小写处理所以写规则文件的时候MAC 地址一律用小写冒号分隔不要写大写。2.2 判断用 udev 规则还是 systemd.link 文件改网卡名其实有两条主流技术路线。除了本文主角 udev 规则还有一个更“现代化”的方案是 systemd 的.link文件放在/etc/systemd/network/目录下由systemd-udevd或systemd-networkd解析。两个方案的区别我整理成了表格对比项udev 规则systemd .link 文件配置文件/etc/udev/rules.d/*.rules/etc/systemd/network/*.link生效机制设备 ADD 事件触发由 udevd/networkd 在启动时处理适用环境几乎所有 Linux依赖 systemd但 Ubuntu 20.04 就是 systemd 系统老系统兼容强非 systemd 也能用弱CentOS 7 以后才自然易用性语法简洁但坑多配置结构化和 Netplan 协同好标题既然是围绕 udev而且我个人在实际运维里更习惯用 udev 规则处理网卡改名原因有两个一是 udev 规则不依赖systemd-networkd是否接管网络不管是 Netplan、NetworkManager 还是纯/etc/network/interfaces改名都是设备层面的事二是规则文件一个文件管多张网卡写注释、备份、回滚都比较直观。如果你是一个云主机用户并且已经决定使用 Netplan 管理网络那其实还有一种更省事的方案在 Netplan 的 YAML 配置里用set-name指定网卡名底层会自动生成.link文件。这个我放到后面专门说因为大部分教程只教了 udev却没提醒读者“只改 udev 不联动 Netplan 会掉 IP”。两套机制只能二选一同时用可能互相打架。2.3 判断用哪种匹配方式更稳udev 规则最关键的部分是匹配条件。匹配条件选错规则写十遍也不会生效。常见匹配方式有三种匹配方式示例优点缺点按 MAC 地址ATTR{address}00:16:3e:12:34:56直观适合云主机和固定物理机换网卡、云主机迁移后 MAC 变化会失效按 PCI 路径KERNELS0000:03:00.0换网卡也不怕物理机多网卡首选云虚拟化环境中 PCI 路径也可能变化按 USB 接口路径KERNELS1-1.3适合 USB 外接网卡、ARM 小主板插入不同 USB 口会变化我一般优先按 MAC 匹配因为大多数服务器和云主机网卡的 MAC 是固定的规则写起来最清晰。如果是物理机上插了多张 PCIe 网卡且可能换网卡硬件我会再加一条KERNELS0000:03:00.0作为辅条件这样即使 MAC 变了规则依然能通过 PCI 槽位锁定网卡。但要注意匹配条件不是越多越好。条件太多会导致规则过度精确反而容易因为某一项不匹配而失效。常规做法是“MAC 地址 DRIVERS 非空”就够用了。3. 核心实操udev 规则把网卡改成 eth03.1 规则文件的完整写法本人实践中最稳定的一张规则文件长这样SUBSYSTEMnet, ACTIONadd, DRIVERS?*, ATTR{address}00:16:3e:78:9a:bc, NAMEeth0放在/etc/udev/rules.d/70-persistent-net.rules文件中。下面逐字段拆解一下因为很多教程从来不讲为什么这么写SUBSYSTEMnet限制只匹配网络子系统设备。如果不写规则可能会尝试去匹配硬盘、USB 设备等虽然一般不会命中但写上是责任。ACTIONadd只在设备被系统添加检测到时触发执行。重启、热插拔、重新 trigger 的“add”事件都会执行避免重复改名的副作用。DRIVERS?*表示驱动非空。这个字段很多老教程里没有但实测下来在 Ubuntu 20.04 上如果不写某些虚拟网卡或特殊驱动设备可能匹配不精确。加上这一项基本不会出错。ATTR{address}00:16:3e:78:9a:bc匹配网卡 MAC 地址也就是身份指纹。NAMEeth0就是要改成的目标名称。注意NAME赋值用的是单等号前面的匹配条件则是双等号别写混了。再说一下文件名。Ubuntu 20.04 的/lib/udev/rules.d/下有很多发行版自带的规则文件数字越小越早执行。自定义规则放到/etc/udev/rules.d/下优先级天然高于/lib/udev/rules.d/里同名甚至同编号的文件。我习惯命名为70-persistent-net.rules数字 70 在中间偏前既不会被80-net-setup-link.rules之类的系统规则压住也不会因为数字太小干扰早期设备初始化。一个文件里可以管理多张网卡每张网卡一行顺序从上往下执行。比如同时固定eth0和eth1SUBSYSTEMnet, ACTIONadd, DRIVERS?*, ATTR{address}00:16:3e:78:9a:bc, NAMEeth0 SUBSYSTEMnet, ACTIONadd, DRIVERS?*, ATTR{address}00:16:3e:11:22:33, NAMEeth13.2 完整操作步骤实录我按自己平时在 Ubuntu 20.04 云主机上的操作顺序来写每一步都有实际意义。第一步备份现有配置。改网卡名前备份 Netplan 配置是给自己留一条回滚线。这一步很多人不做等 IP 丢了才后悔sudo cp -r /etc/netplan /root/netplan.backup.$(date %F) sudo cp /etc/udev/rules.d/70-persistent-net.rules /root/ 2/dev/null || true第二步确认当前网卡信息ip link sudo udevadm info -a /sys/class/net/ens3假设输出里设备自身的ATTR{address}是00:16:3e:78:9a:bc我们就拿这个值作为匹配条件。第三步写 udev 规则文件sudo vim /etc/udev/rules.d/70-persistent-net.rules内容就是 3.1 节里那行规则。注意文件编码、权限普通文本文件即可不用加执行权限。第四步写 Netplan 联动配置。看看当前 Netplancat /etc/netplan/00-installer-config.yaml假设原来配置如下network: version: 2 ethernets: ens3: dhcp4: true必须把ens3改成eth0否则重启后网卡名虽然是eth0了但根本没有 IPnetwork: version: 2 ethernets: eth0: dhcp4: true然后校验并应用sudo netplan try sudo netplan apply第五步重载 udev 规则并触发网卡 ADD 事件sudo udevadm control --reload-rules sudo udevadm trigger --actionadd --subsystem-matchnet不出意外的话几秒钟后网卡名就变了。再用ip link确认一下。如果只是想在当前运行环境下立即改而不想等重启也可以临时手动操作注意网卡要断开再改名sudo ip link set ens3 down sudo ip link set ens3 name eth0 sudo ip link set eth0 up但这种临时改名不会写入启动配置重启后还要靠 udev 规则。所以我的建议是先写好规则文件再执行trigger别用临时命令去应急因为你迟早要面对重启。3.3 被无数人忽略的 Netplan 联动问题我在 3.2 里反复提到 Netplan是因为这是“教程没写而实操必踩”的地方。Ubuntu 20.04 默认网络栈就是 Netplan它只认自己在 YAML 里定义的接口名。如果你用 udev 把网卡从ens3改成了eth0但 Netplan 里还是ens3那么系统启动后会出现两个问题udev 把网卡改成了eth0Netplan 在启动阶段根据旧配置去找ens3找不到就跳过最终的结果是eth0一直发不出 IP。更坑的是如果你用 SSH 远程管理这台机器直接在会话里netplan apply或trigger网卡一改名SSH 连接立刻断开。因为新版连接已经完全依赖旧名ens3上的 IP 地址改名后旧连接对应的接口没了新接口还没配好地址。所以规范流程应该是先写好 udev 规则同时改好 Netplan 配置最后再触发或重启。你需要有带外控制台、物理终端、云厂商 VNC 之一作为兜底手段。我在生产环境操作时会写一个延迟执行脚本sleep 5 sudo udevadm control --reload-rules sudo udevadm trigger --actionadd --subsystem-matchnet然后用nohup放到后台这样就算 SSH 断开脚本也会在五秒内自动把改名执行完。等重新连接时网卡已经变成eth0了。另外Netplan 实际上也支持直接在 YAML 里设置网卡名。如果你不想写 udev 规则可以用这种方式network: version: 2 ethernets: wan-phy: match: macaddress: 00:16:3e:78:9a:bc set-name: eth0 dhcp4: trueset-name字段会指示 Netplan 在底层生成 systemd-networkd 的.link文件同样能把网卡名钉成eth0。这种方式和 udev 规则方案各有利弊如果团队已经全面用 Netplan 管理网络我建议直接走set-name配置集中在一个文件里好维护如果网络管理可能切到 NetworkManager 或者老式的/etc/network/interfaces那还是 udev 规则更通用因为改名发生在设备层你后续用任何网络管理工具都是对着eth0操作。切记udev 规则和 Netplanset-name不要同时对一个设备生效。两套改名机制同时作用极大概率会出现“rename conflict”设备可能变成rename2这种名字那就更难看了。4. 常见问题与现场排查4.1 排查工具三板斧udev 规则写完之后不生效是新手遇到最多的问题。我排查时固定用三个工具# 查看内核与 udev 日志 sudo journalctl -u systemd-udevd -b # 模拟设备事件验证规则是否命中 sudo udevadm test /sys/class/net/ens3 # 查看内核改名记录 dmesg | grep -i renameudevadm test是最直观的它会打印一条模拟事件从触发到处理的完整过程。关键是要看输出里有没有类似 “renamed to eth0” 或者 “eth0 is already configured” 的行。如果有前者说明规则没问题如果有后者说明名称被占用或者已经被其他规则抢先处理了。实际现场执行效果大概是这样的... Reading rules file: /etc/udev/rules.d/70-persistent-net.rules ... udev_device_new_from_syspath: device 0053 has devpath /devices/pci0000:00/0000:00:03.0/net/ens3 ... link_config: autonegotiation is 1 rules_list_parse: 0: NAMEeth0 ... Using default interface naming scheme v245. ... renamed to eth0 ...4.2 高频问题修复清单下面这几种情况是这几年处理网卡改名过程中反复遇到的整理成速查表给各位参考现象可能原因解决思路规则写了但重启后名字没变规则文件没生效或 Netplan/systemd-networkd 抢占检查规则文件名序号确认/etc/udev/rules.d目录udevadm test看是否命中网卡名变成rename2目标名eth0已被另一个设备占用ip link看有没有重复名字先改名占用设备或换一个名称如net0SSH 断开后连不上改名导致原接口下线Netplan 未同步控制台登录把 Netplan 配置改成新网卡名再netplan apply重启后eth0存在但没 IPNetplan 仍然绑定旧接口名同步修改/etc/netplan/*.yaml或 NetworkManager 配置文件克隆虚机/迁移后规则失效MAC 地址变了原来的ATTR{address}匹配不上重新用udevadm info -a查新 MAC或者改用 PCI 路径匹配容器或者 Docker 场景叫不了eth0虚拟接口不支持 rename或容器网络空间独立容器里的网卡名通常在容器内配置不要试图用宿主 udev 规则改容器虚拟网卡4.3 热插拔事件和 udev 的更多玩法看到这里你可能会觉得udev 规则不就是“开机改个名”而已。其实不是udev 处理的是内核上报的设备事件ACTIONadd只是它的一类。在嵌入式开发和 ARM 小板上这个机制的用处远不止网卡命名。比如很多人喜欢用 udev 规则配合 systemd 服务做“外部设备插入自动触发任务”。我曾经在一台 ARM 小板上这么玩过写一条 udev 规则监听 USB 设备匹配手机插入事件设备一接入立即触发一个 systemd service用脚本自动把手机存储里的照片同步到服务器目录这个场景里 systemd 的看门狗保障 service 异常退出后自动重启而 udev 负责“通知系统设备来了”。同样的思路也能用在 USB 有线网卡上。USB 网卡在 Ubuntu 20.04 默认会被 udev 自动命名为enx加 MAC比如enx00e04c534458。你完全可以写一条规则把它改成usbwan、eth1这样好记的名字方法和我前面讲的完全一样匹配字段换成 USB 接口路径即可。要提醒一句热插拔规则里ACTIONadd只是“插入”事件拔掉再插入仍然会再次触发。如果脚本里有“只执行一次”的逻辑建议在脚本内部做幂等判断比如检查目标文件或 PID 锁是否存在否则插拔一次就执行一次可能会造成重复挂载、重复同步等问题。5. 进阶思路改名之外的 udev 玩法与实践经验5.1 云主机、物理机、ARM 小板上怎么选匹配方式不同环境网卡命名的稳定方案其实有不同的侧重不能拿着一套规则到处套。我按环境分类给出一套自己的选择逻辑环境类型推荐匹配方式原因云主机OpenStack/KVMATTR{address}按 MAC 匹配云厂商一般会固定虚拟网卡的 MAC规则稳定即使主机迁移MAC 多数不变物理机多 PCIe 网卡KERNELS0000:03:00.0按 PCI 槽位匹配网卡硬件可以换但槽位不会换按 PCI 路径可避免换卡后规则失效USB 网卡、ARM 小板KERNELS1-1.3或 USB 接口路径USB 设备的物理路径可控性差按接口路径能区分同一块 USB Hub 上不同口虚拟化平台VMware/Proxmox优先按 PCI 路径 MAC 双条件某些平台对虚拟网卡 MAC 会随机化两条条件互相兜底我实际在香橙派 zero2 这类 ARM 小板上调 USB 网卡时踩过最深的坑就是同一个 USB 网卡换了个 USB 口插接口名就从usb0跳到usb1业务脚本全部扑街。后来就改用 USB 接口路径匹配把网卡名固定在eth1才解决。这类小板的经验其实就是 Linux 通用逻辑的延伸只不过 ARM 板子外围设备更多、更杂udev 规则显得格外重要。5.2 三条经验原则给已经看到这里的朋友我只留三条经验第一条备份比规则更重要。你可以不会写很花哨的规则但必须会回滚。改网卡名之前Netplan、udev rules、interfaces 文件全部复制一份。如果改完出了问题先删规则文件恢复备份再 reload 和 trigger系统立刻回到原始状态。第二条规则文件要进版本管理。不要只在一台机器的/etc/udev/rules.d/里写规则而不做任何记录。这种文件总有一天会在你重建系统时忘掉。我习惯在运维仓库里单独建一个network-naming/目录把规则文件、匹配说明、涉及机器列表全部记下来新机器直接复制规则减少重复劳动。第三条改完名字之后一定要完整地自检一遍。不要只ip link看到eth0就收工。正确的验收顺序是# 看网卡名 ip link # 看路由是否正常 ip route # 看网络服务状态 systemctl status systemd-networkd networking # 看防火墙是否加载了正确接口名 sudo nft list ruleset sudo iptables -L -n -v # 看监控是否在采集 # 检查你使用的监控 agent 或脚本里是否绑定了 eth0只有业务、防火墙、监控、路由全部验证过才算是真正改完了。很多事故不是改的时候出的而是改完后面几天才发现某个后台脚本还在按旧名字发告警。这个内容后面其实还能扩展很多比如用 udev 规则给网卡改名时顺便设置软中断队列的收发队列数、RPS/RSS 参数或者配合systemd-link设置网卡 MTU 和 wol 能力。但那些都是锦上添花先把命名这件事做干净你的 Ubuntu 20.04 才算真正在你的掌控之下。