Ubuntu 开发环境搭建避坑(一):网卡 EEE 致 60% 周期性丢包,Realtek RTL8125 网络黑洞排查与修复

这是《Ubuntu 开发环境搭建避坑》系列的第一篇。笔者是做运维开发的,新装了一台 Ubuntu 台式机(主板自带 Realtek RTL8125 2.5G 网卡)准备搭日常开发环境:Docker、JDK、一堆 apt 依赖,再配个 RustDesk 方便从别的机器远程进来写代码。结果环境还没搭完,网络先"半残"了------apt 下载龟速、git clone 断断续续、RustDesk 远程画面卡成幻灯片,自建的 RustDesk 中继服务器日志里反复报这台机器"网络质量差"。

最后定位到的根因有点出乎意料:网卡的一个"节能"特性(EEE,节能以太网)唤醒失败,造成了周期性的通信黑洞。这篇把完整的排查路径、量化数据、修复方法和一键脚本分享出来------如果你也在新装的 Ubuntu 上遇到"莫名卡顿但一切计数正常",大概率能直接对号入座。

一、现象:先量化,再动手

排查网络问题的第一原则是先拿数字,"感觉卡"是不能定位问题的。装好基础工具后采了一轮基线数据:

指标 故障时 修复后
ping 网关 / 局域网设备 / 外网 全部丢包 60% 0%
丢包模式 周期性:每 2.5~3s 一循环,通约 1s → 黑洞 1.5~2s ---
收到包的 RTT 极稳(0.5ms,mdev 0.04ms) 0.5ms
下载速度(阿里云镜像) 236 KB/s 19.4 MB/s(82 倍)
RustDesk 到中继的 TCP 发送积压 74483 字节 437 字节
网卡错误计数 / 链路闪断 / ARP 冲突 全部为零 ---

三个关键观察,后面都会用到:

  1. 网关、局域网、外网丢包率完全相同(都是 60%)------问题在共享的近端段,不在远端;
  2. 丢包是周期性的,不是随机散布------通 1 秒、断 1~2 秒,像呼吸一样规律;
  3. 网卡所有错误计数为零,链路不闪断------这条最有迷惑性,让人一开始就把硬件排除了。

二、五层排查法:从近到远逐层收窄

这种"逐层收窄、每层拿数据说话"的思路,和之前 Java 进程 Unable to create new native thread 排查:Linux 线程数五层限制 里定位线程数上限的方法论是同一套------先穷尽约束层,再对号入座。

2.1 第 1 层:本机与链路层

bash 复制代码
ip -s link                       # 接口收发错误/丢包计数
ethtool enp2s0                   # 协商速率、双工、链路状态
ethtool -S enp2s0                # 硬件详细计数(CRC/FIFO 等)
dmesg | grep -iE 'enp2s0|link|r8169'   # 链路闪断、驱动重置

判读:协商速率异常(比如降到 100M 或半双工)说明网线/端口有问题。本机协商在 2.5G 全双工、链路 up,所有错误计数为零。

这里的坑:计数全零 ≠ 链路正常。 EEE 唤醒失败、WiFi 干扰这类问题都不计入任何网卡错误计数器------"硬件计数全零"具有极强迷惑性,这也是本文案例最初被带偏的原因。

2.2 第 2 层:本地网段(ping 网关)

bash 复制代码
ping -c 50 -i 0.2 -q 192.168.1.1
  • 0% 丢包 → 本地网段正常,问题在更远端或应用层,直接跳第 4 层;
  • 丢包 → 问题锁定在【本机网卡↔网线↔交换机/路由器】这一段,进第 3 层。

本机实测 60% 丢包------问题在近端这一段。

2.3 第 3 层:区分丢包模式(本案的胜负手)

bash 复制代码
ping -D -c 40 -i 0.2 192.168.1.1    # -D 给每个包打时间戳

看丢包的时间分布,两种模式指向完全不同的根因:

模式 特征 首要怀疑
周期性黑洞 连续通过 N 个包 → 整段丢失 1~2s → 循环(周期 2~10s) ① EEE/ASPM 等电源管理唤醒失败 ② ARP/IP 冲突 ③ STP 拓扑震荡 ④ 某设备周期性重启/广播风暴
随机丢包 无规律散布 网线/水晶头质量、拥塞、WiFi 干扰、路由器过载

