最可靠方式是执行readlink -f /proc/<PID>/exe获取进程绝对路径,因ps仅显示命令名、which/whereis依赖当前环境且不覆盖虚拟环境或自定义路径;辅以/proc/<PID>/cmdline和/proc/<PID>/cwd可完整还原运行上下文。

怎么直接拿到进程的绝对可执行路径
最可靠的方式是读 /proc/<pid>/exe</pid>,不是靠 ps 或 which 猜。因为 ps 只显示命令名(比如 python),而实际可能是 /home/user/.pyenv/versions/3.11.9/bin/python;which python 查的是当前 shell 的 $PATH,跟进程无关。
- 先用
pgrep -f your_keyword或ps -ef | grep your_keyword拿到 PID - 再运行
readlink -f /proc/<pid>/exe</pid>—— 一行命令直接输出解析后的绝对路径 - 如果看到输出末尾带
(deleted),说明二进制文件已被删,但进程还在跑,路径仍有效 -
ls -l /proc/<pid>/exe</pid>也能看,但要自己解析箭头右边的内容,不如readlink -f直接
为什么只看 exe 不够,还得查 cmdline 和 cwd
知道程序本体在哪,不等于知道它在跑什么、从哪启动、依赖哪些配置。这三个字段必须一起看:
-
cat /proc/<pid>/cmdline | tr '\0' ' '</pid>:还原完整启动命令,比如/usr/bin/node /var/www/app/server.js --port=3000 -
readlink -f /proc/<pid>/cwd</pid>:确认当前工作目录,影响相对路径加载(如 config.json 是否能被找到) -
pwdx <pid></pid>是个快捷替代,但不支持僵尸进程,且某些内核版本对特权进程返回空 - 注意:
/proc/<pid>/cmdline</pid>对僵尸进程为空;/proc/<pid>/cwd</pid>对 init 或容器 init 进程可能不可读
用 fuser -v 快速反查路径归属哪个进程
当你只知道一个路径(比如 /var/log/nginx/access.log)被谁占着,想反推是哪个进程在写,fuser -v 比先找 PID 再查 /proc 更快:
- 普通用户运行
fuser -v /path只能看到自己的进程;必须加sudo fuser -v /path才能看见系统级进程(如rsyslog、nginx) - ACCESS 列里的
txt表示该进程正以可执行方式运行这个文件;cwd表示这是它的当前工作目录;mem表示 mmap 了该文件 - 查挂载点(如
/mnt/data)时,建议加-m参数:sudo fuser -v -m /mnt/data,避免漏掉子目录下的访问进程 - 如果输出里出现
kernel作为 PID,说明是内核级操作(如 ext4 journal 写入),不能 kill,得从上层服务入手
别踩这些坑:常见误判和权限陷阱
很多“查不到路径”的问题,其实不是命令不会用,而是权限或场景理解错了:
-
lsof -p <pid></pid>能列打开的文件,但它不保证显示exe路径——尤其对 setuid 进程或容器内进程,lsof可能权限不足或信息受限 -
ps -f -p <pid></pid>显示的CMD字段会被截断,且不包含绝对路径;ps e -p <pid></pid>虽能看环境变量,但PWD不一定等于cwd - 容器内进程的
/proc/<pid>/exe</pid>指向的是容器镜像里的路径(如/usr/local/bin/python),宿主机上不存在对应文件,别拿宿主机的which去比对 -
hidepid=2(常见于某些安全加固系统)会让非 root 用户看不到其他用户的/proc/<pid></pid>目录,此时readlink会报No such file or directory,不是路径错,是权限挡住了
readlink -f /proc/<pid>/exe</pid> + cat /proc/<pid>/cmdline</pid> + readlink -f /proc/<pid>/cwd</pid> 这三行命令缺一不可。任何只依赖单一工具或只查某一层信息的做法,都容易在多 Python 版本、虚拟环境、容器或 systemd 服务场景下翻车。


















