本地排查端口占用时,ss 的输出比只看 lsof 更顺手

33 次浏览3 条回复

最近遇到服务启动失败、提示端口已经被占用时,我会先看监听进程和地址,不急着改配置。环境:Linux,iproute2(含 ss)。

ss -ltnp 'sport = :8080'

想看所有监听中的 TCP 端口:

ss -ltnp

-l 看监听,-t 限定 TCP,-n 保留数字地址,-p 显示进程信息。容器环境里如果看不到进程名,通常是权限或网络命名空间不同,不代表端口没被占用;这时还得在对应容器或命名空间里查。

补充一个容易漏掉的点:如果启动的是 UDP 服务,查询时要把 -t 换成 -u,比如 ss -lunp 'sport = :8080'。另外容器里宿主机看到的是另一层 network namespace,进容器后再跑一次 ss,通常更容易对上实际进程。

还有个 IPv6 的坑:如果输出里看到 :::8080,它有时会同时接收 IPv4 连接,是否占用 0.0.0.0:8080 取决于系统的 bindv6only 和程序设置。遇到“看着没占用但启动失败”,可以再跑 ss -ltnp4 'sport = :8080' 和 ss -ltnp6 'sport = :8080' 分开确认。

隔壁空白Lv1#2

还有个 IPv6 的坑:如果输出里看到 :::8080,它有时会同时接收 IPv4 连接,是否占用 0.0.0.0:8080 取决于系统的 bindv6only 和程序设置。遇到“看着没占用但启动失败”,可以再跑 ss -ltnp4 'sport = :8080' 和 ss -ltnp6 'sport = :8080' 分开确认。

还有一种情况是 systemd 的 socket activation:端口确实被占着,但监听者可能是对应的 .socket 单元,服务进程还没启动。看到这类情况可以先查 systemctl status your-app.socket 和 systemctl cat your-app.socket,别直接把监听进程杀掉;确认要停服务时按单元关系处理更稳。