Day4、10个排查网络问题的命令行工具:每个配真实输出,建议收藏

0 阅读14分钟

10个排查网络问题的命令行工具:每个配真实输出,建议收藏


前言

线上出问题的时候,最怕的不是问题本身,而是不知道用什么工具去看

ping不通?是网络不通还是端口没开?DNS没解析?是本地缓存还是权威DNS的问题?连接超时?是防火墙拦了还是目标服务没响应?

这些问题,一个命令就能定位。但你得知道用哪个命令、怎么看输出。

今天这篇,10个工具,从最常见的到冷门但救命的,每个都配真实输出和使用场景。不讲man page上那些参数罗列,只讲你排查问题时真正会敲的命令。


工具1:ping

场景: 第一步,确认目标是否可达。

ping -c 4 10.0.1.60
PING 10.0.1.60 (10.0.1.60) 56(84) bytes of data.
64 bytes from 10.0.1.60: icmp_seq=1 ttl=64 time=0.312 ms
64 bytes from 10.0.1.60: icmp_seq=2 ttl=64 time=0.287 ms
64 bytes from 10.0.1.60: icmp_seq=3 ttl=64 time=0.295 ms
64 bytes from 10.0.1.60: icmp_seq=4 ttl=64 time=0.301 ms

--- 10.0.1.60 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.287/0.298/0.312/0.012 ms

重点看什么

字段含义异常信号
packet loss丢包率> 0% 就有问题
time单次往返延迟同机房应 < 1ms,同城 < 5ms
ttl生存跳数突然变化说明路由路径变了
mdev延迟抖动值大说明网络不稳定

高频用法

# 用指定大小的包测试(排查MTU问题)
ping -s 1472 -c 4 目标IP

# 持续ping,观察网络波动(Ctrl+C停止)
ping 目标IP

# 指定源地址(多网卡场景)
ping -I eth1 目标IP

ping不通不代表网络不通

这是最常见的误解。ping不通的可能原因:

  • 目标机器禁了ICMP(iptables -j DROP)
  • 中间防火墙拦截了ICMP
  • 目标服务正常,只是不响应ping

ping只能证明"ICMP可达",不能证明"服务可用"。 ping通了不代表端口开着,ping不通不代表服务挂了。


工具2:telnet / nc(端口连通性)

场景: ping通了,但服务连不上。用telnet或nc测试端口级别的连通性。

telnet 10.0.1.60 3306
Trying 10.0.1.60...
Connected to 10.0.1.60.
Escape character is '^]'.

看到 Connected to 就说明端口通。如果卡在 Trying... 最后超时,说明端口不通。

# nc更轻量,脚本中更常用
nc -zv 10.0.1.60 3306
Connection to 10.0.1.60 3306 port [tcp/mysql] succeeded!
# 测试不通的情况
nc -zv 10.0.1.60 3307 -w 3
nc: connect to 10.0.1.60 port 3307 (tcp) failed: Connection refused

输出含义

结果含义排查方向
succeeded端口通,服务在监听问题在应用层
Connection refused端口不通,目标主动拒绝服务没启动,或iptables REJECT
超时无输出包被丢弃防火墙DROP,或网络不通

Connection refused 和 超时的区别非常重要:

  • refused = 到达了目标机器,目标说"这个端口没人监听"。说明网络通,问题在目标服务。
  • 超时 = 包根本没到达目标机器,或者到了但被防火墙默默丢掉。说明网络层有问题。
# 批量测试多个端口
nc -zv 10.0.1.60 80 443 3306 6379

# 扫描一段端口
nc -zv 10.0.1.60 8000-8010

工具3:traceroute / mtr(路由追踪)

场景: 访问慢,想知道数据包经过了哪些节点、在哪一跳出问题。

traceroute -n 10.0.1.60
traceroute to 10.0.1.60, 30 hops max, 60 byte packets
 1  10.0.0.1      0.5 ms   0.4 ms   0.3 ms
 2  172.16.0.1    1.2 ms   1.1 ms   1.3 ms
 3  * * *
 4  192.168.1.1   3.5 ms   3.2 ms   3.8 ms
 5  10.0.1.60     5.1 ms   4.9 ms   5.0 ms

