Home / Alt manpages / proc_pid_cwd(5)

  • proc_pid_cwd(5)
  • File format
  • linux

Trace a Process's Working Directory with /proc/PID/cwd

You will inspect the current working directory of a running Linux process using /proc/PID/cwd, then verify the resolved path without changing the process. Allow about ten minutes. You need a shell and a process ID; elevated privileges are not normally needed for your own processes.

This guide follows the installed Linux man-pages 6.7 package. The proc_pid_cwd(5) entry describes /proc/PID/cwd as a symbolic link to the process's current working directory. It is a live view of process state, not a setting that you edit.

1. Check the interface and your own directory

Start with the shell that is running your commands. $$ expands to that shell's process ID, and readlink prints the target of the procfs link:

$ printf 'shell PID: %s\n' "$$"
shell PID: 3907400
$ readlink "/proc/$$/cwd"
/home/alex/project

The PID in the output is an example and will differ on your machine. The path should match the directory in which that shell is running. Compare it with a physical-path resolution when symlinks may be involved:

$ readlink -f "/proc/$$/cwd"
/home/alex/project
$ pwd -P
/home/alex/project

Checkpoint: you have confirmed that procfs is mounted and that a process can expose its own working directory.

2. Choose a target process

For a process that belongs to you, obtain its PID from the command that started it, a service status command, or a process listing. Avoid guessing from a partial name when several instances exist. This example starts a harmless, short-lived process in a temporary directory so the target is unambiguous:

$ probe_dir=$(mktemp -d /tmp/proc-cwd-check.XXXXXX)
$ (cd "$probe_dir" && exec sleep 60) &
[1] 3907400
$ probe_pid=$!
$ printf 'target PID: %s\n' "$probe_pid"
target PID: 3907400

The command substitution creates a temporary directory, and the child changes into it before running sleep. The trailing & puts that child in the background; $! records its PID. This changes only a temporary process and directory in your own account.

Check that the process still exists before reading procfs:

$ kill -0 "$probe_pid" && echo 'process is running'
process is running

If this check fails, the process has already exited and its /proc/PID directory has disappeared. Start a new target rather than reusing the old PID.

Use readlink for the direct target and readlink -f when you want the canonical path:

$ readlink "/proc/$probe_pid/cwd"
/tmp/proc-cwd-check.k7L2mQ
$ readlink -f "/proc/$probe_pid/cwd"
/tmp/proc-cwd-check.k7L2mQ

The random suffix is expected because mktemp created it. If the process is using a directory reached through a symbolic link, the first command can preserve that spelling while readlink -f resolves existing path components. A later directory rename or process exit can also make a previously observed path stale, so treat the result as a point-in-time observation.

You can use the link as a directory path, but do not silently turn an inspection into a write. For example, list its contents without changing anything:

$ ls -la "/proc/$probe_pid/cwd"
total 8
drwx------ 2 alex alex 4096 Sep 26 12:00 .
drwxrwxrwt 1 root root 4096 Sep 26 12:00 ..

Directory contents and ownership vary. If you only need the path, stop after readlink.

4. Understand permission failures

The manpage says that dereferencing or reading this symbolic link is controlled by a ptrace access check using PTRACE_MODE_READ_FSCREDS. In practice, a process owned by another account, a protected service, or a process in a different security context may reject the read even when its PID is visible.

$ readlink "/proc/OTHER_PID/cwd"
readlink: /proc/OTHER_PID/cwd: Permission denied

The exact diagnostic is supplied by your system. Do not treat sudo as a universal fix: using elevated privileges may expose a sensitive service's path, and a container, namespace, LSM policy or procfs configuration can still affect what is visible. If you administer the host and have a legitimate need, follow its access policy and record why the path was inspected. Ordinary observation of your own process does not require root.

Also check the process state. A missing /proc/PID usually means the process exited, while a permission error means the procfs entry exists but the access check failed:

$ test -e "/proc/$probe_pid/cwd" && echo 'proc entry exists'
proc entry exists

5. Account for multithreaded processes

For a multithreaded process, the manpage records a specific edge case: the link contents are unavailable if the main thread has already terminated, commonly after pthread_exit(3). A failure in that state does not mean that every thread has stopped or that the application has no working directory. It means the documented /proc/PID/cwd view is unavailable for that process state.

When the path matters to a service, capture the PID and result while the service is healthy, and compare the path with the service's configured working directory. Do not restart a production service merely to make this diagnostic work. A restart is service-disrupting and needs an approved maintenance procedure.

6. Clean up the test process

End the temporary process and remove the temporary directory only after the checks are complete:

$ kill "$probe_pid"
$ wait "$probe_pid" 2>/dev/null || true
$ rmdir "$probe_dir"
$ test ! -e "$probe_dir" && echo 'temporary test directory removed'
temporary test directory removed

This cleanup is safe for the directory created by the example. Do not substitute a path copied from a service or another user's process, and do not use a recursive removal command for this test. If rmdir reports that the directory is not empty, inspect it first; something else may have created a file there.

Done means

  • You read /proc/PID/cwd with a verified PID.
  • You used readlink -f when a canonical path was required.
  • You distinguished a vanished process from a permission or ptrace access failure.
  • You treated the result as live process state, not persistent configuration.
  • You left the target process and its working directory unchanged, apart from cleaning up the temporary test process.