别再ping着发呆了:银行老运维的10分钟网络排障法 云间豹变 | Linux调优实战系列 记得某次半夜值班遇到告警,应用电话打过来:「A系统调B系统接口,间歇超时,帮忙看一下网络。」 我揉了揉眼睛, ping 10.10.1.20 ——通。 telnet 10.10.1.20 8080 ——通。 「网络没问题啊,你们应用层自己查。」 挂了电话,五分钟后告警又来了,一晚上反复如此,第二天还被喷没解决问题。 这是我早年入行踩过最深的坑:ping通,不等于网络没问题。 后来我整理了一套「10分钟网络定位法」,从那以后再也没被这类网络基础问题「骚扰」过。 先建一张「网络排查地图」 从技术原理角度来看,银行生产环境的网络问题,藏在至少6个层面。出了事你得知道先查哪层: 排查层面 工具 能看到什么 连通性 ping /  ping6 基础ICMP可达性 路由 ip route /  traceroute 包走的路径,在哪一跳丢的 端口 ss /  netstat 本地监听和连接状态 DNS dig /  nslookup 域名解析对不对 网卡物理层 ethtool /  ip addr 网卡UP、协商速率、有无错包 抓包 tcpdump 包到底有没有到本机,TCP握手细节 应用层 curl -w 请求慢在哪一段(DNS/TCP/SSL/服务端) 10分钟排障法则的核心 :不要上来就ping。先问清楚症状(慢?不通?间歇?),再从底层往上层逐层查。 六个命令,覆盖物理层到应用层 ① ss — 连接状态一看就懂 # 查看所有TCP连接,按状态分组统计 # NR>1 跳过表头行,避免把 "State" 也算进去 ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn # 查看哪个进程在监听8080端口(排障必用) sudo ss -tlnp | grep 8080 # 查看已建立的连接,按本地端口聚合,看有没有异常外联 # state established 比简写 est 兼容性更好(老版本 RHEL/CentOS 适用) ss -tn state established | awk 'NR>1 {print $4}' | sort | uniq -c | sort -rn | head -20 ② ip route — 路由表是第一现场 # 查看路由表,默认路由指向谁 ip route show # 追踪到目标IP的路径(每一跳延迟,IP都是随便取的,无需在意) traceroute -n 10.10.1.20 # 或者用mtr(实时刷新,推荐) mtr -r -c 10 10.10.1.20 ③ tcpdump — 抓包,看清包到底到没到 # 抓取到达eth0的HTTP流量(排障神器) sudo tcpdump -i eth0 -nn port 80 and host 10.10.1.20 -c 100 # 抓取ICMP包,看ping的包有没有出去 sudo tcpdump -i eth0 -nn icmp # 保存到文件,事后用Wireshark分析 sudo tcpdump -i eth0 -w /tmp/capture.pcap port not 22 ④ dig — DNS问题别再背锅了 # 查A记录,看解析对不对 dig +short api.example.com # 追踪DNS解析全过程(看是哪一层DNS的问题) dig +trace api.example.com # 反向解析,从IP查域名(安全审计常用) dig -x 10.10.1.20 ⑤ ethtool — 网卡物理层排障 # 看网卡是否UP、协商速率和双工模式(百兆/千兆/万兆) ethtool eth0 | grep -E "Speed|Duplex|Link detected" # 看网卡驱动信息和固件版本 ethtool -i eth0 # 看网卡收发包统计(有多少错误、丢包) ethtool -S eth0 | grep -iE "drop|error|discard" 💡  什么时候用 ethtool?  当你怀疑是"网线松了""网卡掉速""协商到百兆而不是千兆"这类物理层问题的时候。 ping  看不出来, ss  也看不出来,只有  ethtool  能确认。 ⑥ curl — 应用层时间拆解(从开发角度排查必备) # 把一次HTTP请求的时间拆成 DNS→TCP握手→SSL→服务端处理 四段 curl -w '\nDNS解析: %{time_namelookup}s TCP握手: %{time_connect}s SSL握手: %{time_appconnect}s 服务端首字节: %{time_starttransfer}s 总耗时:    %{time_total}s\n' \    -o /dev/null -s http://10.10.1.20:8080/api/health 💡  ping  告诉你网络通不通, curl -w  告诉你 慢在哪一段 。DNS 慢找 DNS,TCP 握手慢找路由,服务端慢找应用——不用猜。 真实案例:10分钟从「ping通」找到「MTU丢包」 这是我处理过最「烧脑」的一次故障。 故障现象 :应用A调用应用B的接口,小请求正常(GET /health 秒回),但带 payload 的 POST 大请求就超时。A和B在同一网段, ping  正常, telnet  端口也通。 定位过程(实际耗时10分钟) : # 第1分钟:确认基础连通性 ping 10.10.1.20 # 通。不是网络不通的问题。 # 第2分钟:用curl模拟大请求——复现问题 curl -X POST -d "$(dd if=/dev/urandom bs=1000 count=50 2>/dev/null | base64)" \    --connect-timeout 3 --max-time 10 \    http://10.10.1.20:8080/api/submit # 超时!小请求OK,带body的大请求挂。 # 第3分钟:检查TCP握手时的MSS协商(tcpdump抓包) sudo tcpdump -i eth0 -nn 'tcp port 8080 and (tcp[tcpflags] & tcp-syn != 0)' -c 3 # 看到 A→B SYN 包中 MSS=1460(A端MTU 1500 正常) # 看到 B→A SYN-ACK 包中 MSS=8960(B端MTU 9000 巨帧!) 问题就在 MSS=8960 。 B 端虚拟机迁移后网卡被配成了 MTU=9000。TCP 握手时,B 向 A 通告 "我能收 8960 字节的 TCP 段"。A 端客户端看到这个值,尝试构造接近 8960 字节的大段发送——但 A 自己的网卡 MTU 只有 1500,内核只能做  IP 分片 。 # 第4分钟:验证分片行为 ip link show eth0 | grep mtu # A端: mtu 1500 ip link show eth0 | grep mtu  # 在B端执行 # B端: mtu 9000  ← 问题在这 被分片的 IP 包经过交换机时,部分交换机对分片包的处理不稳定——重组队列有限、分片可能乱序到达。 一旦有一个分片丢了,B 端的 TCP 层就永远等不到完整段,应用层超时。  小请求为什么没事?因为小于 1460 字节,根本不需要分片。 # 第5分钟:临时修复——把B端MTU改回1500,立即恢复 sudo ip link set eth0 mtu 1500 # 验证:再次curl大请求 curl -X POST -d "$(dd if=/dev/urandom bs=1000 count=50 2>/dev/null | base64)" \    --connect-timeout 3 --max-time 10 \    http://10.10.1.20:8080/api/submit # 正常返回! 永久生效 (根据是否使用 NetworkManager 选一种,切记提工单去做): # 方式一:传统 network-scripts(RHEL 7 及以前) sed -i 's/^MTU=.*/MTU=1500/' /etc/sysconfig/network-scripts/ifcfg-eth0 # 方式二:NetworkManager(RHEL 8+ 及大部分现代发行版) nmcli con mod eth0 802-3-ethernet.mtu 1500 nmcli con up eth0 从告警到恢复, 10分钟搞定手工 。 如果用传统方式——先找应用组查代码、再找网络组查路由、再逐层拉会——这个故障保底耗2小时。 放进crontab的网络巡检脚本 不要等出事才查。这个脚本每天跑一次,主动发现问题: #!/bin/bash # network_check.sh — 日常网络健康巡检 REPORT="/tmp/network_report_$(date +%Y%m%d).txt" echo"=== 网络巡检报告 $(date) ===" > "$REPORT" # 1. 检查默认路由是否存在 DEFAULT_ROUTE=$(ip route | grep default | wc -l) echo"默认路由数量: ${DEFAULT_ROUTE}" >> "$REPORT" [ "$DEFAULT_ROUTE" -eq 0 ] && echo"[WARN] 缺少默认路由!" >> "$REPORT" # 2. 检查DNS配置是否正常(银行环境不通外网,改查本地resolver) DNS_NS=$(grep -c '^nameserver' /etc/resolv.conf 2>/dev/null) echo"DNS服务器数量: ${DNS_NS}" >> "$REPORT" [ "$DNS_NS" -eq 0 ] && echo"[WARN] 未配置DNS服务器!" >> "$REPORT" # 能访问外网的机器可以加一步验证:dig +time=2 +short 你的内网域名 # 3. 检查网卡状态和协商速率 for iface in $(ls /sys/class/net/ | grep -v lo); do   STATE=$(cat /sys/class/net/$iface/operstate 2>/dev/null || echo"N/A")   SPEED=$(ethtool $iface 2>/dev/null | grep -oP 'Speed: \K.*')   [ -z "$SPEED" ] && SPEED="N/A" echo"网卡 $iface: 速率=${SPEED} 状态=${STATE}" >> "$REPORT"   [ "$STATE" != "up" ] && echo"[WARN] 网卡 $iface 不是UP状态!" >> "$REPORT" done # 4. 检查MTU是否与标准值一致(巨帧未关是常见坑) for iface in $(ls /sys/class/net/ | grep -v lo); do   MTU=$(cat /sys/class/net/$iface/mtu 2>/dev/null)   [ -n "$MTU" ] && [ "$MTU" -ne 1500 ] && \     echo"[WARN] 网卡 $iface MTU=${MTU} (非标准1500)!" >> "$REPORT" done # 5. 检查异常连接数(根据业务实际情况调整阈值) ESTAB_COUNT=$(ss -tn state established | tail -n +2 | wc -l) echo"当前ESTABLISHED连接数: ${ESTAB_COUNT}" >> "$REPORT" [ "$ESTAB_COUNT" -gt 500 ] && echo"[WARN] 连接数超阈值(${ESTAB_COUNT}),请核查" >> "$REPORT" # 6. 检查有没有丢包的网卡 for iface in $(ls /sys/class/net/ | grep -v lo); do   RX_DROP=$(cat /sys/class/net/$iface/statistics/rx_dropped 2>/dev/null || echo 0)   TX_DROP=$(cat /sys/class/net/$iface/statistics/tx_dropped 2>/dev/null || echo 0)   [ "$RX_DROP" -gt 100 ] && echo"[WARN] $iface RX丢包: $RX_DROP" >> "$REPORT"   [ "$TX_DROP" -gt 100 ] && echo"[WARN] $iface TX丢包: $TX_DROP" >> "$REPORT" done cat "$REPORT" 和之前排查日志一样 别再tail -f发呆了:银行老运维的10分钟日志排障法 ,加进crontab每天早上8点跑一次: 0 8 * * * /opt/scripts/network_check.sh >> /var/log/network_daily.log 2>&1 尾声 10分钟定位,不是玄学,是方法。 地图建好了,从底层往上层逐层推——物理网卡→路由→传输层→应用端口,基本不会走弯路。 下次碰到网络故障,不用只会ping了。 你遇到过最「烧脑」的网络故障是什么? 是MTU不匹配,还是路由表被误改? 评论区聊聊,没准能帮到下一个正在ping着发呆的人。 👉 觉得有用就转发给你的运维bro,在网络排障的时候说不定用得上 如果不想错过下一期排障实战,点个关注,每次更新直接推到你微信里。顺手点个「在看」,让我知道这类干货你们爱看。