第3跳全是 * * *,说明那一跳的设备不回ICMP(很常见,不代表有问题)。

traceroute的问题: 只跑一次,结果可能不准。

mtr:traceroute的升级版

mtr -n -c 100 10.0.1.60
Host                  Loss%  Snt   Last  Avg   Best  Wrst  StDev
1. 10.0.0.1           0.0%  100   0.4   0.5   0.3   0.8   0.1
2. 172.16.0.1         0.0%  100   1.2   1.3   1.0   2.1   0.2
3. 192.168.1.1        5.0%  100   3.5   3.8   3.0   8.2   1.1
4. 10.0.1.60          0.0%  100   5.1   5.0   4.8   5.5   0.1

重点看什么

字段含义
Loss%该跳的丢包率
Avg平均延迟
Wrst最大延迟(看尖刺)
StDev延迟标准差(越大越不稳定)

关键判断: 如果某一跳Loss%突然升高,且后续所有跳都保持这个丢包率,那问题就在那一跳。如果某一跳Loss%高但后续跳恢复正常,那大概率是那一跳设备限速ICMP,不影响实际流量。

# TCP模式(绕过ICMP限制,更接近真实流量路径)
mtr -T -P 80 -n -c 50 目标IP

# 指定源地址
mtr -a 10.0.1.50 -n -c 50 目标IP

工具4:dig / nslookup(DNS排查)

场景: 域名访问异常,怀疑DNS解析有问题。

dig api.example.com
;; ANSWER SECTION:
api.example.com.    300    IN    A    5.6.7.8

;; Query time: 23 msec
;; SERVER: 223.5.5.5#53(223.5.5.5)

高频用法

# 直接查权威DNS(绕过本地缓存)
dig api.example.com @ns1.dnspod.net +short
# 5.6.7.8

# 查不同DNS服务器的结果对比
dig api.example.com @114.114.114.114 +short   # 国内公共DNS
dig api.example.com @223.5.5.5 +short         # 阿里DNS
dig api.example.com @8.8.8.8 +short           # Google DNS
dig api.example.com @1.1.1.1 +short           # Cloudflare DNS

# 只看结果,不看额外信息
dig +short api.example.com

# 查看完整解析链路(从根DNS开始追踪)
dig +trace api.example.com

+trace 输出(非常有用)

.                        518400  IN  NS  a.root-servers.net.
.                        518400  IN  NS  b.root-servers.net.
...
com.                     172800  IN  NS  a.gtld-servers.net.
...
example.com.             86400   IN  NS  ns1.dnspod.net.
...
api.example.com.         300     IN  A   5.6.7.8

从根→顶级域→权威DNS逐级追踪,能看到每一级返回了什么。如果中间某一级返回了错误的结果,就能定位问题在哪个DNS服务商。

# 查反向解析(IP → 域名)
dig -x 5.6.7.8 +short

# 查所有记录类型
dig example.com ANY +noall +answer

# 查TTL
dig example.com +noall +answer +ttlid

DNS排查速查表

现象排查命令可能原因
解析到错误IPdig @权威DNS 对比 dig @LocalDNSLocalDNS缓存未刷新或被劫持
解析慢dig 看Query timeDNS服务器响应慢或网络延迟
部分地区解析错误从不同DNS查询对比DNS服务商配置不一致
间歇性解析失败dig +trace 逐级排查某级DNS服务器不稳定

工具5:ss(替代netstat)

场景: 查看当前服务器的连接状态、端口监听情况。

# 查看所有监听端口
ss -tlnp
State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0       128     0.0.0.0:22          0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
LISTEN  0       511     0.0.0.0:80          0.0.0.0:*          users:(("nginx",pid=5678,fd=6))
LISTEN  0       128     127.0.0.1:3306      0.0.0.0:*          users:(("mysqld",pid=9012,fd=23))

