土法炼钢兴趣小组的算法知识备份

【网络工程】ss/netstat/ip 工具链:Socket 状态分析与连接审计

文章导航

分类入口
network
标签入口
#ss#netstat#ip#conntrack#linux#diagnostics

目录

每个后端工程师都用过 netstat -an,但很少有人真正掌握了 Linux 网络诊断工具链的全部能力。ssnetstat 快两个数量级,但它的过滤语法鲜为人知。ip 命令族替代了 ifconfigroutearpnetstat -r 四个传统工具,功能更强大也更统一。conntrack 是 NAT 和防火墙的连接追踪表,高并发服务的隐形瓶颈常常藏在这里。

本文系统讲解这些工具的工程用法——不是命令手册式的罗列,而是聚焦”在什么场景下用什么命令解决什么问题”。

一、ss:现代 Socket 统计工具

1.1 ss vs netstat:为什么要切换

netstat 通过读取 /proc/net/tcp/proc/net/udp 等文件获取信息,在连接数多时非常慢:

连接数 netstat 耗时 ss 耗时 倍数
1,000 0.3 s 0.01 s 30x
10,000 3.2 s 0.02 s 160x
100,000 35 s 0.08 s 437x
1,000,000 > 5 min 0.5 s > 600x

ss 使用 netlink(SOCK_DIAG)接口直接从内核获取 socket 信息,跳过了 /proc 文件系统的文本解析开销。在百万连接的服务器上,netstat 可能跑不出结果,ss 依然秒级返回。

1.2 ss 基础用法

# 列出所有 TCP 连接
ss -tan

# 列出所有监听端口
ss -tlnp

# 列出所有 UDP socket
ss -uan

# 显示详细信息(包含计时器、内存使用)
ss -tanmi

# 常用选项
# -t  TCP
# -u  UDP
# -a  所有状态(包括 LISTEN)
# -n  不解析域名(速度快)
# -l  只显示 LISTEN
# -p  显示进程信息
# -m  显示内存使用
# -i  显示 TCP 内部信息(cwnd、rtt 等)
# -e  显示扩展信息(UID、cookie 等)
# -o  显示计时器信息

1.3 ss 过滤语法

ss 的过滤语法是它最强大也最被低估的功能。语法分为状态过滤地址/端口过滤两类。

状态过滤

# 只显示 ESTABLISHED 连接
ss -tan state established

# 只显示 TIME-WAIT
ss -tan state time-wait

# 只显示 CLOSE-WAIT(常用于检测连接泄漏)
ss -tan state close-wait

# 多状态组合
ss -tan state established state close-wait

# 预定义状态组
ss -tan state connected      # 所有已连接状态
ss -tan state synchronized   # 已同步状态(不含 SYN-SENT/SYN-RECV)
ss -tan state bucket          # TIME-WAIT 和 SYN-RECV(内核用 mini socket)
ss -tan state big              # 所有非 bucket 状态

TCP 状态过滤支持的值:

established  syn-sent  syn-recv  fin-wait-1  fin-wait-2
time-wait    close     close-wait  last-ack   listening
closing      all       connected   synchronized  bucket  big

地址/端口过滤

# 过滤目标端口
ss -tan 'dport = :443'

# 过滤源端口
ss -tan 'sport = :8080'

# 过滤目标 IP
ss -tan 'dst 10.0.1.100'

# 过滤源 IP
ss -tan 'src 10.0.1.50'

# 组合过滤
ss -tan 'dport = :443 and dst 10.0.1.100'
ss -tan 'sport = :8080 or sport = :8081'

# 端口范围
ss -tan 'dport >= :1024 and dport <= :65535'

# 排除某些端口
ss -tan 'dport != :22'

# 过滤特定子网
ss -tan 'dst 10.0.1.0/24'

1.4 ss 的 TCP 内部信息

ss -ti 显示 TCP 连接的内核参数,这些信息对诊断性能问题至关重要:

ss -ti 'dport = :443' | head -20

输出示例:

