4、排查工具之netstat:基本用法、查看端口状态、过滤特定端口
说到端口排查,netstat 是我用得最多的命令,没有之一。这工具老归老,但真到了线上环境,它往往是最快能给你答案的那个。我记得刚入行那会儿,师父就丢给我一句话:「端口出问题?先 netstat -anp 看一眼。」这么多年过去了,这个习惯一直没变。
说白了,netstat 就是用来查看当前系统上网络连接状态的。哪个端口在监听、哪个进程占着它、连接是 ESTABLISHED 还是 TIME_WAIT,它都能告诉你。在 TLS 连接场景里,端口被占、端口耗尽、端口冲突,这些破事儿全靠它来定位。
4.1 基本用法:三板斧先记住
我个人习惯把 netstat 的常用参数分成三组,记牢这三组,日常排查基本够用。
| 参数组合 | 作用 | 适用场景 |
|---|---|---|
-anp |
显示所有连接和监听端口,不解析域名,带进程信息 | 通用排查,看谁占着端口 |
-tunp |
只看 TCP/UDP,不显示 Unix socket | 网络连接排查,过滤掉无关信息 |
-lntup |
只看正在监听的 TCP/UDP 端口 | 检查服务是否启动、端口是否开放 |
我的习惯: 每次上机器第一件事就是 netstat -tunp。为什么?因为不加 -t 和 -u 的话,会刷出一堆 Unix socket 和 raw socket,信息太杂,看着头疼。
# 最常用的组合
netstat -tunp
# 输出示例(简化版)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 1234/nginx
tcp 0 0 192.168.1.10:443 10.0.0.5:54321 ESTABLISHED 1234/nginx
tcp 0 0 192.168.1.10:443 10.0.0.6:54322 TIME_WAIT -
你看,输出里每一列都很清楚:本地地址、远端地址、连接状态、进程 PID 和名字。嗯,这里要注意,TIME_WAIT 那一行的 PID 是 -,因为连接已经关闭了,进程信息自然就没了。
4.2 查看端口状态:五种常见状态你得认识
在 TLS 连接排查里,端口状态是最直接的线索。我遇到过不少同事,看到 TIME_WAIT 就慌,其实大可不必。下面这五种状态,是你在排查时最常碰到的。
| 状态 | 含义 | TLS 场景下的常见原因 |
|---|---|---|
LISTEN |
端口正在监听,等待连接 | 服务端 TLS 端口正常开放 |
ESTABLISHED |
连接已建立,正在通信 | TLS 握手完成,数据传输中 |
TIME_WAIT |
连接已关闭,端口还在等待 | 短连接场景下大量出现,正常现象 |
CLOSE_WAIT |
对方关闭了连接,本机还没关 | 应用层没调用 close(),代码有 bug |
SYN_SENT |
正在尝试建立连接 | 客户端发起 TLS 连接,但服务端没响应 |
避坑指南: 我曾经在排查一个 TLS 长连接泄漏问题时,发现 CLOSE_WAIT 状态堆积了上千个。当时第一反应是网络问题,查了半天才发现是应用层代码里忘了处理连接关闭事件。记住,CLOSE_WAIT 基本等于「代码有坑」,别往网络方向瞎找。
4.3 过滤特定端口:精准定位问题
生产环境上跑着几十个服务,端口一大堆。你总不能一个个数吧?这时候就得学会过滤。我常用的过滤方式有两种:grep 和 awk。
4.3.1 用 grep 过滤端口
最简单粗暴的方法,直接搜端口号。
# 查看 443 端口的所有连接
netstat -tunp | grep ':443'
# 查看 8443 端口的监听状态
netstat -lntup | grep ':8443'
# 排除 22 端口(SSH),只看业务端口
netstat -tunp | grep -v ':22'
你想想看,如果服务端 TLS 端口是 443,客户端连不上,第一件事就是跑 netstat -lntup | grep ':443'。如果没输出,说明服务根本没在监听;如果有 LISTEN,再看防火墙和证书问题。
4.3.2 用 awk 精确提取
grep 有时候会误匹配,比如你搜 :443,结果把 :4432 也带出来了。这时候 awk 更靠谱。
# 精确匹配本地端口为 443 的连接
netstat -tunp | awk '$4 ~ /:443$/'
# 只看 ESTABLISHED 状态的连接
netstat -tunp | awk '$6 == "ESTABLISHED"'
# 统计各种状态的连接数
netstat -tunp | awk 'NR>2 {print $6}' | sort | uniq -c | sort -rn
小技巧: 我习惯把最后那个统计命令存成别名 alias connstat='netstat -tunp | awk '\''NR>2 {print $6}'\'' | sort | uniq -c | sort -rn'。每次怀疑端口耗尽时,跑一下就能看到 TIME_WAIT 是不是堆积了。
4.4 实战场景:用 netstat 定位 TLS 端口问题
光讲理论没意思,我拿一个真实案例来说说怎么用。
有一次线上告警,说某个 TLS 服务连不上了。我登录机器,先跑了一组命令:
# 第一步:看服务在不在监听
netstat -lntup | grep ':8443'
# 输出:tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 5678/java
# 服务在监听,没问题
# 第二步:看连接状态
netstat -tunp | grep ':8443' | awk '{print $6}' | sort | uniq -c
# 输出:
# 234 ESTABLISHED
# 1896 TIME_WAIT
# 12 SYN_SENT
# 问题来了:TIME_WAIT 太多,SYN_SENT 也有
# 第三步:看 SYN_SENT 连的是谁
netstat -tunp | grep ':8443' | awk '$6 == "SYN_SENT"'
# 发现大量连接在尝试连同一个后端 IP
你看,三步下来问题就清楚了:服务端监听正常,但客户端因为 TIME_WAIT 太多导致端口耗尽,新的连接只能卡在 SYN_SENT。解决方案就是调整内核参数 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_fin_timeout。
核心思路: netstat 不是万能的,但它能帮你快速缩小排查范围。看到 LISTEN 正常,就别在服务端配置上浪费时间;看到 SYN_SENT 堆积,就往网络和端口资源方向查。说白了,它就是你的「第一眼工具」。
4.5 知识体系:netstat 在端口排查中的位置
下面这张图,是我自己总结的 netstat 排查思路,你一看就明白。
这张图说白了就是我的「排查三板斧」:先看服务端有没有在监听,再看连接状态分布,最后根据异常状态(TIME_WAIT、CLOSE_WAIT、SYN_SENT)去追根溯源。你照着这个流程走,大部分端口问题都能在五分钟内定位到根因。