重点看什么

字段含义异常信号
LISTEN 的地址0.0.0.0 = 全网监听,127.0.0.1 = 仅本地数据库只该监听127.0.0.1
Recv-Q接收队列积压LISTEN状态下 > 0 说明有连接等待accept
Send-Q发送队列积压ESTABLISHED状态下积压说明发送缓冲区满
# 按状态统计连接数
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
  5000 ESTABLISHED
  2000 TIME_WAIT
   500 CLOSE_WAIT
    50 SYN_SENT
# 查看特定端口的连接
ss -tnp | grep :3306

# 查看特定状态的连接
ss -ant state time-wait
ss -ant state close-wait

# 看连接的详细信息(包含timer)
ss -ant -o state established '( dport = :3306 or sport = :3306 )'
# 查看socket统计摘要
ss -s
Total: 8500
TCP:   7550 (estab 5000, closed 2000, orphaned 50, timewait 2000)

Transport Total     IP        IPv6
RAW       2         1         1
UDP       10        8         2
TCP       5550      5500      50
...

ss比netstat快10倍以上,连接数多的服务器上netstat可能卡住,ss秒出结果。


工具6:tcpdump(抓包神器)

场景: 以上工具都定位不了问题时,抓包看实际网络交互。

# 抓指定端口的包
tcpdump -i eth0 port 8080 -nn
14:23:01.123456 IP 10.0.1.50.45678 > 10.0.1.60.8080: Flags [S], seq 1000000
14:23:01.123789 IP 10.0.1.60.8080 > 10.0.1.50.45678: Flags [S.], seq 2000000, ack 1000001
14:23:01.124012 IP 10.0.1.50.45678 > 10.0.1.60.8080: Flags [.], ack 2000001
14:23:01.125678 IP 10.0.1.50.45678 > 10.0.1.60.8080: Flags [P.], seq 1000001:1000200, ack 2000001
14:23:01.126001 IP 10.0.1.60.8080 > 10.0.1.50.45678: Flags [.], ack 1000200

高频用法

# 抓指定主机之间的包
tcpdump -i eth0 host 10.0.1.50 and host 10.0.1.60 -nn

# 只抓SYN包(看谁在建连接)
tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' -nn

# 只看TCP握手(排除数据包)
tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' -nn

# 抓DNS查询
tcpdump -i eth0 port 53 -nn

# 保存到文件,用Wireshark分析
tcpdump -i eth0 port 80 -nn -w /tmp/capture.pcap

# 限制抓包数量
tcpdump -i eth0 port 80 -nn -c 100

# 读取pcap文件
tcpdump -nn -r /tmp/capture.pcap

实战:排查连接超时

tcpdump -i eth0 host 10.0.1.60 and port 3306 -nn

场景A:看到SYN重传

14:23:01.000 IP 10.0.1.50.45678 > 10.0.1.60.3306: Flags [S]
14:23:02.000 IP 10.0.1.50.45678 > 10.0.1.60.3306: Flags [S]  ← 1秒后重传
14:23:04.000 IP 10.0.1.50.45678 > 10.0.1.60.3306: Flags [S]  ← 2秒后重传

只有SYN出去,没有SYN+ACK回来。说明包被中间设备丢掉了(防火墙拦截)或目标端口没开。

场景B:看到RST

14:23:01.000 IP 10.0.1.50.45678 > 10.0.1.60.3306: Flags [S]
14:23:01.001 IP 10.0.1.60.3306 > 10.0.1.50.45678: Flags [R.]  ← RST

目标端口收到SYN后直接回RST。说明目标机器上3306端口没有进程在监听。

场景C:看到完整握手但数据传输后超时

14:23:01.000 SYN
14:23:01.001 SYN+ACK
14:23:01.002 ACK
14:23:01.003 发送请求数据
14:23:06.003 发送请求数据(5秒后重传)
14:23:16.003 发送请求数据(10秒后重传)

