无法通过awk从fuser输出提取端口占用PID的技术求助
解决fuser提取端口占用PID失败的问题
最近我遇到个小麻烦:想提取占用9092/tcp端口的进程ID,用fuser直接查能得到正确结果:
$ fuser 9092/tcp 9092/tcp: 5920
但想用awk分割冒号提取PID时,结果却不对:
$ fuser 9092/tcp | awk -F: '{print $2}' 9092/tcp:
本来想把提取到的PID用来执行ls -l /proc/<PID>/exe,写成了:
ls -l /proc/$(fuser 9092/tcp | awk -F: '{print $2}')/exe
结果自然没法正常运行。
我的环境工具版本:
- bash:GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
- fuser:fuser (PSmisc) 22.20
问题根源
其实是PSmisc版本的fuser输出流向搞的鬼:它默认把带端口号的提示文本输出到标准错误(stderr),而真正的PID是输出到标准输出(stdout)。所以当你用管道给awk时,awk读到的是空内容(或者如果你的环境里输出流向不同,那就是分隔符没选对)。
几种解决方案
方案1:直接捕获fuser的标准输出(最简洁)
把stderr的提示信息重定向到/dev/null,直接拿到PID:
PID=$(fuser 9092/tcp 2>/dev/null) ls -l /proc/$PID/exe
或者写成一行:
ls -l /proc/$(fuser 9092/tcp 2>/dev/null)/exe
方案2:调整awk的分隔符(针对输出整行到stdout的情况)
如果你的fuser确实把9092/tcp: 5920整行输出到stdout,那可以把分隔符设为冒号加空格,或者直接按空格分割:
按: 分割:
ls -l /proc/$(fuser 9092/tcp | awk -F': ' '{print $2}')/exe
按空格分割(更简单):
ls -l /proc/$(fuser 9092/tcp | awk '{print $2}')/exe
方案3:换用lsof(更直观的工具)
如果觉得fuser的逻辑太绕,用lsof来提取PID会更直接:
ls -l /proc/$(lsof -i :9092 -t)/exe
-i :9092指定查找9092端口的进程,-t选项让lsof只输出PID,省心不少。
内容的提问来源于stack exchange,提问作者Ibrahim Quraish




