Linux 端口被占用的排查方法

25次阅读

端口显示“Address already in use”却查不到进程,通常因权限不足、未监听本地地址、容器占用、iptables DNAT 规则或 systemd socket 激活所致;应优先用 sudo ss -tulnlp 排查,再检查 docker、防火墙及 systemd。

Linux 端口被占用的排查方法

netstat 查 端口 占用时显示“Address already in use”却找不到进程

这通常是因为 netstat 默认不显示监听在非本地地址(如 0.0.0.0 或具体 IP)的 socket,或没加权限查看其他用户进程。实际端口已被占用,但你没看到对应行。

正确做法是用 sudo 运行,并加上 -tuln 参数:

sudo netstat -tuln | grep :8080

其中:-t 查 TCP,-u 查 UDP,-l 只显示监听态,-n 用数字端口代替服务名。如果仍无输出,说明可能不是传统 socket 监听,比如被 dockersystemd 或内核模块占用了端口。

lsof -i : 端口号 返回空但端口确实无法绑定

lsof -i :8080 查不到进程,常见原因有三:

  • 目标进程以 root 权限运行,而你没用 sudo 执行 lsof
  • 端口被 iptablesnftables 的 DNAT/REDIRECT 规则“伪装”占用(比如 iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080),此时实际没有进程监听 80,但流量全被转走,lsof 不会显示
  • 容器或 pod 内部监听了该端口(如 Docker 容器映射了 -p 8080:8080),宿主机上 lsof 默认看不到容器网络命名空间里的监听

建议组合使用:

sudo lsof -iTCP:8080 -sTCP:LISTEN
sudo ss -tuln | grep :8080

ss 命令比 netstat 更快更可靠,但参数容易写错

ss 是现代 Linux 推荐替代 netstat 工具,底层直接读取内核 socket 表,速度快且信息更全。但它的过滤语法和 netstat 不同,新手常因参数漏掉关键标志而查不到。

查指定端口监听进程的正确写法是:

sudo ss -tulnlp | grep :8080

注意:-l(listening)、-p(show process,必须 root)、-n(numeric)、-t/-u(协议)。漏掉 -p 就看不到 PID 和程序名;漏掉 -l 则只显示已建立连接,不显示等待连接的监听端口。

如果提示 Permission denied,不是命令错了,是没加 sudo ——-p 需要 CAP_NET_ADMIN 或 root 权限。

Docker / Podman 容器导致端口“幽灵占用”

即使 sslsof 都没查到宿主机上的监听进程,端口仍不可用,大概率是容器在用。Docker 默认用 host 网络模式或端口映射(-p)时,会在宿主机上真实监听该端口。

快速确认方法:

  • 查所有容器端口映射:docker ps --format "table {{.ID}}t{{.Names}}t{{.Ports}}" | grep 8080
  • 查所有监听了该端口的容器:docker ps -q | xargs -r docker port | grep 8080
  • 若用 Podman:podman ps --format "{{.ID}} {{.PORTS}}" | grep 8080

特别注意:容器停止后,有时 docker-proxy 进程残留(尤其旧版 Docker),表现为 lsof -i :8080 显示一个 docker-proxy 进程,kill 它即可释放端口。

实际排查时,别只盯一个命令。先 sudo ss -tulnlp 快速扫一遍,没结果再看容器,再检查 iptables/nftables,最后怀疑是否是 systemd socket 激活(systemctl list-sockets | grep 8080)。端口冲突的根因往往藏在最不常想到的地方。

text=ZqhQzanResources