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

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


前言

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

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

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

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


工具1:ping

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

bash 复制代码
ping -c 4 10.0.1.60
python 复制代码
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 延迟抖动 值大说明网络不稳定

高频用法

bash 复制代码
# 用指定大小的包测试(排查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测试端口级别的连通性。

bash 复制代码
telnet 10.0.1.60 3306
sql 复制代码
Trying 10.0.1.60...
Connected to 10.0.1.60.
Escape character is '^]'.

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

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

输出含义

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

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

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

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

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

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

bash 复制代码
traceroute -n 10.0.1.60
arduino 复制代码
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的升级版

bash 复制代码
mtr -n -c 100 10.0.1.60
erlang 复制代码
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,不影响实际流量。

bash 复制代码
# 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解析有问题。

bash 复制代码
dig api.example.com
css 复制代码
;; 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)

高频用法

bash 复制代码
# 直接查权威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 输出(非常有用)

erlang 复制代码
.                        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服务商。

bash 复制代码
# 查反向解析(IP → 域名)
dig -x 5.6.7.8 +short

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

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

DNS排查速查表

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

工具5:ss(替代netstat)

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

bash 复制代码
# 查看所有监听端口
ss -tlnp
ruby 复制代码
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状态下积压说明发送缓冲区满
bash 复制代码
# 按状态统计连接数
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
yaml 复制代码
  5000 ESTABLISHED
  2000 TIME_WAIT
   500 CLOSE_WAIT
    50 SYN_SENT
bash 复制代码
# 查看特定端口的连接
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 )'
bash 复制代码
# 查看socket统计摘要
ss -s
yaml 复制代码
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(抓包神器)

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

bash 复制代码
# 抓指定端口的包
tcpdump -i eth0 port 8080 -nn
ini 复制代码
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

高频用法

bash 复制代码
# 抓指定主机之间的包
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

实战:排查连接超时

bash 复制代码
tcpdump -i eth0 host 10.0.1.60 and port 3306 -nn

场景A:看到SYN重传

ini 复制代码
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

ini 复制代码
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:看到完整握手但数据传输后超时

makefile 复制代码
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请求有问题。

bash 复制代码
# 看完整的请求和响应头
curl -v http://api.example.com/health
markdown 复制代码
*   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"}

高频用法

bash 复制代码
# 只看响应头(不下载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
makefile 复制代码
DNS解析:     0.023s
TCP连接:     0.045s
TLS握手:     0.120s
首字节时间:   0.350s
总耗时:      0.380s

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

阶段 耗时大说明
DNS解析慢 DNS服务器有问题
TCP连接慢 网络延迟或服务端backlog满
TLS握手慢 证书问题或CPU瓶颈
首字节时间慢 服务端处理慢(查应用日志)
总耗时-首字节时间差大 响应体大,带宽瓶颈
bash 复制代码
# 指定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(路由排查)

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

bash 复制代码
# 查看路由表
ip route show
scss 复制代码
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

重点看什么

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

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

bash 复制代码
# 查看策略路由规则
ip rule show
sql 复制代码
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
bash 复制代码
# 查看特定路由表
ip route show table 100
sql 复制代码
default via 10.0.1.1 dev eth1
10.0.1.0/24 dev eth1 scope link

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


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

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

bash 复制代码
ethtool eth0
yaml 复制代码
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_errors CRC校验错误 网线质量差或光模块故障
bash 复制代码
# 查看ring buffer大小
ethtool -g eth0
yaml 复制代码
Pre-set maximums:
RX:     4096
TX:     4096
Current hardware settings:
RX:     256
TX:     256

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

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

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


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

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

bash 复制代码
# 追踪一个进程的所有网络相关系统调用
strace -f -e trace=network -p 12345
scss 复制代码
[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,说明请求发出去了但在等对端回复。问题在对端。

高频用法

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

# 带时间戳
strace -f -T -e trace=network -p 12345
scss 复制代码
[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秒才回数据。

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

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

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

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

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


排查流程速查

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

arduino 复制代码
第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追踪进程
  └── 定位具体卡在哪个系统调用

速查对照表

场景 首选工具 备选
目标是否可达 ping mtr
端口是否开放 nc -zv telnet
路由路径 mtr traceroute
DNS解析 dig nslookup
连接状态 ss netstat
抓包分析 tcpdump Wireshark
HTTP诊断 curl -w wget
路由表 ip route route
网卡状态 ethtool ip link
进程网络行为 strace ltrace

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

相关推荐
renhailab1 小时前
被免费星巴克咖啡"骗"进 TRAE SOLO,却意外解锁了移动端 AI 办公新姿势
后端
渐儿1 小时前
Agent Harness 工程指南
后端
李日灐2 小时前
【优选算法5】位运算经典算法面试题
后端·算法·面试·位运算
杨运交2 小时前
[014][web模块]构建可重复读取的请求体:Spring Boot 请求缓存过滤器设计与实现
后端
didadida2622 小时前
子路径部署 Vue/React 应用偶发白屏
前端·后端
SamDeepThinking2 小时前
IntelliJ IDEA 中有什么让你相见恨晚的技巧?
java·后端·程序员
SamDeepThinking2 小时前
为什么选微服务而不是动态扩容单体
java·后端·架构
uzong2 小时前
每位工程师都必须掌握的十大数据库扩容策略
后端·架构
Ruihong2 小时前
🔥Vue 转 React 实战:VuReact 实时监听开发指南
vue.js·后端·react.js