ESTAB  0  0  10.0.1.50:54321  10.0.2.100:443
     cubic wscale:7,7 rto:204 rtt:15.2/0.5 ato:40 mss:1448 pmtu:1500
     rcvmss:1448 advmss:1448 cwnd:10 bytes_sent:1234 bytes_acked:1234
     bytes_received:5678 segs_out:15 segs_in:12 data_segs_out:8 data_segs_in:10
     send 7.6Mbps lastsnd:120 lastrcv:80 lastack:80
     pacing_rate 15.2Mbps delivery_rate 6.8Mbps delivered:9
     busy:200ms rcv_rtt:16 rcv_space:29200 rcv_ssthresh:29200
     minrtt:14.8

各字段含义:

字段 含义 工程关注点
cubic 拥塞控制算法 是否使用了预期的算法(BBR?)
rto:204 重传超时,单位 ms 过大说明 RTT 高或有重传历史
rtt:15.2/0.5 平滑 RTT / RTT 方差 方差大说明延迟抖动严重
cwnd:10 拥塞窗口,单位 MSS 过小说明拥塞或刚从丢包中恢复
mss:1448 最大段大小 1448 = 1500 MTU - 40 (IP+TCP) - 12 (TCP options)
pmtu:1500 路径 MTU 小于 1500 说明路径上有 MTU 限制
send 7.6Mbps 当前发送速率 与预期带宽对比
rcv_space:29200 接收窗口通告值 过小可能限制吞吐量
minrtt:14.8 观测到的最小 RTT 最接近物理链路延迟的值

1.5 实战:用 ss 做连接审计

场景 1:检测 CLOSE_WAIT 泄漏

CLOSE_WAIT 表示对端已经关闭连接(发了 FIN),但本端还没调用 close()。如果持续增长,说明应用有连接泄漏:

# 统计 CLOSE_WAIT 按进程分组
ss -tanp state close-wait | \
  awk '{print $NF}' | \
  grep -oP 'users:\(\("\K[^"]+' | \
  sort | uniq -c | sort -rn

# 持续监控 CLOSE_WAIT 趋势
watch -n 5 'ss -tan state close-wait | wc -l'

# 查看具体哪些连接处于 CLOSE_WAIT
ss -tanp state close-wait | column -t

场景 2:查找端口占用

# 谁在用 8080 端口
ss -tlnp 'sport = :8080'
# LISTEN  0  4096  *:8080  *:*  users:(("java",pid=12345,fd=88))

# 如果端口被占用但找不到进程
# 可能是 TIME_WAIT 状态的连接占着
ss -tan 'sport = :8080' state time-wait | wc -l

场景 3:统计连接状态分布

# TCP 状态分布
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn
#  15234 ESTAB
#   3421 TIME-WAIT
#    234 CLOSE-WAIT
#     56 FIN-WAIT-2
#     12 SYN-SENT
#      8 LAST-ACK
#      3 SYN-RECV

# 按目标 IP 统计连接数(找连接最多的目标)
ss -tan state established | awk 'NR>1 {print $5}' | \
  awk -F: '{print $1}' | sort | uniq -c | sort -rn | head -10

# 按进程统计连接数
ss -tanp state established | \
  grep -oP 'users:\(\("\K[^"]+' | \
  sort | uniq -c | sort -rn

二、ip 命令族:统一的网络配置工具

2.1 ip 命令替代关系

ip 命令族统一了原来分散在多个工具中的功能:

传统工具 ip 等价命令 功能
ifconfig ip addr / ip link 接口地址和状态
route ip route 路由表
arp ip neigh ARP/NDP 邻居表
netstat -r ip route show 路由表(同上)
netstat -i ip -s link 接口统计
iptunnel ip tunnel 隧道管理
brctl ip link / bridge 网桥管理

2.2 ip link:接口管理

# 简洁列出所有接口
ip -br link show
# lo      UNKNOWN  00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
# eth0    UP       aa:bb:cc:dd:ee:ff <BROADCAST,MULTICAST,UP,LOWER_UP>
# docker0 DOWN     02:42:xx:xx:xx:xx <NO-CARRIER,BROADCAST,MULTICAST,UP>

# 详细统计(收发字节数、错误数)
ip -s link show eth0

# 设置接口 UP/DOWN
ip link set eth0 up
ip link set eth0 down

# 修改 MTU
ip link set eth0 mtu 9000

# 查看接口详细信息(包括 driver)
ip -d link show eth0

