优先用 sudo lsof -i :端口号,因其一次性输出command/pid/user/type/name等完整字段,权限可控、兼容性好,且天然适配linux“一切皆文件”模型;ss和netstat已逐步弃用。

直接上结论:优先用 sudo lsof -i :端口号,不是 netstat 也不是 ss —— 它一次输出 COMMAND/PID/USER/TYPE/NAME,字段直给、权限可控、兼容性好,省去二次过滤和猜进程名的麻烦。
为什么 lsof -i :端口号 是首选
Linux 把网络连接当“打开的文件”处理,lsof 天然适配这套模型。执行 sudo lsof -i :3000 后,你能立刻看到:
-
COMMAND:比如node、java、docker-proxy,不是一堆数字或- -
PID:第二列就是进程 ID,不用再从字符串里awk提取 -
USER:明确是谁启动的,避免误杀系统服务 -
NAME字段含*:3000 (LISTEN),状态一目了然
而 ss -tulnp 在非 root 下常显示空 Process 字段;netstat 在 Ubuntu 22.04+、CentOS 8+ 默认不预装,还得额外装 net-tools。
lsof 不加 sudo 会漏掉进程
普通用户权限只能看到自己启动的进程。常见错误现象:
- 执行
lsof -i :8080却看不到 PID,或只看到部分结果 - 明明
nginx或dockerd在监听,但输出为空
这是因为 root 或其他用户的监听行为被权限拦截了。必须加 sudo 才能完整覆盖:
sudo lsof -i :8080
如果提示 command not found,说明未安装:sudo apt install lsof(Debian/Ubuntu)或 sudo yum install lsof(RHEL/CentOS)。
加 -P -n 避免卡顿和干扰
默认情况下,lsof 会尝试反向解析 IP 和端口名(比如把 :3000 变成 :http-alt),既慢又容易因 DNS 延迟阻塞输出。建议固定带上:
-
-P:端口号保持数字形式,不查/etc/services -
-n:IP 地址不查 DNS,避免超时
所以稳定写法是:
sudo lsof -i :3000 -P -n
若你只想看 TCP LISTEN 状态(排除 ESTABLISHED 连接干扰),可加限定:
sudo lsof -iTCP -sTCP:LISTEN -P -n -i :3000
看到 docker-proxy 或 containerd 别急着 kill
lsof 输出里 COMMAND 是 docker-proxy?那大概率是容器映射的端口,不是宿主机原生进程:
- 对应
PID杀了也没用,docker-proxy会自动重启 - 真正要查的是容器内进程:先
docker ps --format "table {{.ID}}\t{{.Ports}}" | grep 3000找容器 ID,再docker exec -it [CONTAINER_ID] ps aux | grep your-app - 同一端口被多个子进程共用也很常见(如 Node.js cluster 模式),
PID只是主进程,别只 kill 主进程就以为完事了
拿到 PID 后,先用 ps -p PID -o pid,ppid,cmd,%mem,%cpu 确认命令行和父进程;真要终止,优先 kill -15 PID(SIGTERM),等几秒没反应再 kill -9。
实际操作中,最易被忽略的是:IPv6 双栈监听导致误判。比如 lsof 显示 TYPE 是 IPv6,但你在 curl 时用的是 IPv4 地址,仍可能连通——因为内核做了透明映射。此时别急着删规则,先确认是否真是冲突,而不是双栈正常行为。











