根据端口号查询进程 PID 与工作目录:netstat 加 pwdx 的组合用法
排查”这个端口到底是谁在占、程序装在哪”是运维的日常动作:告警里只有一个端口号,你得接着找出进程、找到部署目录,才能接着看日志。这篇给一个一步到位的小脚本:传入端口号,直接拿到 PID 和进程工作目录,并把管道里每一步拆开讲清楚。
实测环境:Rocky Linux 9 容器(net-tools 2.0、pwdx 来自 procps-ng)。CentOS 7/8 行为一致。
核心机制一句话
netstat -nlp 能列出每个监听端口对应的”PID/程序名”,pwdx 能把 PID 翻译成进程当前的工作目录——两步接力,端口就落到了磁盘上的目录。
脚本
1 |
|
用法:保存为 portpath.sh,chmod +x 后以端口号作为第一个参数执行。
实测
容器里用 python3 在 8000 端口起一个测试进程(工作目录 /tmp/webdemo),跑脚本看结果:

输出里的 PID 和路径直接对上了:170 号 python3 进程,工作目录 /tmp/webdemo。末尾的 echo -e 部分用 ANSI 颜色码把端口号和路径高亮,在终端里更醒目(图中为剥离颜色码后的纯文本)。
这条管道还能顺手变出别的取值:第 7 列按斜杠切开后取第二段,得到的就是程序名而不是 PID——netstat -nlp | grep :$1 | awk '{print $7}' | awk -F"/" '{print $2}',告警只给端口号时,先报一句”是 nginx 占着”往往比先报 PID 更有用。改列号还能取连接状态、监听地址,套路相同。
每一步在做什么
netstat -nlp | grep :$1:找出监听传入端口的那个监听项;awk '{print $7}':取第 7 列,内容形如”PID/程序名”;awk -F"/" '{ print $1 }':按斜杠切开后取第一段,留下纯 PID;pwdx $PID:查询该进程的当前工作目录,输出形如”PID: 路径”;awk -F ' ' '{print $2}':取 pwdx 输出的第二列,得到不带前缀的路径;- 最后的
echo -e用颜色把端口号和路径高亮出来。
这条管道的精髓在”文本即接口”:netstat 的每列输出都是下一个工具的输入,改列号就能取出程序名(第 7 列按斜杠取第二段)或者连接状态。
错误写法对比:grep 的子串陷阱
脚本里的 grep :$1 是子串匹配。查 :80 时,:8000、:8080 的监听项一样会命中,脚本可能给你完全不相干进程的路径。实测(容器里同时监听 80 和 8000):
1 | netstat -nlp | grep :80 | awk '{print $4}' |
输出同时包含 0.0.0.0:80 和 0.0.0.0:8000 两行,取到的 PID 就看哪行排前面了,结果不可靠。修正写法是让匹配锚定行尾:
1 | netstat -nlp | awk '$4 ~ /:80$/' |
本地地址列精确以 :80 结尾才命中,实测只剩 80 端口那一行。两组输出的对照见下图:

把脚本第一行的 grep 换成这个 awk,坑就填上了。
注意事项
grep :$1子串匹配的问题见上一节,生产脚本建议直接用锚定行尾的 awk 写法。awk -F ' ' '{print $2}'只取 pwdx 输出的第一段路径,进程工作目录含空格时结果会不完整,必要时用pwdx $PID | cut -d" " -f2-取整段。- netstat 的
-p要看到进程信息需要足够权限,建议以 root 执行;普通用户跑会看到监听项但没有 PID。 - 新系统上 netstat 属于 net-tools 包(已停止维护),ss 命令是替代品:
ss -nlp | awk '$4 ~ /:80$/'语义完全一致,且不用额外安装。
注:ss 的查询走内核 netlink diag 通道,本次实测的 Docker Desktop 容器内核不支持,
ss -nlp报RTNETLINK answers: Invalid argument;物理机和云主机上正常,用法以 ss(8) 为准。
小结
从告警里的一个端口号,到磁盘上的部署目录,中间只隔着一条管道:netstat 找 PID,pwdx 找目录。用脚本把这个动作固化下来,下次端口告警就不用再手忙脚乱地敲四五行命令了。
本文由作者 2020-2024 年间的 CSDN 博客文章重构而来,原发布于 CSDN。