2.3 ip addr:地址管理

# 简洁列出所有地址
ip -br addr show
# lo      UNKNOWN  127.0.0.1/8 ::1/128
# eth0    UP       10.0.1.50/24 fe80::1/64

# 添加地址
ip addr add 10.0.1.51/24 dev eth0

# 删除地址
ip addr del 10.0.1.51/24 dev eth0

# 只看 IPv4
ip -4 addr show

# 只看 IPv6
ip -6 addr show

2.4 ip route:路由管理

# 查看路由表
ip route show
# default via 10.0.1.1 dev eth0 proto dhcp metric 100
# 10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.50
# 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1

# 查看到特定目标的路由
ip route get 8.8.8.8
# 8.8.8.8 via 10.0.1.1 dev eth0 src 10.0.1.50

# 添加静态路由
ip route add 10.0.2.0/24 via 10.0.1.1 dev eth0

# 添加策略路由(多出口场景)
ip rule add from 10.0.1.0/24 table 100
ip route add default via 10.0.1.1 dev eth0 table 100

# 查看路由缓存(已废弃,现代内核用 FIB)
ip route show cache

# 查看特定路由表
ip route show table all | head -20

2.5 ip neigh:邻居表(ARP/NDP)

# 查看 ARP 表
ip neigh show
# 10.0.1.1 dev eth0 lladdr aa:bb:cc:dd:ee:ff REACHABLE
# 10.0.1.2 dev eth0 lladdr 11:22:33:44:55:66 STALE
# 10.0.1.3 dev eth0 FAILED

# 各状态含义
# REACHABLE: 最近确认可达
# STALE: 上次确认已过期,下次使用时会重新验证
# DELAY: 正在等待确认
# PROBE: 正在发送 ARP 探测
# FAILED: ARP 解析失败
# INCOMPLETE: ARP 请求已发送,等待响应

# 手动添加 ARP 条目
ip neigh add 10.0.1.100 lladdr aa:bb:cc:dd:ee:ff dev eth0

# 刷新 ARP 缓存
ip neigh flush dev eth0

# 监控 ARP 变化
ip monitor neigh

2.6 ip 命令的 JSON 输出

ip 命令支持 JSON 输出,方便脚本处理:

# JSON 格式输出
ip -j addr show eth0 | jq '.[0].addr_info[] | select(.family == "inet")'

# 获取 IP 地址
ip -j addr show eth0 | jq -r '.[0].addr_info[] | select(.family == "inet") | .local'

# 获取默认路由网关
ip -j route show default | jq -r '.[0].gateway'

# 批量检查接口状态
ip -j link show | jq '.[] | {name: .ifname, state: .operstate, mtu: .mtu}'

三、conntrack:连接追踪

3.1 conntrack 基础

conntrack 是 Linux netfilter 框架的连接追踪模块。每个经过 netfilter 的连接都会在 conntrack 表中创建一个条目。NAT、有状态防火墙规则都依赖它。

# 查看 conntrack 表大小
cat /proc/sys/net/netfilter/nf_conntrack_count  # 当前条目数
cat /proc/sys/net/netfilter/nf_conntrack_max    # 最大条目数

# 列出所有连接跟踪条目
conntrack -L | head -10
# tcp  6 431999 ESTABLISHED src=10.0.1.50 dst=10.0.2.100 sport=54321 dport=443
#   src=10.0.2.100 dst=10.0.1.50 sport=443 dport=54321 [ASSURED] mark=0

# 按协议统计
conntrack -L 2>/dev/null | awk '{print $1}' | sort | uniq -c | sort -rn
# 85234 tcp
#  3456 udp
#   123 icmp

# 按状态统计(TCP)
conntrack -L -p tcp 2>/dev/null | \
  grep -oP '(ESTABLISHED|TIME_WAIT|CLOSE_WAIT|SYN_SENT|FIN_WAIT|CLOSE|LAST_ACK|SYN_RECV)' | \
  sort | uniq -c | sort -rn

3.2 conntrack 表满的诊断

conntrack 表满是高并发服务器的常见问题,表现为新连接被随机丢弃:

# 检查是否表满
dmesg | grep "nf_conntrack: table full"
# [12345.678] nf_conntrack: table full, dropping packet

