一个容器内进程的 cwd 诊断记录
八月 05, 2026 [Linux 与系统] #Linux #docker #调试一个容器内进程的 cwd 诊断记录
问题现象
在一台远程服务器上排查一个 Java 服务(portal.jar),执行:
ssh smyl@192.168.7.16 "ps -ef | grep portal.jar"
得到进程 PID 后,查看它的启动目录:
sudo ls -l /proc/2333607/cwd
结果显示 symlink 指向 /(根目录)。但是 ls / 里根本没有 portal.jar,文件去哪了?
排查过程
1. 先看完整的启动命令行
cat /proc/2333607/cmdline | tr '\0' ' '
输出:
java -agentlib:jdwp=... -jar portal.jar --spring.datasource.url=...
注意这里用的是相对路径 -jar portal.jar,没有带目录。也就是说,jar 的路径在启动命令行里,和 cwd 是两回事——/proc/PID/cwd 只是进程的 OS 层工作目录(chdir 状态),不等于 jar 文件所在位置。
2. 看父进程,这是关键一步
ps -fp 2333588 # 父进程
输出:
root 2333588 1 ... /usr/bin/containerd-shim-runc-v2 -namespace moby \
-id b1361c5698864840338b2753403884cff27c8189a6c7bc4a88fabb83f1706805 \
-address /var/run/docker/containerd/containerd.sock
看到父进程是 containerd-shim-runc-v2 就基本可以断定:这个进程跑在 Docker 容器里。
几个识别特征:
containerd-shim-runc-v2:Docker 为每个容器创建的 shim 进程,是容器内 PID 1 的宿主侧父进程-namespace moby:Docker 的 containerd 命名空间-address /var/run/docker/containerd/containerd.sock:Docker 的 containerd socket-id <64位hex>:就是容器 ID
3. docker inspect 交叉验证
docker inspect b1361c56... --format '{{json .Config.WorkingDir}} {{json .Path}} {{json .Args}}'
输出:
"/" "java" ["...","-jar","portal.jar","--spring.datasource.url=..."]
容器 Config.WorkingDir 是 /,命令是 java ... -jar portal.jar,与 cmdline 完全吻合。同时拿到容器名 xfuzz-saas-test-server-1、镜像 wfuzz-web:v1.12.27.1。
4. 进容器确认
docker exec <容器ID> ls -l /portal.jar
容器里 /portal.jar 确实存在(396MB);而宿主机 ls / 里没有。真相大白:
cwd 显示的 / 是容器内的根目录(overlay 文件系统),不是宿主机的根目录。 两者是两个不同的文件系统,我在宿主机的 / 里找容器里的文件,当然找不到。
原理小结
/proc/PID/cwd:进程的工作目录,是 OS 层 chdir 状态,和可执行文件/jar 在哪没有必然关系;jar 的真实路径要看/proc/PID/cmdline里的启动参数(可能有相对路径 + 其他情况)- 容器进程的文件系统:Docker 容器根目录是 overlay2 挂载的镜像层,与宿主根目录隔离。宿主上
ls -l /proc/PID/cwd显示的路径是容器命名空间内的路径 - 容器进程判定:
ps -ef时看 PPID,父进程是containerd-shim-runc-v2(Docker)或containerd-shim(containerd)即为容器内进程;容器内根目录还有.dockerenv标记文件
后续:下载文件的排查
这个服务还提供 wfuzz 程序下载功能,最初也没找到 wfuzz 文件。排查结果:
- 可下载的文件不在
portal.jar里。jar 内搜到的wfuzz全是 Java 包名/类名(com.wfuzz.saas.portal.*),不是二进制 - 下载源在容器磁盘上:配置文件
application-platform.yml里写了repo: /dist/repo、install: /dist/install、assetDir: /repo/dist/asset - 实际文件在
/repo/dist/out/wfuzz-Linux-x86_64、/repo/dist/repo/wfuzz-2.4.20-Linux-x86_64.tar.xz等
找不到的另一个原因是文件名带了架构后缀:wfuzz-Linux-x86_64、wfuzz-2.4.20-Linux-x86_64.tar.xz,用 ls 或 find -name "wfuzz" 精确匹配会漏掉,要写成:
find / -iname "*wfuzz*"
经验总结
- 排查进程问题先看三件套:
cmdline(启动参数)、cwd、exe,再看 PPID(父进程是谁往往直接给出答案) - 看到
containerd-shim-runc-v2立刻意识到是容器场景,接下来一切都要到容器内文件系统里找 - cwd 指向的
/不等于可执行文件所在目录;文件位置看 cmdline,文件系统边界看父进程 - 文件搜索用通配符(
*wfuzz*),别被带后缀的文件名骗了