握手正常,但请求数据发出去后没有响应。问题在应用层——服务端收到请求但没处理,或者处理了但响应没发出来。


工具7:curl(HTTP层诊断)

场景: 网络通、端口通,但HTTP请求有问题。

# 看完整的请求和响应头
curl -v http://api.example.com/health
*   Trying 5.6.7.8:80...
* Connected to api.example.com (5.6.7.8) port 80
> GET /health HTTP/1.1
> Host: api.example.com
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 15
<
{"status":"ok"}

高频用法

# 只看响应头(不下载body)
curl -I http://api.example.com

# 看每个阶段耗时(排查慢在哪)
curl -o /dev/null -s -w "
DNS解析:     %{time_namelookup}s
TCP连接:     %{time_connect}s
TLS握手:     %{time_appconnect}s
首字节时间:   %{time_starttransfer}s
总耗时:      %{time_total}s
" http://api.example.com
DNS解析:     0.023s
TCP连接:     0.045s
TLS握手:     0.120s
首字节时间:   0.350s
总耗时:      0.380s

这个输出极其有用。一眼就能看出慢在哪个阶段:

阶段耗时大说明
DNS解析慢DNS服务器有问题
TCP连接慢网络延迟或服务端backlog满
TLS握手慢证书问题或CPU瓶颈
首字节时间慢服务端处理慢(查应用日志)
总耗时-首字节时间差大响应体大,带宽瓶颈
# 指定DNS解析(跳过本地DNS)
curl --resolve api.example.com:80:5.6.7.8 http://api.example.com

# 模拟HTTPS但忽略证书错误(测试环境用)
curl -k https://api.example.com

# 指定源IP(多网卡场景)
curl --interface eth1 http://api.example.com

# 跟随重定向
curl -L http://api.example.com

工具8:ip route / ip rule(路由排查)

场景: 服务器多网卡、多出口,流量走了错误的路径。

# 查看路由表
ip route show
default via 10.0.0.1 dev eth0
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.50
10.0.1.0/24 dev eth1 proto kernel scope link src 10.0.1.50
172.16.0.0/16 via 10.0.0.1 dev eth0

重点看什么

# 查看到特定目的地走哪条路由
ip route get 10.0.1.60
10.0.1.60 dev eth1 src 10.0.1.50
ip route get 8.8.8.8
8.8.8.8 via 10.0.0.1 dev eth0 src 10.0.0.50

场景: 你期望访问10.0.1.60走eth1,但实际走了eth0,导致从错误的源IP发出,被对端防火墙拒绝。

# 查看策略路由规则
ip rule show
0:     from all lookup local
32764: from 10.0.1.50 lookup 100
32765: from 10.0.0.50 lookup 200
32766: from all lookup main
32767: from all lookup default
# 查看特定路由表
ip route show table 100
default via 10.0.1.1 dev eth1
10.0.1.0/24 dev eth1 scope link

多网卡环境下,策略路由决定了"从哪个IP进来的流量,从哪个IP回去"。如果配错了,会出现请求能到但回包走错路径的问题,表现为连接建立后立刻断开或超时。


工具9:ethtool(网卡底层状态)

场景: 网络时好时坏,怀疑是物理层或驱动层的问题。

ethtool eth0
Settings for eth0:
    Speed: 1000Mb/s
    Duplex: Full
    Auto-negotiation: on
    Link detected: yes

    Statistics:
    rx_packets: 12345678
    tx_packets: 9876543
    rx_errors: 0
    tx_errors: 0
    rx_dropped: 150
    tx_dropped: 0
    rx_crc_errors: 0
    rx_fifo_errors: 0

重点看什么

字段含义异常信号
Speed协商速率本该千兆但显示百兆/十兆
Duplex双工模式显示Half就是半双工,性能大降
Link detected物理链路no = 网线没插或交换机端口没开
rx_errors接收错误包数持续增长说明物理链路有问题
rx_dropped接收丢包内核缓冲区满或ring buffer太小
rx_crc_errorsCRC校验错误网线质量差或光模块故障
# 查看ring buffer大小
ethtool -g eth0
Pre-set maximums:
RX:     4096
TX:     4096
Current hardware settings:
RX:     256
TX:     256

