Linux无直接重传率命令,必须用/proc/net/snmp中TCPRetransSegs与TcpOutSegs的两时间点差值比值计算,>0.5%需关注,>2%表明链路持续丢包。

直接看 /proc/net/snmp 的差值,别信绝对值
Linux 没有“当前重传率”这种瞬时指标,/proc/net/snmp 里 TCPRetransSegs 和 TcpOutSegs 都是累计计数器。直接拿某次采样的比值(比如 RetransSegs / OutSegs)毫无意义——它反映的是从系统启动至今的平均表现,对高丢包场景完全失真。
必须取两组时间点的差值:(RetransSegs₂ − RetransSegs₁) ÷ (OutSegs₂ − OutSegs₁)。这个比值才是真实、可告警的重传率。
- 用
watch -n1 'cat /proc/net/snmp | grep -A1 Tcp | tail -n1'手动记下 5 秒内两组值,快速估算 - 第 11 列是
OutSegs,第 15 列是RetransSegs(注意字段顺序,不同内核版本可能微调,先head -1 /proc/net/snmp确认) - 结果 > 0.005(0.5%)就要盯住;> 0.02(2%)基本可断定链路存在持续丢包
用 nstat -t 1 看每秒增量,避免手算翻车
nstat 是 sysstat 提供的专用工具,自动处理差值、单位和零值过滤,比手撕 awk 更稳。它输出的第二列就是「上一秒内的增量」,直接可除。
运行:watch -n 1 'nstat -z -t 1 | grep -E "TcpRetransSegs|TcpOutSegs"'
-
TcpRetransSegs 123 0.0表示上一秒重传了 123 段 -
TcpOutSegs 9876 0.0表示上一秒发出 9876 段(含纯 ACK) - 比值 ≈ 123 / 9876 ≈ 1.25%,趋势比单点更可靠
- 务必加
-t 1(按秒聚合)和-z(过滤零值),否则会被历史归零项干扰
ss -ti 的 retransmits 不是总重传数,别误判
ss -ti 输出末尾的 retransmits 字段常被当成“该连接重传次数”,但它只统计超时重传(RTO timeout),不包括快速重传、SACK 重传或 TLP。它对应的是 /proc/net/snmp 中的 TCPTimeouts,不是 TCPRetransSegs。
- 执行
ss -ti state established,看到retransmits:0并不能说明没丢包 - 该字段在连接关闭后清零,无法回溯;即使全局
TCPRetransSegs持续上涨,它也可能长期为 0 - 真要定位高重传流:先用
ss -tunap找出目标四元组(源/目的 IP+端口),再加-i查其retransmits;若值 > 0 且持续增长,才说明该流路径存在稳定丢包
别碰 sar -n TCP,它根本不存在
sar -n TCP 是个常见幻觉。官方文档和内核源码里压根没有这个子选项,执行后要么报错,要么静默忽略,甚至返回 DEV 层数据,完全不可信。
- 能用的是
sar -n ETCP(扩展 TCP 统计),它提供retransmit(累计重传段数)、orsts、inerrs等字段 - 但
sar -n ETCP仍是快照,仍需你手动做差值计算,不如nstat -t 1直接 -
netstat -s是/proc/net/snmp的文本封装,在最小化系统或容器中常不可用;字段解析逻辑不透明,容易把segments retransmitted和其他统计混在一起
真正关键的细节是:TCP 重传率本身只是现象,不是根因。它告诉你“哪里坏了”,但不告诉你“为什么坏”。计算出来 >2% 之后,下一步必须结合 ifconfig 看网卡 errors、用 ethtool -S 查驱动级丢包、抓包确认是否全是 Dup ACK 或 RTO 超时——这些动作之间的时间窗口越小,越容易锁定丢包发生在哪一跳。


















