1. 工业现场双网卡路由冲突的典型症状与根因定位1.1 一个让人抓狂的现场故障去年冬天一个做机器视觉的朋友半夜给我打电话说他们产线上的工控机出了个邪门问题设备同时插着有线网卡和无线网卡有线接的是厂内PLC和相机的内网无线连的是车间办公网。结果每次重启之后访问外网时好时坏有时候能ping通网关有时候直接超时更离谱的是连内网的相机都偶尔掉线。他一开始怀疑是网线接触不良换了三根线、两个交换机端口问题依旧。后来怀疑无线驱动重装了两次系统还是老样子。这种场景在工业计算机上太常见了。工控机、边缘计算盒子、AGV小车控制器、视觉检测主机几乎都是“有线无线”双网卡并存的配置。有线负责低延迟、高可靠的设备通信无线负责远程运维、数据上云或者调试。听起来很美好但Linux内核的路由表只有一个默认网关两张网卡同时存在时谁抢到默认路由流量就走谁。如果两张网卡都通过DHCP拿到了网关地址那系统里就会出现两条默认路由内核按Metric值小的优先。问题是很多发行版默认给有线网卡的Metric是100无线是600看起来有线优先但实际部署中经常反过来或者两条路由的Metric一样导致内核随机选一条表现就是“时好时坏”。我后来远程连上去看了一眼ip route show果然两条default路由一条走eth0一条走wlan0Metric都是100。内核在等价路由之间做哈希每次新建连接可能走不同的网卡内网流量被错误地扔到无线网卡上外网流量又可能被扔到没有外网出口的有线网卡上。这就是典型的双网卡路由优先级冲突。1.2 为什么传统ifconfig和route搞不定很多从CentOS 6或者Ubuntu 14.04时代过来的运维第一反应是改/etc/network/interfaces或者写/etc/sysconfig/network-scripts/route-eth0。但在现代Linux发行版上网络管理栈已经换了好几代。Ubuntu 18.04之后默认用Netplan底层可以是systemd-networkd或者NetworkManagerDebian 10之后systemd-networkd逐渐成为服务器和工控场景的主流RHEL 8/9虽然默认NetworkManager但很多工业客户为了精简系统会手动切到systemd-networkd。systemd-networkd的好处是轻量、启动快、配置统一特别适合无头工控机。但它有个特点路由Metric的配置方式和传统工具完全不同。你不能再写up ip route add default via ... metric 100这种脚本而是要在.network文件里用[Route]段或者GatewayOnLink、Metric这些关键字。很多人不知道这个区别照着网上的老教程改结果配置根本不生效重启后路由又乱了。更麻烦的是无线网卡在systemd-networkd下的行为和有线的差异很大。有线网卡通常由.network文件静态匹配无线网卡如果走wpa_supplicant可能由wpa_supplicantwlan0.service管理DHCP客户端拿到的路由Metric默认是600但如果你在.network里没显式指定systemd-networkd可能会给它一个默认值导致和有线网卡的Metric打架。1.3 根因拆解内核路由决策的底层逻辑要彻底解决这个问题得先搞清楚Linux内核怎么选路。内核维护一张路由表main表每条路由有一个Metric也叫跳数。当有多个匹配目标地址的路由时内核选Metric最小的。如果Metric相同就进入等价多路径ECMP模式按哈希分流。对于默认路由0.0.0.0/0如果两条路由Metric相同内核会轮流用或者根据源地址哈希表现就是“一会儿走有线一会儿走无线”。工业场景的需求通常是内网设备PLC、相机、机器人必须走有线因为无线延迟抖动大丢包率高。外网或办公网流量走无线因为有线网络通常是隔离的没有外网出口。如果无线断开系统不能完全失联至少要有线还能通内网。所以正确的路由策略应该是有线网卡的默认路由Metric设小比如100无线网卡的默认路由Metric设大比如600并且确保内网网段的路由只走有线。这样内核优先选有线作为默认出口但如果有线没有外网流量会走有线然后被丢弃——所以还需要更精细的策略路由或者干脆不给有线配默认网关只配内网静态路由。但很多工控机的有线网卡是通过DHCP拿地址的DHCP服务器会下发默认网关你没法控制。这时候就得在systemd-networkd里用UseRoutesfalse或者Metric来覆盖DHCP下发的路由。2. systemd-networkd配置体系与Metric参数深度解析2.1 systemd-networkd的文件结构与匹配逻辑systemd-networkd的配置分三个层次.netdev文件创建虚拟设备.network文件匹配物理设备并配置网络.link文件配置底层链路参数。对于双网卡路由优先级核心是.network文件。.network文件的匹配规则是按文件名排序第一个匹配上的生效。比如10-eth0.network和20-wlan0.network系统会先读10再读20。匹配条件用[Match]段可以按网卡名、MAC地址、驱动类型、PCI路径等匹配。工业现场建议用MAC地址匹配因为网卡名可能因为内核枚举顺序变化而改变比如enp3s0变成enp4s0。一个典型的.network文件长这样[Match] MACAddress00:1b:21:3c:4d:5e [Network] DHCPipv4 LinkLocalAddressingno IPv6AcceptRAno [DHCPv4] UseRoutesfalse [Route] Destination192.168.1.0/24 Gateway192.168.1.1 Metric100这里的关键是[DHCPv4]段的UseRoutesfalse它告诉systemd-networkd不要安装DHCP下发的默认路由。然后手动在[Route]段里加内网静态路由Metric设小。这样有线网卡只负责内网不会抢默认路由。无线网卡的配置类似但通常需要保留DHCP下发的默认路由因为无线是外网出口。可以这样写[Match] MACAddressaa:bb:cc:dd:ee:ff [Network] DHCPipv4 [DHCPv4] UseRoutestrue RouteMetric600RouteMetric600是systemd-networkd 244版本之后支持的参数直接覆盖DHCP下发的默认路由Metric。如果你的系统版本较老可能需要在[Route]段手动加默认路由或者用Metric在[Network]段全局设置。2.2 Metric值的计算与选择依据Metric值不是随便填的它影响内核选路的优先级。数值越小优先级越高。常见的默认值有线DHCP100无线DHCP600静态路由通常不设默认0工业场景建议有线内网静态路由Metric 50-100有线默认路由如果有外网Metric 100无线默认路由Metric 600备用4G/5G路由Metric 700为什么无线要设600而不是200因为无线链路的稳定性远不如有线即使信号满格延迟也可能突然飙升。把Metric设大确保只要有线可用默认流量就不走无线。600这个值是systemd-networkd的默认无线Metric沿用它可以减少和其他服务的冲突。如果两张网卡都需要默认路由但希望有线优先可以设有线默认路由Metric100无线默认路由Metric600这样内核优先选有线。但有线如果没有外网出口流量会走有线然后被防火墙丢弃不会自动切到无线。要实现自动切换需要更复杂的策略路由或者用ip rule配合ip route但工业场景通常不需要自动切换因为网络拓扑是固定的。2.3 策略路由与多表路由的进阶用法如果需求更复杂比如“内网走有线外网走无线但无线断开时外网走有线”那就得用策略路由。Linux支持多张路由表默认有local、main、default三张。可以创建自定义表比如table 100给有线table 200给无线。配置方法是在.network文件里用[RoutingPolicyRule]段[RoutingPolicyRule] From192.168.1.0/24 Table100 Priority1000然后在[Route]段指定Table100。这样源地址是内网网段的流量会查table 100走有线。其他流量查main表走无线。但策略路由的配置复杂度高容易出错。工业现场如果只是简单的“内网有线、外网无线”用Metric覆盖就够了。策略路由适合有多个内网网段、需要精细控制的场景。3. 双网卡Metric配置的完整实操流程3.1 环境确认与网卡识别第一步永远是确认系统版本和网络管理栈。执行systemctl status systemd-networkd networkctl status ip link show如果systemd-networkd是active说明它在管理网络。如果同时有NetworkManager在跑可能会冲突建议禁用其中一个systemctl disable --now NetworkManager systemctl enable --now systemd-networkd然后识别网卡名和MAC地址ip -br link show输出类似lo UNKNOWN 00:00:00:00:00:00 enp3s0 UP 00:1b:21:3c:4d:5e wlp2s0 UP aa:bb:cc:dd:ee:ff记下MAC地址后面配置用MAC匹配更可靠。3.2 有线网卡配置只走内网不抢默认路由创建/etc/systemd/network/10-wired.network[Match] MACAddress00:1b:21:3c:4d:5e [Network] DHCPipv4 LinkLocalAddressingno IPv6AcceptRAno LLMNRno [DHCPv4] UseRoutesfalse UseDNSfalse [Route] Destination192.168.1.0/24 Gateway192.168.1.1 Metric100这里UseRoutesfalse是关键它阻止DHCP下发的默认路由进入内核。UseDNSfalse是因为内网DNS通常不需要避免DNS查询走有线导致解析慢。然后手动加内网静态路由Metric100。如果内网有多个网段比如192.168.1.0/24和192.168.2.0/24就加多个[Route]段。3.3 无线网卡配置作为默认出口Metric设大创建/etc/systemd/network/20-wireless.network[Match] MACAddressaa:bb:cc:dd:ee:ff [Network] DHCPipv4 LinkLocalAddressingno IPv6AcceptRAno [DHCPv4] UseRoutestrue RouteMetric600 UseDNStrueRouteMetric600确保无线默认路由的Metric是600低于有线的100优先级。UseDNStrue让无线下发的DNS生效用于外网域名解析。如果系统版本不支持RouteMetric可以改成手动加默认路由[Route] Destination0.0.0.0/0 Gateway192.168.100.1 Metric600但网关地址得写死不如DHCP灵活。3.4 重启服务与路由验证配置完成后重启systemd-networkdsystemctl restart systemd-networkd然后检查路由表ip route show期望输出default via 192.168.100.1 dev wlp2s0 proto dhcp src 192.168.100.50 metric 600 192.168.1.0/24 via 192.168.1.1 dev enp3s0 proto static metric 100 192.168.1.0/24 dev enp3s0 proto kernel scope link src 192.168.1.10 metric 100 192.168.100.0/24 dev wlp2s0 proto kernel scope link src 192.168.100.50 metric 600注意默认路由只有一条走无线Metric 600。内网路由走有线Metric 100。这样内网流量走有线外网流量走无线互不干扰。再验证一下ping -c 3 192.168.1.100 # 内网设备应该走有线 ping -c 3 8.8.8.8 # 外网应该走无线 traceroute 8.8.8.8 # 确认第一跳是无线网关如果内网ping不通检查有线网卡的IP和路由是否正确。如果外网ping不通检查无线网关和DNS。3.5 持久化与开机自启验证systemd-networkd的配置是持久的重启后自动生效。但建议做一次完整重启测试reboot重启后再次检查ip route show确认路由表符合预期。如果发现路由又乱了可能是其他服务在干扰比如dhclient或者NetworkManager残留。用systemctl list-units | grep -i network排查。另外工业现场经常有断电重启的情况建议在/etc/systemd/network/下加一个99-default.link文件统一设置网卡命名策略避免网卡名变化导致匹配失败[Match] OriginalName* [Link] NamePolicymac MACAddressPolicypersistent这样网卡名会基于MAC地址生成重启后不会变。4. 常见故障排查与避坑经验实录4.1 路由表里出现两条默认路由怎么办这是最常见的症状。原因通常是DHCP下发的路由没被抑制。检查.network文件里有没有UseRoutesfalse或者RouteMetric是否生效。如果配置没问题但路由还在可能是systemd-networkd版本太老不支持这些参数。用systemd --version查看版本低于244的建议升级或者改用[Route]段手动覆盖。另一个可能是无线网卡的wpa_supplicant在DHCP之后又加了一条路由。检查/etc/wpa_supplicant/wpa_supplicant.conf里有没有update_config1这个选项会让wpa_supplicant修改网络配置建议关掉。4.2 内网流量被错误地路由到无线网卡如果ip route show里内网网段的路由指向了无线网卡说明有线的静态路由没生效。检查[Route]段的Destination和Gateway是否正确Metric是否比无线的小。另外如果内网网段和无线网段有重叠比如都是192.168.1.0/24那内核会优先选直连路由导致冲突。工业现场一定要规划好网段有线内网和无线外网用不同的私有网段。4.3 无线断开后系统完全失联如果无线是唯一的默认出口无线一断外网就没了。但内网应该还能通。如果内网也不通说明有线的静态路由没配好或者有线网卡的IP丢了。建议在.network文件里加ConfigureWithoutCarrieryes这样即使网线没插网卡也会保留IP配置方便调试。另外可以配一个备用路由比如用4G模块Metric设700无线断了自动切4G。但工业场景通常不需要因为产线网络是固定的。4.4 排查工具与命令速查表问题现象排查命令可能原因解决方法两条默认路由ip route showDHCP路由未抑制加UseRoutesfalse或RouteMetric内网走无线ip route get 192.168.1.100静态路由Metric太大调小有线Metric外网走有线ip route get 8.8.8.8有线默认路由Metric太小调大有线Metric或删默认路由无线断开失联networkctl status有线无IP检查DHCP和ConfigureWithoutCarrier配置不生效journalctl -u systemd-networkd文件权限或语法错误检查chmod 644和networkctl reload注意修改.network文件后一定要执行networkctl reload再networkctl reconfigure 网卡名或者直接重启systemd-networkd。只改文件不重载配置不会生效。4.5 几个只有踩过坑才知道的细节第一个坑[DHCPv4]段的RouteMetric参数在systemd 244之前叫Metric而且只在[Network]段生效。如果你照着新文档写在老系统上会报错。建议先查版本再决定用哪个参数。第二个坑无线网卡的.network文件如果和wpa_supplicant的配置冲突比如wpa_supplicant自己加了默认路由那systemd-networkd的Metric会被覆盖。解决办法是在wpa_supplicant配置里加update_config0禁止它修改网络。第三个坑工业现场经常用USB无线网卡这种网卡的MAC地址可能每次重启都变。用MAC匹配会失效。建议用[Match]的Path或者Driver匹配比如Driverrtl8192cu或者用OriginalNamewlan*。第四个坑如果系统里同时有systemd-networkd和dhclient在跑dhclient会偷偷加路由。检查ps aux | grep dhclient如果有禁用对应的服务。5. 工业场景下的扩展配置与长期维护建议5.1 多网卡多网段的策略路由模板如果工控机有三张网卡有线内网、无线外网、4G备用可以这样配有线内网[Match] MACAddress00:1b:21:3c:4d:5e [Network] DHCPipv4 [DHCPv4] UseRoutesfalse [Route] Destination192.168.1.0/24 Gateway192.168.1.1 Metric100无线外网[Match] MACAddressaa:bb:cc:dd:ee:ff [Network] DHCPipv4 [DHCPv4] UseRoutestrue RouteMetric6004G备用[Match] MACAddress11:22:33:44:55:66 [Network] DHCPipv4 [DHCPv4] UseRoutestrue RouteMetric700这样优先级有线内网 无线外网 4G备用。无线断了4G自动接管默认路由。5.2 配置文件的版本管理与备份工业现场的配置一旦调好就不应该随便动。建议把/etc/systemd/network/整个目录用git管理或者至少打个tar包备份。每次修改前先cp -r /etc/systemd/network /etc/systemd/network.bak出问题可以快速回滚。另外.network文件的权限必须是644属主root。如果权限不对systemd-networkd会忽略它。用chmod 644 /etc/systemd/network/*.network统一设置。5.3 远程维护时的安全注意事项工业现场通常没有显示器全靠SSH远程。如果路由配错SSH可能断连。建议在修改网络配置前先开一个screen或者tmux会话或者用at命令定时回滚echo cp /etc/systemd/network.bak/* /etc/systemd/network/ systemctl restart systemd-networkd | at now 5 minutes这样5分钟后如果没取消配置自动回滚。确认新配置没问题后用atrm删掉定时任务。5.4 长期运行中的Metric漂移问题有些工控机运行几个月后路由Metric会莫名其妙变化。这通常是因为DHCP租约续期时systemd-networkd重新应用了路由但Metric没保持。解决办法是在.network文件里显式写死RouteMetric并且加[DHCPv4]的UseRoutestrue让每次续期都按配置来。另外如果无线信号弱wpa_supplicant可能会频繁重连每次重连都会重新DHCP导致路由表抖动。建议在/etc/systemd/network/20-wireless.network里加[Network]的DHCPipv4和[DHCPv4]的RouteMetric600并且用wpa_supplicant的bgscan参数优化漫游。5.5 从Metric到策略路由的演进路径如果现场需求从“内网有线、外网无线”升级到“多个内网网段走不同网卡”那就得用策略路由。比如192.168.1.0/24 走有线1192.168.2.0/24 走有线2其他走无线配置方法是在.network文件里加[RoutingPolicyRule][RoutingPolicyRule] From192.168.1.0/24 Table100 Priority1000 [Route] Destination192.168.1.0/24 Gateway192.168.1.1 Table100 Metric100然后创建/etc/iproute2/rt_tables里的自定义表100 wired1 200 wired2这种配置复杂度高建议先在测试环境验证再上产线。5.6 一个真实的产线案例复盘去年那个朋友的产线最后是怎么解决的我远程连上去发现他的系统是Ubuntu 20.04systemd 245NetworkManager和systemd-networkd都在跑。NetworkManager给无线加了默认路由Metric 600systemd-networkd给有线加了默认路由Metric 100但有线没有外网所以外网流量走有线被丢弃。同时内网流量因为两条默认路由等价有时候走无线导致相机掉线。解决步骤禁用NetworkManagersystemctl disable --now NetworkManager确认systemd-networkd接管systemctl enable --now systemd-networkd写有线.network文件UseRoutesfalse加内网静态路由Metric 100写无线.network文件RouteMetric600重启验证路由表加at定时回滚确认稳定后取消前后花了不到20分钟问题彻底解决。后来他产线跑了半年没再出过网络问题。这个案例说明双网卡路由冲突不是玄学就是Metric没配对。只要理解了内核选路逻辑用systemd-networkd的配置覆盖DHCP默认行为就能稳稳搞定。工业现场的网络配置稳定比灵活重要宁可手动写死路由也不要依赖DHCP的自动下发。