端口被占了?用 ss 和 lsof 三分钟定位真凶
每个在 Linux 上部署过服务的人都遇到过这句报错:Address already in use。端口明明"没人在用",进程却起不来;或者反过来,你想确认某个服务真的在监听 80 端口,却不知道该敲哪条命令。Linux 下的答案是两件工具:ss 和 lsof。这篇短文把它们的分工、常用组合和几个容易踩的坑一次讲清楚。
先记住分工
ss 属于 iproute2 套件,作用是"看 socket":谁在监听、连接状态如何、队列积压多少。它查的是内核 socket 表本身,速度极快。lsof 则是"看打开的文件"——在 Linux 里 socket 也是一种文件,所以 lsof -i 能把 socket 反查到具体的进程号和进程名。一个从 socket 出发找进程,一个从进程出发找 socket,方向正好相反。
场景一:端口被占,找出占用的进程
最快的组合是:
sudo ss -ltnp 'sport = :8080'
-l只看监听(Listen)socket,-t只看 TCP,-n不做域名解析(否则会很慢),-p显示占用它的进程。- 过滤表达式
'sport = :8080'直接锁定本地端口,比grep 8080更精确,不会误匹配到 PID 里恰好含 8080 的行。
如果 ss 没装(比如极简容器),用 lsof 顶上:
sudo lsof -i :8080 -sTCP:LISTEN
-sTCP:LISTEN 把结果限定在监听状态,避免一堆 ESTABLISHED 连接刷屏。
场景二:进程在,端口却"看不懂"
有时候 ss -ltnp 里看到进程名是空的——这通常是权限问题:非 root 用户看不到别的用户进程的 -p 信息,前面加 sudo 即可。另一个常见困惑是出现 users:(("nginx",pid=123,fd=6)) 好几行,那是 master 进程 fork 出的多个 worker 共享监听 fd,属正常现象,不用逐个杀。
场景三:TIME_WAIT 一大堆,算不算端口泄漏?
排查线上问题时常见 ss -s 输出里有成百上千个 timewait。TCP 主动关闭方会在 TIME_WAIT 停留 2MSL(默认约 60 秒),这是协议设计的一部分,不是 bug。确认办法:
ss -tan state time-wait | wc -l
只要对端四元组不冲突,内核可以复用端口(开启 tcp_tw_reuse 更好),一般无需处理。真正要警惕的是大量 close-wait——那说明本应用收到对端 FIN 后一直没调 close(),几乎都是代码里忘了关连接,这时用 lsof -p <pid> 看该进程持有的 socket 数量,配合应用日志定位泄漏点。
小结
日常排查记住三句话:找"谁占了端口"用 ss -ltnp(配 sudo);ss 没信息就用 lsof -i :端口 反查进程;连接状态异常先看 ss -s 里 TIME_WAIT 和 CLOSE_WAIT 的比例。两个工具都不需要额外安装,熟练之后,绝大多数端口问题都能在三分钟内定位。
- 点赞
- 收藏
- 关注作者
评论(0)