本机抓到的是标准的周期性黑洞:每 2.5~3 秒一个循环。"周期性"这个特征价值极大------它把"线路质量差"这类静态原因排除掉了(坏网线不会按时坏),把嫌疑集中在有状态机、会周期性休眠/唤醒的机制上:电源管理首当其冲。

2.4 第 4 层:局域网对端 + 外网交叉验证

bash 复制代码
ping 192.168.1.88       # 同网段其它设备(本例为 RustDesk 服务器)
ping 223.5.5.5          # 外网对照(阿里 DNS,国内质量稳定)
mtr -rwb -c 30 -n 223.5.5.5

判读逻辑:

  • 所有目标(网关/局域网/外网/mtr 每一跳)丢包率相同 → 问题在共享的近端段(本机网卡、网线、直连交换设备),与远端无关。这是最重要的定位推理之一;
  • 只有外网丢、局域网干净 → 路由器 WAN/运营商问题;
  • 只有某一台局域网设备丢 → 那台设备或它的接入链路问题。

本机对网关、RustDesk 服务器、阿里 DNS 三个目标丢包率清一色 60%------凶手在共享段,基本就是本机网卡或那根网线。

2.5 第 5 层:排除 ICMP 假阳性(协议对照)

路由器(尤其某些型号)会限速/丢弃 ICMP,制造假丢包。三种对照手段:

bash 复制代码
# 手段1: ICMPv6 对照(路由器一般不限速 NDP 相关的 ICMPv6,还能暴露队列延迟)
ping -6 -I enp2s0 -c 20 fe80::<网关链路本地地址>
# 本例故障时它显示 RTT 高达 1 秒 → 暴露真实存在通信黑洞,不是被过滤

# 手段2: TCP 握手成功率
for i in $(seq 20); do curl -o /dev/null -sS --connect-timeout 2 -w '%{time_connect}\n' http://192.168.1.88:21118/; done

# 手段3: 真实下载吞吐(最贴近用户体感,至少测两个源)
curl -4 -o /dev/null -sS -w '%{speed_download} B/s\n' --max-time 20 <镜像源1>
curl -4 -o /dev/null -sS -w '%{speed_download} B/s\n' --max-time 20 <镜像源2>

判读:ICMP 大量丢但 TCP/下载完全正常 → ICMP 被过滤,别被带偏;下载同样崩溃(本例 236 KB/s)→ 真实劣化。单一测速源慢可能是服务器限速,至少测两个源再下结论。

三、进阶判别:三个快速排除实验

3.1 区分"本机没发出"还是"对端没回"

在 ping 前后取网卡硬件发包计数差:

bash 复制代码
ethtool -S enp2s0 | grep tx_packets > /tmp/b
ping -c 30 -i 0.2 -q 192.168.1.1
ethtool -S enp2s0 | grep tx_packets > /tmp/a
diff /tmp/b /tmp/a

内核计 30 个已发、硬件计数也涨了 ≥30 → 包离开了网卡,问题在外部路径;硬件计数明显少 → 本机 qdisc/驱动/NIC 停摆。本例计数吻合------包发出去了,但响应回不来或回来时正赶上网卡"睡着"。

3.2 ARP 冲突检测

bash 复制代码
timeout 15 ip monitor neigh     # 15 秒内邻居表零变化 → 无 ARP 冲突

3.3 本机配置快速排除清单

bash 复制代码
tc qdisc show dev enp2s0          # 应只有 fq_codel,出现 netem = 人为丢包
ip rule show                      # 应只有 0/32766/32767 三条默认规则
ip route show table all           # 单一默认路由,无 VPN 隧道劫持
awk '{d+=$2} END{print d}' /proc/net/softnet_stat   # 软中断丢包,应为 0

3.4 两个必须知道的"数据会骗人"

  • nstat 的 TCP 计数因 GRO/TSO 卸载严重失真:InSegs/OutSegs 差值算出的"重传率"不可直接采信,只作弱参考;
  • 网卡错误计数为零 ≠ 链路正常:EEE 唤醒失败、信号裕量不足都不计数。

四、锁定根因:EEE(节能以太网)唤醒失败

到此可以收网了。证据链:全目标均匀丢包 + 周期性黑洞 + RTT 极稳 + 硬件计数全零------这个组合的典型指纹就是电源管理类故障。查 EEE 状态:

bash 复制代码
sudo apt install ethtool
sudo ethtool --show-eee enp2s0

