ss / netstat / lsof 端口探查指南
排查网络问题时第一步就是看哪些端口被谁占用。三大工具各有侧重:ss 现代高效(推荐首选),netstat 经典兼容,lsof 万能文件视角。
核心原则:同一 IP 地址上不能有两个服务监听同一端口。
工具速览
| 工具 | 定位 | 优势 | 注意 |
|---|---|---|---|
| ss | 现代 socket 统计 | 快、信息全、默认安装 | 推荐首选 |
| netstat | 经典网络统计 | 兼容老系统 | 已被 ss 替代,部分发行版需单独安装 |
| lsof | 列出打开文件 | 万物皆文件,可查端口+进程+文件 | 需 root 看全量 |
ss — 现代首选
核心命令
# 列出所有监听端口(最常用)
sudo ss -tulnp
# 所有 TCP/UDP 连接(含 ESTABLISHED)
ss -tuan
# 只显示 TCP 监听端口
ss -tln
# 显示进程信息
ss -tlnp
输出字段解读
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=845,fd=3))
| 字段 | 含义 |
|---|---|
| Netid | 协议类型(tcp/udp/tcp6/udp6) |
| State | 连接状态(LISTEN/ESTAB/CLOSE-WAIT/TIME-WAIT 等) |
| Recv-Q / Send-Q | 接收/发送队列字节数(LISTEN 状态 Send-Q 为 backlog) |
| Local Address:Port | 本地地址和端口(0.0.0.0 表示监听所有 IP) |
| Peer Address:Port | 远端地址(LISTEN 状态为 0.0.0.0:*) |
常用过滤
# 只看 LISTEN 状态
ss -tln state listening
# 只看 ESTABLISHED 连接
ss -tn state established
# 过滤特定端口
ss -tlnp '( sport = :80 or sport = :443 )'
# 按远端 IP 过滤
ss -tn dst 10.0.1.5
# 统计各状态连接数
ss -tan | awk 'NR>1{print $1}' | sort | uniq -c | sort -rn
TCP 状态诊断
# 查看 TIME-WAIT 连接数(过多说明短连接频繁)
ss -tan state time-wait | wc -l
# 查看 CLOSE-WAIT(被动关闭方未调用 close,可能应用 bug)
ss -tan state close-wait
# 递归查看 Send-Q 堆积的连接(可能对端接收慢)
ss -tnp 'send > 0'
netstat — 经典备用
netstat 正在被 ss 取代,但大量老脚本和习惯仍在使用:
# 所有监听端口(等价于 ss -tulnp)
netstat -tulnp
# 所有连接(含 UNIX socket)
netstat -anp
# 按进程名过滤
netstat -tlnp | grep nginx
# 统计各状态数量
netstat -an | awk '/^tcp/ {print $NF}' | sort | uniq -c | sort -rn
# 路由表(这是 netstat 的独特功能)
netstat -r
关键状态标志
netstat 输出第六列 State:
| 状态 | 含义 | 常见问题 |
|---|---|---|
| LISTEN | 监听中 | 正常 |
| ESTABLISHED | 已建立连接 | 正常 |
| TIME-WAIT | 主动关闭后等待 | 过多说明短连接频繁 |
| CLOSE-WAIT | 被动关闭未 close | 应用 bug(忘记 close socket) |
| SYN-SENT | 正在发起连接 | 持续 → 对端不可达 |
lsof — 万物皆文件
lsof 不仅看端口,还能查看哪些文件(socket、管道、普通文件)被进程打开:
端口相关
# 列出所有网络连接(等价于 ss -tulnp 的部分功能)
sudo lsof -i
# 查看特定端口被谁占用(最常用的排障命令)
sudo lsof -i :8080
# 查看特定协议
sudo lsof -i tcp
sudo lsof -i udp
# 查看特定进程的所有网络连接
sudo lsof -i -a -p <PID>
# 查看连接状态(LISTEN/ESTABLISHED)
sudo lsof -i tcp -s tcp:listen
sudo lsof -i tcp -s tcp:established
输出字段
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 12345 root 6u IPv4 45678 0t0 TCP *:80 (LISTEN)
| 字段 | 含义 |
|---|---|
| COMMAND | 进程名 |
| PID | 进程 ID |
| USER | 所属用户 |
| FD | 文件描述符(6u = fd 6, read/write) |
| TYPE | IPv4/IPv6/unix |
| NAME | 连接的本地和远端地址 |
查看其他打开文件
# 进程打开的所有文件
sudo lsof -p <PID>
# 谁在使用某个文件/目录
sudo lsof /var/log/nginx/access.log
# 查看被删除但仍被进程占用的文件(磁盘空间不释放)
sudo lsof +L1
# 查看特定用户打开的文件
sudo lsof -u nginx
实战场景
场景一:端口已被占用,新服务无法启动
# 快速确认谁占用了 80 端口
sudo lsof -i :80
# 或
sudo ss -tlnp 'sport = :80'
# 查看该进程详情
ps aux | grep <PID>
# 释放端口(kill 占用进程)
sudo kill -9 <PID>
场景二:服务器有大量 TIME-WAIT 连接
# 统计 TIME-WAIT 数量
ss -tan state time-wait | wc -l
# 如果超过数千,调整内核参数:
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=30
场景三:排查 CLOSE-WAIT 堆积(应用 bug)
# 查看 CLOSE-WAIT 连接
ss -tan state close-wait
# 定位到进程后检查代码:被 close() 后的 socket 是否正确关闭
场景四:磁盘满了但找不到大文件
# 可能是已删除文件仍被进程占用
sudo lsof +L1 | awk '{print $2}' | sort -u | while read pid; do
ps -p $pid -o comm=
done
命令速查
# ss(推荐)
ss -tlnp # TCP 监听端口 + 进程名
ss -tulnp # TCP/UDP 监听端口
ss -tan state time-wait # 只看 TIME-WAIT
# netstat
netstat -tulnp # TCP/UDP 监听端口
netstat -an | awk '{print $NF}' | sort | uniq -c | sort -rn # 连接状态统计
# lsof
lsof -i :8080 # 谁在用 8080
lsof -i -s tcp:listen # 所有 TCP 监听
lsof -p <PID> # 进程打开的所有文件
lsof +L1 # 已删除但仍占用的文件
关联页面
| 页面 | 关联点 |
|---|---|
| network-troubleshooting-order | 服务器网络排障七步法(含 ss/netstat 实战场景) |
| linux-essential-commands-reference | Linux 30 个高频命令速查手册(ss/netstat/lsof 等核心命令速查) |
| journalctl-log-tracking-guide | journalctl 日志管理指南 |
| server-performance-four-dimensions | 服务器五维排查(网络维度配合工具) |