# 当前使用率
CURR=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
echo "Usage: $CURR / $MAX ($(( CURR * 100 / MAX ))%)"

# 查看各超时参数
sysctl -a 2>/dev/null | grep conntrack.*timeout | head -10
# net.netfilter.nf_conntrack_tcp_timeout_established = 432000  (5 天!)
# net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
# net.netfilter.nf_conntrack_tcp_timeout_close = 10

# 优化:缩短超时
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600    # 1 小时
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_time_wait=30        # 30 秒

# 优化:增大表上限
sysctl -w net.netfilter.nf_conntrack_max=1048576

# 优化:增大 hash 表大小(减少冲突)
echo 262144 > /sys/module/nf_conntrack/parameters/hashsize

3.3 conntrack 实战查询

# 查看到特定目标的连接
conntrack -L -d 10.0.2.100

# 查看特定端口的连接
conntrack -L -p tcp --dport 443

# 查看 NAT 映射
conntrack -L -n

# 删除特定连接(强制重建)
conntrack -D -s 10.0.1.50 -d 10.0.2.100 -p tcp --dport 443

# 实时监控连接事件
conntrack -E
# [NEW]    tcp  6 120 SYN_SENT src=10.0.1.50 dst=10.0.2.100 ...
# [UPDATE] tcp  6 431999 ESTABLISHED src=10.0.1.50 dst=10.0.2.100 ...
# [DESTROY] tcp  6 src=10.0.1.50 dst=10.0.2.100 ...

# 统计每秒新建连接数
conntrack -E 2>/dev/null | pv -l -i 5 > /dev/null

四、/proc/net/ 文件解读

4.1 关键文件清单

/proc/net/ 下的文件是内核网络状态的直接映射:

# TCP 连接(ss/netstat 的数据来源)
cat /proc/net/tcp | head -5
#  sl  local_address rem_address   st tx_queue rx_queue ...
#   0: 0100007F:1F90 00000000:0000 0A 00000000:00000000 ...
# 0A = 10 = LISTEN 状态
# 地址是十六进制小端序

# TCP 统计
cat /proc/net/snmp | grep Tcp
# Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens ...
# Tcp: 1 200 120000 -1 12345 67890 ...

# 网络统计(更详细)
cat /proc/net/netstat | head -4

# softnet 统计
cat /proc/net/softnet_stat
# 每行一个 CPU,列含义:
# col1: 收到的帧总数
# col2: 因 netdev_budget 用完而 drop 的帧数(> 0 需要关注)
# col3: 因 time_squeeze 而延迟处理的次数

4.2 /proc/net/snmp 的工程解读

这个文件提供了全局的协议统计,是诊断网络问题的重要指标源:

# 解析 TCP 关键指标
awk '/^Tcp:/ {if(NR%2==0) {
    printf "ActiveOpens:  %s\n", $6;
    printf "PassiveOpens: %s\n", $7;
    printf "AttemptFails: %s\n", $8;
    printf "EstabResets:  %s\n", $9;
    printf "CurrEstab:   %s\n", $10;
    printf "InSegs:      %s\n", $11;
    printf "OutSegs:     %s\n", $12;
    printf "RetransSegs: %s\n", $13;
    printf "InErrs:      %s\n", $14;
    printf "OutRsts:     %s\n", $15;
}}' /proc/net/snmp

关键指标解读

指标 含义 异常判断
AttemptFails 连接尝试失败次数 持续增长→对端不可达或防火墙
EstabResets 已建立连接被 RST 次数 持续增长→应用异常关闭或中间设备干扰
RetransSegs 重传的段数 RetransSegs / OutSegs > 1% → 网络质量差
InErrs 接收到的错误段 持续增长→校验和错误或数据损坏
OutRsts 发出的 RST 数 高→大量连接到未监听端口

4.3 监控脚本:TCP 指标持续采集

#!/bin/bash
# tcp-metrics.sh — TCP 指标持续采集
INTERVAL="${1:-5}"

echo "timestamp,active_opens,passive_opens,attempt_fails,estab_resets,retrans_segs,in_errs,out_rsts,curr_estab"