当前RX只有256,最大支持4096。高流量场景下可能不够用:

# 调大ring buffer
ethtool -G eth0 rx 2048 tx 2048
# 查看网卡驱动和固件版本(排查驱动bug)
ethtool -i eth0
driver: virtio_net
version: 1.0.0
firmware-version:

虚拟机用的virtio_net,物理机通常是ixgbe、bnxt_en、mlx5_core等。如果遇到奇怪的网络问题,搜一下对应驱动的已知bug。


工具10:strace(系统调用追踪)

场景: 以上工具都查不出问题,进程行为异常但不知道卡在哪。strace能看到进程的每一个系统调用。

# 追踪一个进程的所有网络相关系统调用
strace -f -e trace=network -p 12345
[pid 12345] socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
[pid 12345] connect(8, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.0.1.60")}, 16) = 0
[pid 12345] sendto(8, "...query...", 42, MSG_NOSIGNAL, NULL, 0) = 42
[pid 12345] recvfrom(8,  <unfinished ...>

卡在 recvfrom,说明请求发出去了但在等对端回复。问题在对端。

高频用法

# 追踪文件和网络操作
strace -f -e trace=file,network -p 12345

# 带时间戳
strace -f -T -e trace=network -p 12345
[pid 12345] connect(8, {...sin_port=htons(3306)...}, 16) = 0 <0.003125>
[pid 12345] sendto(8, "...", 42, 0, NULL, 0) = 42 <0.000089>
[pid 12345] recvfrom(8, "...", 16384, 0, NULL, NULL) = 1024 <5.234567>

<5.234567> 就是这个系统调用的耗时。recvfrom花了5.2秒才返回,说明对端处理了5秒才回数据。

# 追踪连接建立失败的原因
strace -f -e trace=connect,socket -p 12345 2>&1 | grep -i "3306"
connect(8, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.0.1.60")}, 16) = -1 ECONNREFUSED

ECONNREFUSED——目标端口拒绝连接。非常明确。

# 追踪DNS解析
strace -f -e trace=network -p 12345 2>&1 | grep "53"

能看到进程是否发了DNS查询、查询发给了哪个DNS服务器、有没有收到回复。

strace是最后的手段。 当你用尽了所有网络工具都定位不了问题时,strace能告诉你进程在系统调用层面到底在干什么。


排查流程速查

遇到网络问题时,按这个顺序来:

1步:ping 目标IP
  ├── 不通 → 检查路由 ip route get、检查防火墙
  └── 通 → 第2步

第2步:nc -zv 目标IP 端口
  ├── Connection refused → 服务没启动或端口错了
  ├── 超时 → 防火墙拦截,用tcpdump确认
  └── succeeded → 第3步

第3步:curl -v(HTTP服务)或对应客户端测试
  ├── 连接建立但无响应 → 抓包看数据交互
  ├── 响应慢 → curl -w 看耗时分布
  └── 响应正常但内容错误 → 应用层问题

第4步:tcpdump抓包
  ├── SYN重传无回复 → 包被丢弃,查防火墙和路由
  ├── 有RST → 端口或服务异常
  └── 握手正常但数据异常 → 应用层bug

第5步:strace追踪进程
  └── 定位具体卡在哪个系统调用

速查对照表

场景首选工具备选
目标是否可达pingmtr
端口是否开放nc -zvtelnet
路由路径mtrtraceroute
DNS解析dignslookup
连接状态ssnetstat
抓包分析tcpdumpWireshark
HTTP诊断curl -wwget
路由表ip routeroute
网卡状态ethtoolip link
进程网络行为straceltrace

这篇偏实操,建议收藏,遇到问题时直接翻出来对照用。下一篇写 一次跨网延迟飙到300ms的排查全过程,把前面几篇的知识串起来做一次完整的故障复盘。