输出显示 EEE status: enabled(enabled-active)------Realtek RTL8125(r8169 驱动)的 EEE 处于开启状态。

EEE(Energy-Efficient Ethernet,节能以太网,IEEE 802.3az)的机制是:链路空闲时让 PHY(物理层芯片)进入低功耗休眠,有数据时再快速唤醒。问题在于 RTL8125 上这个"快速唤醒"并不可靠------PHY 睡着后唤醒失败或过慢,就出现周期性的双向通信黑洞;而唤醒失败不产生任何错误计数,所以计数器看起来一切正常。这与前面观察到的"通 1 秒、断 1~2 秒"的呼吸式丢包完全吻合:流量来了 PHY 醒着就通,空闲了睡过去,下一批包赶上了唤醒延迟就全丢。

对实时流(RustDesk/视频会议/游戏)这是毁灭性的:它们持续小流量发包,恰好反复触发休眠/唤醒循环。

五、修复:ethtool --set-eee 一条命令关闭 EEE + 复测

bash 复制代码
sudo ethtool --set-eee enp2s0 eee off

复测(同参数):

指标 修复前 修复后
ping 网关丢包 60% 0%
下载速度 236 KB/s 19.4 MB/s
RustDesk TCP 发送积压 74483 B 437 B

RustDesk 远程立刻恢复流畅。注意 ethtool --set-eee 的效果重启后失效 ,必须持久化,否则哪天重启完"怎么又卡了"。"一次修复不算完,重启后仍要成立"这个意识,和 OpenSSH 漏洞修复升级前先搭 telnet 救生通道 里"防锁死要先兜底"是同一种工程习惯。

六、持久化:重启不复发

方案 A:NetworkManager dispatcher 钩子(Ubuntu 桌面版默认走 NetworkManager,推荐):

bash 复制代码
sudo tee /etc/NetworkManager/dispatcher.d/90-disable-eee <<'EOF'
#!/bin/bash
[ "$1" = "enp2s0" ] && [ "$2" = "up" ] && /usr/sbin/ethtool --set-eee "$1" eee off
EOF
sudo chmod 755 /etc/NetworkManager/dispatcher.d/90-disable-eee

网卡每次 up 时自动关 EEE。

方案 B:systemd oneshot 服务(服务器版无 NetworkManager 时兜底):

ini 复制代码
[Unit]
Description=Disable EEE on boot (fix RTL8125 periodic stall)
After=network-pre.target
Before=network.target