PREV=""
while true; do
    CURR=$(awk '/^Tcp:/ && NR%2==0 {print $6,$7,$8,$9,$10,$11,$12,$13,$14,$15}' /proc/net/snmp)
    TS=$(date '+%Y-%m-%d %H:%M:%S')

    if [ -n "$PREV" ]; then
        # 计算增量
        paste <(echo "$PREV") <(echo "$CURR") | \
          awk -v ts="$TS" '{
            printf "%s,%d,%d,%d,%d,%d,%d,%d,%s\n",
              ts, $11-$1, $12-$2, $13-$3, $14-$4, $15-$5,
              $18-$8, $19-$9, $20
          }'
    fi

    PREV="$CURR"
    sleep "$INTERVAL"
done

输出示例:

timestamp,active_opens,passive_opens,attempt_fails,estab_resets,retrans_segs,in_errs,out_rsts,curr_estab
2025-08-12 14:30:05,234,567,2,1,45,0,5,15234
2025-08-12 14:30:10,245,580,0,0,38,0,3,15267
2025-08-12 14:30:15,212,554,15,8,890,0,45,15190  ← 异常:attempt_fails 和 retrans 飙升

五、netstat 的遗留价值

5.1 netstat 仍然有用的场景

虽然 ss 在性能和功能上全面超越 netstat,但 netstat 在少数场景下仍有价值:

# 协议统计(这个 netstat 的输出比 ss 更直观)
netstat -s | head -40
# Tcp:
#     23456 active connection openings
#     67890 passive connection openings
#     234 failed connection attempts
#     56 connection resets received
#     15234 connections established
#     890123 segments received
#     876543 segments sent out
#     4567 segments retransmitted           ← 重传数
#     12 bad segments received
#     345 resets sent

# 多播组成员
netstat -g

# Unix domain socket
netstat -x
# 或 ss -x

5.2 从 netstat 到 ss 的迁移对照

netstat 命令 ss 等价命令 说明
netstat -an ss -an 所有连接
netstat -tlnp ss -tlnp TCP 监听端口
netstat -s ss -s + nstat 协议统计
netstat -r ip route show 路由表
netstat -i ip -s link show 接口统计
netstat -g ip maddr show 多播组

六、nstat:增量网络统计

nstat 是一个被低估的工具,它显示增量网络统计,比 netstat -s 更适合实时监控:

# 显示自上次调用以来的增量统计
nstat -s

# 持续输出(每 5 秒)
nstat -n 5

# 只看 TCP 相关
nstat -s | grep -i tcp

# 重要指标
nstat -s | grep -E "TcpRetransSegs|TcpTimeouts|TcpAbortOnTimeout|TCPLostRetransmit"
# TcpRetransSegs    456    # 这个周期内的重传段数
# TcpTimeouts       12     # 超时次数
# TCPLostRetransmit 3      # 重传也丢了

nstat 的工程价值:当你怀疑有网络问题但不知道具体是什么时,开一个 nstat -n 5,看哪些计数器在跳——它能快速缩小排查范围。

七、综合实战场景

7.1 场景一:排查 TIME_WAIT 堆积

# 1. 确认 TIME_WAIT 数量
ss -tan state time-wait | wc -l
# 45000  ← 大量 TIME_WAIT

# 2. 看 TIME_WAIT 连接到哪里
ss -tan state time-wait | awk '{print $5}' | awk -F: '{print $1}' | \
  sort | uniq -c | sort -rn | head -5
# 35000 10.0.2.100    ← 绝大部分连到这个 IP

# 3. 这个 IP 是什么服务?
# → 数据库/Redis/下游 API 服务

# 4. 根因分析:短连接太多,每个请求都新建 TCP 连接
# TIME_WAIT 默认持续 60 秒(2 * MSL)

# 5. 解决方案
# 方案 A:启用连接池(根本解决)
# 方案 B:启用 tcp_tw_reuse(允许复用 TIME_WAIT 连接)
sysctl -w net.ipv4.tcp_tw_reuse=1
# 方案 C:减少 TIME_WAIT 持续时间(不推荐,改内核行为)

7.2 场景二:排查连接泄漏

# 1. CLOSE_WAIT 持续增长
watch -n 10 'ss -tan state close-wait | wc -l'
# 从 50 → 200 → 500 → 持续增长

