2. 常见排错工具:netstat、ss、lsof、tcpdump、strace 的使用方法与实战技巧

端口复用出了问题,你第一反应是什么?

我个人的习惯是——先别急着翻代码,先看看系统到底在干什么。说白了,排错就像破案,你得先有线索。而 netstat、ss、lsof、tcpdump、strace 这五个工具,就是我最常用的「现场勘查工具」。

这一章,我把它们的使用方法和实战技巧掰开揉碎讲清楚。每个工具我都会结合真实场景,告诉你什么时候用它、怎么用、以及常见的坑在哪。

核心思路:排错不是靠猜,是靠证据。这五个工具分别从「连接状态」「进程绑定」「网络流量」「系统调用」四个维度给你证据。你掌握得越熟练,定位问题的速度就越快。

端口复用排错工具知识体系 排错工具链 netstat ss lsof tcpdump strace 查看连接状态 统计端口监听 替代 netstat 性能更好更快 查看进程打开 的文件和端口 抓包分析 网络流量 追踪系统调用 定位内核交互 四维排错:连接状态 → 进程绑定 → 网络流量 → 系统调用

2.1 netstat —— 老牌工具,但别滥用

netstat 是我刚入行时用的第一个网络排错工具。说实话,现在生产环境我很少用它了,因为 ss 更快。但有些老系统上只有 netstat,你还是得会用。

常用场景:查看某个端口是否在监听、统计当前连接数。

# 查看所有监听端口
netstat -tlnp

# 查看所有连接(包括已建立的)
netstat -anp | grep 8080

# 统计各状态连接数
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

我的经验:netstat 的 -tlnp 组合是我最常用的。t 表示 TCP,l 表示 listening,n 用数字显示地址,p 显示进程信息。少一个参数,输出就可能让你看花眼。

注意:netstat 在连接数多的机器上会非常慢。我曾经在一台有 10 万连接的网关设备上跑 netstat,结果卡了将近 30 秒才出结果。这种场景下,请用 ss。

2.2 ss —— 现代替代品,性能碾压

ss 是 iproute2 包里的工具,说白了就是 netstat 的升级版。它直接从内核的 socket 信息中读取数据,而不是解析 /proc 文件系统,所以 速度比 netstat 快一个数量级。

我个人习惯:只要系统支持,我就用 ss 代替 netstat。

# 查看所有 TCP 监听端口
ss -tlnp

# 查看所有 UDP 监听端口
ss -ulnp

# 查看指定端口(比如 8080)
ss -tlnp | grep 8080

# 查看所有已建立的连接
ss -tunp state established

# 按状态过滤(比如 TIME-WAIT)
ss -tunp state time-wait
对比项 netstat ss
数据来源 /proc/net/tcp 等 内核 netlink 接口
性能 连接数多时慢 快,适合高并发
状态过滤 需配合 grep/awk 原生支持 state 过滤
推荐场景 老系统、临时查看 生产环境首选

实战技巧:用 ss 排查端口复用冲突时,我经常这样用:ss -tlnp sport = :8080。这个语法可以直接过滤源端口,比 grep 精准得多。

2.3 lsof —— 谁动了我的端口?

lsof 的全称是 List Open Files。在 Linux 里,一切皆文件,socket 也是文件。所以 lsof 能告诉你:哪个进程打开了哪个端口。

我记得有一次线上告警,说 3306 端口被占用了。用 netstat 一看,确实有进程在监听,但进程名显示不出来(权限问题)。这时候 lsof 就派上用场了。

# 查看哪个进程占用了 3306 端口
lsof -i :3306

# 查看某个进程打开了哪些端口
lsof -i -p 12345

# 查看所有 TCP 监听
lsof -iTCP -sTCP:LISTEN

# 查看某个用户的所有网络连接
lsof -i -u nginx

避坑指南:lsof 默认会解析主机名,如果 DNS 有问题,它会卡住。加上 -n 参数(不解析主机名)可以避免这个问题。我习惯用 lsof -nP -i :端口,P 表示不解析端口名。

2.4 tcpdump —— 网络排错的终极武器

tcpdump 是抓包工具。当 netstat 和 ss 告诉你「有连接」,但应用层就是不通时,就该 tcpdump 上场了。

说白了,tcpdump 能让你看到 网络上实际发生了什么,而不是进程以为发生了什么。

# 抓取 8080 端口的流量
tcpdump -i any port 8080

# 抓取指定主机的流量
tcpdump -i eth0 host 192.168.1.100

# 抓取并保存到文件(方便后续分析)
tcpdump -i any -w capture.pcap port 8080

# 读取抓包文件
tcpdump -r capture.pcap

# 抓取 TCP 三次握手包
tcpdump -i any 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0'

注意:tcpdump 需要 root 权限。另外,在生产环境抓包时,尽量用 -c 数量 限制抓包数量,或者用 -s 0 抓完整包(默认只抓前 68 字节)。我曾经见过有人没加限制,直接把磁盘抓满了……

实战场景:端口复用导致连接被错误路由时,tcpdump 能帮你看到 SYN 包发到了哪个进程。比如你期望连接打到 Nginx,结果 tcpdump 显示 SYN 被另一个进程的 socket 接收了——这就是典型的端口复用冲突。

2.5 strace —— 深入内核的最后一步

strace 追踪进程的系统调用。当上面四个工具都查不出问题时,我会用 strace 看看进程到底在干什么。

嗯,这里要注意:strace 对性能有影响,生产环境慎用。

# 追踪某个进程的系统调用
strace -p 12345

# 只追踪网络相关的系统调用
strace -p 12345 -e trace=network

# 追踪 bind、listen、accept 等调用
strace -p 12345 -e trace=bind,listen,accept

# 输出到文件
strace -p 12345 -o /tmp/strace.log

# 追踪新启动的进程
strace -f -o /tmp/strace.log ./myapp
系统调用 含义 排错场景
bind() 绑定端口 端口被占用时返回 EADDRINUSE
listen() 开始监听 确认进程是否真的在监听
accept() 接受连接 确认连接是否被接收
setsockopt() 设置 socket 选项 检查 SO_REUSEADDR 是否设置

我的经验:有一次排查端口复用问题,用 netstat 和 lsof 都显示进程在监听,但就是连不上。最后用 strace 一看,发现进程调了 bind() 之后根本没调 listen()——代码写漏了。这种问题,只有 strace 能抓到。

2.6 五工具协同排错实战流程

光知道单个工具怎么用还不够,你得知道 什么时候用哪个。下面是我总结的排错流程:

  1. 第一步:ss 快速扫描 —— 查看目标端口是否在监听,状态是否正常。
  2. 第二步:lsof 确认进程 —— 如果端口在监听,确认是哪个进程。
  3. 第三步:tcpdump 抓包 —— 如果连接异常,抓包看网络层面发生了什么。
  4. 第四步:strace 深挖 —— 如果网络层面正常,但应用层异常,追踪系统调用。
  5. 第五步:交叉验证 —— 用多个工具的结果互相印证,避免单一工具误导。

核心原则:从外到内,从快到慢。先用轻量工具缩小范围,再用重量工具精确定位。别一上来就 strace,那就像用大炮打蚊子。