[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool --set-eee enp2s0 eee off

[Install]
WantedBy=multi-user.target

systemctl enable --now disable-eee.service 生效。重启后用 ethtool --show-eee enp2s0 | head -1 验证仍为 disabled。

七、一键脚本:fix-eee-stall.sh

把上面的"检测 → 关闭 → 复测 → 持久化"整条链路写成了脚本,核心逻辑:

bash 复制代码
# EEE 状态探测: enabled / disabled / unsupported
eee_status() {
    local out
    out=$(ethtool --show-eee "$1" 2>&1) || { echo unsupported; return; }
    if echo "$out" | grep -q 'EEE status:.*enabled'; then echo enabled
    elif echo "$out" | grep -q 'EEE status:.*disabled'; then echo disabled
    else echo unsupported; fi
}

# 丢包率采样(纯数字输出便于比较)
loss_pct() {
    ping -c 50 -i 0.2 -q "$1" 2>/dev/null \
        | sed -n 's/.*, \([0-9.]*\)% packet loss.*/\1/p' | head -1
}

# 修复: 对 EEE=enabled 的在线有线网卡执行关闭, 然后同参数复测
ethtool --set-eee "$IF" eee off

用法:

bash 复制代码
./fix-eee-stall.sh --check        # 仅诊断不修改, 无需 root: 报告 EEE 状态+丢包基线
sudo ./fix-eee-stall.sh           # 自动检测所有在线有线网卡并修复
sudo ./fix-eee-stall.sh enp2s0    # 只处理指定网卡

脚本会输出修复前后丢包对比,EEE 关闭后若丢包仍超标,会提示按"换网线 → 换端口 → 锁 1G 验证 → 查 ASPM"的顺序继续排查;持久化自动选择 dispatcher 或 systemd 方案安装。

八、EEE 关闭无效时的决策树

  1. 换网线(2.5G 需 Cat5e 以上,推荐 Cat6)------成本最低,先做;
  2. 换路由器/交换机端口;
  3. 锁 1G 验证 :sudo ethtool -s enp2s0 speed 1000 duplex full autoneg on------1G 下正常则确认 2.5G 信号裕量不足,停在 1G 或换线后恢复 2.5G;
  4. 关 PCIe ASPM :BIOS 中关闭,或内核参数 pcie_aspm=off 试验(与 EEE 同族的节能机制);
  5. 换网卡/PCIe 插槽(板载网卡故障的最后手段)。

九、症状 → 根因速查表

症状组合 首要怀疑 验证命令
全目标均匀丢包 + 周期性通断 + RTT 极稳 + 计数全零 EEE/ASPM 电源管理 ethtool --show-eee <if>
全目标均匀丢包 + 邻居表频繁变化 IP/MAC 冲突 ip monitor neigh
全目标丢包 + 路由器管理页也卡 路由器 CPU 过载/风暴 登录路由器看 CPU,拔设备二分
只有远端丢,局域网干净 运营商/WAN mtr -rb <公网IP> 看从哪跳开始丢
下载慢但 ping 完美 限速/单线程瓶颈/QoS 多源测速 + 换时段
RTT 抖动大(无丢包) 缓冲膨胀(bufferbloat)/拥塞 边下载边 ping 网关对比
协商速率 100M 或半双工 网线/端口老化 `ethtool

十、踩坑点小结

  1. 网卡错误计数全零是最强的烟雾弹------EEE 唤醒失败不进任何计数器,别据此排除硬件;
  2. 周期性丢包是电源管理类故障的指纹------坏网线不会"按时"坏,能画出规律的丢包就去查会休眠的东西(EEE/ASPM/选择性暂停);
  3. 先量化再动手 ------每层修复前取基线、修复后同参数复测,ping -c 50 -i 0.2 -q + ping -D 时间戳这两条命令信息量最大;
  4. ICMP 会骗人------用 ICMPv6/TCP 握手/真实下载三重对照再下结论,测速至少两个源;
  5. ethtool --set-eee 重启失效------不装持久化钩子,问题一定会"复发";
  6. 实时流卡顿但错误日志干净时优先怀疑节能特性------RustDesk/会议/游戏持续小流量恰好反复触发 PHY 休眠唤醒。

写在最后

新机器搭开发环境,第一坑居然埋在网卡的"节能"特性里。这个案例给我的最大教训是:网络排查要从近到远逐层收窄,用对照实验排除假象,抓住丢包的分布特征(周期性/均匀性)反推机制------而不是一上来就换网线、重装驱动。

这是《Ubuntu 开发环境搭建避坑》系列的第一篇,后续会继续记录环境搭建过程中的真实踩坑与解法。同类的 Linux 系统层排障实战,可以参考我之前的几篇:OpenSSH 漏洞修复升级实战、Java 进程 Unable to create new native thread 排查、Hadoop 集群日常运维 SOP。

你有没有遇到过"计数全零但网络就是卡"的诡异故障?最后查出来是什么原因?欢迎在评论区分享你的案例。

系列相关:OpenSSH 升级实战 · JVM 线程数五层限制排查 · Hadoop 日常运维 SOP

相关推荐
墨染天姬1 小时前
【linux 网络1】数据怎么进网卡到内核?
linux·运维·网络
迪康coolmu1 小时前
金融客户数据合规落地:基于迪康端点安全一体化管理系统的四道防线实践
运维·服务器·数据库·经验分享·安全·网络安全·金融
崇子嵘2 小时前
上云方案硬件部分分析
linux
小嘉丶学长2 小时前
Day13 · 列表与元组
linux·运维·服务器·开发语言·python
时间售卖铺2 小时前
MySQL事务ACID与隔离级别深度解析
运维·数据库·mysql·云原生
中屹指纹浏览器svip2 小时前
指纹浏览器RPA自动化靠谱吗?先分清适用边界
运维·自动化·rpa
zuiyuewentian2 小时前
借助 AI 在 Win11 上搭建 Rocky Linux:用 Visual Studio 直接调试 Linux 服务
linux·运维·visual studio
|_⊙2 小时前
应用层协议HTTP与HTTPS
网络·网络协议·http
牢姐与蒯2 小时前
WSL2 迁移教程:把Ubuntu+WSL2从C盘挪到别的盘
linux·运维·服务器·网络·ubuntu·1024程序员节