# 2. 找到泄漏的进程
ss -tanp state close-wait | awk '{print $NF}' | sort | uniq -c | sort -rn
# 480 users:(("myapp",pid=12345,fd=...))

# 3. 检查进程的文件描述符
ls /proc/12345/fd | wc -l        # 总 FD 数
ls -la /proc/12345/fd | grep socket | wc -l  # socket FD 数

# 4. 检查 FD 限制
cat /proc/12345/limits | grep "Max open files"
# Max open files  1024  1048576

# 5. 用 lsof 查看具体的 CLOSE_WAIT 连接
lsof -p 12345 -n -i | grep CLOSE_WAIT | head -10

# 6. 根因:应用未正确处理对端关闭
# → 检查 HTTP 客户端是否正确关闭 response body
# Go: defer resp.Body.Close()
# Java: try-with-resources

7.3 场景三:高并发服务连接数审计

#!/bin/bash
# connection-audit.sh — 连接审计报告
echo "=== 连接审计报告 $(date) ==="

echo ""
echo "--- TCP 状态分布 ---"
ss -tan | awk 'NR>1 {s[$1]++} END {for(k in s) printf "%-15s %d\n", k, s[k]}' | sort -k2 -rn

echo ""
echo "--- Top 10 目标 IP (ESTABLISHED) ---"
ss -tan state established | awk 'NR>1 {split($5,a,":"); print a[1]}' | \
  sort | uniq -c | sort -rn | head -10

echo ""
echo "--- Top 10 监听端口 ---"
ss -tlnp | awk 'NR>1 {print $4, $NF}' | sort -t: -k2 -n

echo ""
echo "--- conntrack 使用率 ---"
CURR=$(cat /proc/sys/net/netfilter/nf_conntrack_count 2>/dev/null || echo "N/A")
MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max 2>/dev/null || echo "N/A")
echo "当前: $CURR / 上限: $MAX"

echo ""
echo "--- 网卡错误统计 ---"
for iface in $(ip -br link show | awk '$2=="UP" {print $1}'); do
    ERRORS=$(ip -s link show "$iface" | grep -A 1 "RX:" | tail -1 | awk '{print $3}')
    DROPS=$(ip -s link show "$iface" | grep -A 1 "RX:" | tail -1 | awk '{print $4}')
    echo "$iface: errors=$ERRORS drops=$DROPS"
done

echo ""
echo "--- TCP 重传率 ---"
nstat -s 2>/dev/null | grep -E "TcpRetransSegs|TcpOutSegs" | \
  awk '{a[$1]=$2} END {
    if(a["TcpOutSegs"]>0)
      printf "重传率: %.4f%%\n", a["TcpRetransSegs"]*100/a["TcpOutSegs"]
  }'

八、ip monitor:实时网络事件监控

ip monitor 是一个被忽视的强大工具,它实时监听内核 netlink 事件,能捕获所有网络配置变化:

# 监控所有网络事件
ip monitor all

# 只监控路由变化
ip monitor route

# 只监控邻居(ARP)变化
ip monitor neigh

# 只监控接口状态变化
ip monitor link

# 只监控地址变化
ip monitor address

输出示例:

[ROUTE]  10.0.2.0/24 via 10.0.1.1 dev eth0
[NEIGH]  10.0.1.100 dev eth0 lladdr aa:bb:cc:dd:ee:ff REACHABLE
[LINK]   3: eth1: <BROADCAST,MULTICAST> mtu 1500 state DOWN
[ADDR]   3: eth1 inet 10.0.3.50/24 scope global eth1

工程场景:当你怀疑路由在动态变化导致间歇性故障时,开一个 ip monitor route 持续跑,等待路由跳变的证据。在多网卡服务器上,ip monitor link 能捕获网卡 flapping(频繁上下线)。

8.1 自动化网络事件告警

#!/bin/bash
# net-event-alert.sh — 网络事件实时告警
ip monitor all | while read -r line; do
    TS=$(date '+%Y-%m-%d %H:%M:%S')
    case "$line" in
        *"state DOWN"*)
            echo "[$TS] ALERT: 接口 DOWN - $line"
            ;;
        *"FAILED"*)
            echo "[$TS] ALERT: ARP 解析失败 - $line"
            ;;
        *"Deleted"*route*)
            echo "[$TS] WARN: 路由删除 - $line"
            ;;
    esac
done

8.2 /proc/net/softnet_stat 深度解读

softnet_stat 是诊断网络包处理瓶颈的关键文件:

cat /proc/net/softnet_stat
# 00015a3c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
# 0000f2a1 00000003 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001

每行一个 CPU,前三列最重要:

含义 异常判断
第 1 列 处理的帧总数 各 CPU 应大致均衡
第 2 列 netdev_budget 用完而 drop 的帧 > 0 表示 CPU 忙不过来
第 3 列 time_squeeze,因时间片用完而推迟处理 > 0 表示 softirq 处理不及时
# 友好格式输出
awk '{printf "CPU%d: processed=%d dropped=%d squeezed=%d\n",
    NR-1, strtonum("0x"$1), strtonum("0x"$2), strtonum("0x"$3)}' \
  /proc/net/softnet_stat

如果第 2 列(dropped)持续增长,需要增大 netdev_budget

# 默认值 300,高负载服务器可以增大
sysctl -w net.core.netdev_budget=600
sysctl -w net.core.netdev_budget_usecs=4000

如果处理量集中在 CPU 0,说明需要配置 RPS/RFS 或调整中断亲和。

九、工具选择决策矩阵

你想做什么 首选工具 备选工具 说明
查看监听端口 ss -tlnp netstat -tlnp ss 更快
查看所有连接 ss -tan netstat -an 连接数多时 ss 必选
连接状态分布 ss -tan \| awk netstat -an 脚本化处理
TCP 内核参数 ss -ti 独有功能
路由表 ip route route -n ip 功能更全
ARP 表 ip neigh arp -n ip 支持 NDP
接口状态 ip -br link ifconfig ip 输出更简洁
连接跟踪 conntrack -L /proc/net/nf_conntrack conntrack 有过滤
协议统计 nstat -s netstat -s nstat 显示增量
实时监控 conntrack -E ip monitor 事件驱动

十、总结:工具链的正确使用姿势

  1. ss 替代 netstat。在任何连接数超过 1000 的环境中,ss 的性能优势是决定性的。熟练掌握 ss 的状态过滤和地址过滤语法,它能在一条命令中完成你以前需要 netstat | grep | awk 三步才能做到的事。

  2. ip 替代 ifconfig/route/arpip 命令族是现代 Linux 网络管理的标准工具。-br(简洁模式)和 -j(JSON 模式)让它既适合人眼阅读也适合脚本处理。

  3. conntrack 是高并发的必检项。如果你的服务处理大量短连接(> 10,000 连接/秒),conntrack 表满是第一个要排除的故障。记住检查 dmesg | grep nf_conntrack

  4. nstat 比 netstat -s 更有用nstat 的增量统计模式让你能快速发现”刚才发生了什么”,而不是”历史总量是多少”。排查间歇性问题时,开着 nstat -n 5 等待问题复现。

  5. /proc/net/ 是最底层的数据源。当高级工具都不够用时,直接读 /proc/net/snmp/proc/net/netstat/proc/net/softnet_stat。这些文件是内核的真实状态,没有任何中间层。


参考文献


上一篇:网络故障排查系统化方法:从现象到根因

下一篇:BPF 网络诊断:bpftrace 与 bcc 工具实战

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-08-15 · network

【网络工程】BPF 网络诊断:bpftrace 与 bcc 工具实战

系统讲解 eBPF 在网络诊断中的工程应用:bcc 工具集(tcplife/tcpretrans/tcpdrop)的使用场景、bpftrace 自定义网络探针编写、XDP 丢包分析、内核协议栈延迟追踪,建立基于 eBPF 的系统化网络诊断方法。

2025-08-18 · network

【网络工程】L4 负载均衡:IPVS、LVS 与连接级调度

系统讲解 L4 负载均衡的内核实现:IPVS 的工作原理与三种转发模式(NAT/DR/TUN)、调度算法选择、LVS 高可用方案(Keepalived + VIP)、云环境中的 L4 LB(NLB/MetalLB),建立传输层负载均衡的工程能力。


By .