Inspect a Process from Its Linux Namespaces with nsenter
You will finish with a safe way to open a shell or run one command using the namespaces of an existing process. That is useful when a service is in a container or a separate network namespace and ordinary host commands show the wrong view. The local manpage is from util-linux 2.39.3, installed here as package version 2.39.3-9ubuntu6.6. This shell also has a Homebrew nsenter 2.41.3 earlier in $PATH, so check which binary your commands use.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a Linux shell, procfs mounted at /proc, and a target process that you are allowed to inspect. Most examples are read-only, but entering another process's namespaces is security-sensitive: do not run commands that mount, unmount, change a hostname, alter firewall rules or modify files until you understand the namespace and have a recovery path.
1. Check the installed command
Start by confirming the binary and its version. These are ordinary, read-only commands and do not need elevated privileges:
$ command -v nsenter
/home/linuxbrew/.linuxbrew/bin/nsenter
$ nsenter --version
nsenter from util-linux 2.41.3
$ /usr/bin/nsenter --version
nsenter from util-linux 2.39.3
The command takes namespace options followed by a program and its arguments. If no program is supplied, it starts the shell named by $SHELL, or /bin/sh by default. Supplying an explicit command is easier to review and less likely to leave an interactive shell in the wrong context. Use /usr/bin/nsenter in the examples if you need the binary that matches the local 2.39.3 manpage; otherwise substitute the path reported by command -v.
Checkpoint
Record the version and binary path before copying an example. Option details can differ between package versions.
2. Choose and inspect a target process
Pick a process whose namespace view you need to examine. For a harmless first test, use the current shell as the target. The shell's PID is available as $$:
$ TARGET_PID=$$
$ printf 'target PID: %s\n' "$TARGET_PID"
target PID: 27184
Your number will differ. To inspect another process, replace 27184 with its numeric PID after checking it with a command such as ps -p 27184 -o pid,comm,args. Access to another user's process or its namespace files may require elevated privileges. Use sudo only when your account is authorised and the target is one you intend to inspect.
The namespace handles are exposed under /proc/PID/ns/. List them without entering anything:
$ ls -l /proc/"$TARGET_PID"/ns/{mnt,uts,ipc,net,pid,user,cgroup,time}
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/ipc -> ipc:[4026531839]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/mnt -> mnt:[4026531841]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/net -> net:[4026531840]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/pid -> pid:[4026531836]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/time -> time:[4026531834]
lrwxrwxrwx 1 user user 0 ... /proc/27184/ns/user -> user:[4026531837]
The inode numbers are host-specific. The listing confirms that the proc entries exist; it does not grant permission to enter them.
3. Run one command in the target's network namespace
Use --target with --net, then give nsenter an explicit program. This asks readlink to print the network namespace link from inside the entered context:
$ nsenter --target "$TARGET_PID" --net -- readlink /proc/self/ns/net
net:[4026531840]
Compare it with the target's link:
$ readlink /proc/"$TARGET_PID"/ns/net
net:[4026531840]
The values should match. With a real container or service PID, the network namespace may instead contain different interfaces and routes. This command does not change the target process. It changes the namespace context of the short-lived readlink process and then exits.
If you see Operation not permitted, check the target PID, your permissions and the kernel's namespace restrictions before trying sudo. Do not treat elevated privileges as a substitute for selecting the correct process.
Some hosts, including restricted containers, deny even a same-namespace reassociation. In that case nsenter may print reassociate to namespaces failed: Operation not permitted; that is an execution-environment limit, not evidence that the namespace link is wrong. Repeat the check on the host that owns the target process.
4. Inspect several namespaces at once
Use --all when you deliberately want all applicable namespaces of the target. The following command prints identity and namespace links without changing system state:
$ nsenter --target "$TARGET_PID" --all -- /bin/sh -c 'printf "pid=%s uid=%s\n" "$$" "$(id -u)"; readlink /proc/self/ns/{mnt,uts,ipc,net,pid,user,cgroup,time}'
pid=27185 uid=1000
mnt:[4026531841]
uts:[4026531838]
ipc:[4026531839]
net:[4026531840]
pid:[4026531836]
user:[4026531837]
cgroup:[4026531835]
time:[4026531834]
Output order and identifiers vary. The user namespace is ignored when it is already the caller's current user namespace. By default, nsenter sets UID and GID to 0 when entering a user namespace, so do not assume that an entered shell has the same credentials as your original shell.
5. Understand PID namespace forking
When changing the PID namespace, nsenter forks by default before executing the program. That lets the new program and its children share the entered PID namespace. A shell started with --pid therefore has a process view that can differ from the shell which launched nsenter.
For a read-only comparison, print the PID list:
$ nsenter --target "$TARGET_PID" --pid -- /bin/sh -c 'printf "inside PID namespace: %s\n" "$$"; ps -e -o pid,comm'
inside PID namespace: 1
PID COMMAND
1 sh
2 ps
The exact list depends on the target. --no-fork suppresses nsenter's PID namespace fork, but it changes the process semantics and is not a general fix for a confusing result. Leave it out unless the program specifically requires exec without that fork.
6. Use a target root or working directory carefully
--root can use the target's root directory and --wd can use its working directory. These options affect where path lookups occur, but they do not make a process safe or reproduce every property of a container. Test with a harmless command first:
$ nsenter --target "$TARGET_PID" --root -- /bin/pwd
/
The target root must contain the requested program. If it does not, nsenter can fail with a file-not-found error even though the command exists on the host. The specified directory for --root or --wd is opened before the namespace switch. --wdns opens the working directory afterwards, and it cannot be combined with --wd.
Safety boundary
Do not combine these options with shell commands that write files until you have checked the path with pwd and readlink -f. A relative path can refer to a different filesystem after the switch. If you accidentally start an interactive shell, type exit; no persistent change is undone by exiting, so review any command that already ran.
7. Diagnose the common failures
A disappearing target can produce an error even when the original PID was valid. Processes exit and PIDs can be reused, so repeat the ps and namespace-link checks immediately before a sensitive inspection.
Check the option spelling and target relationship with the local help text:
$ nsenter --help | sed -n '1,35p'
$ nsenter --target "$TARGET_PID" --net -- /bin/true
$ printf 'exit status: %s\n' "$?"
exit status: 0
A zero status means the requested program returned zero. It does not prove that you inspected the namespace you intended. Record the target PID, compare /proc/PID/ns/* with /proc/self/ns/*, and keep the command explicit.
Done means
- You confirmed the installed nsenter version and read its local option contract.
- You selected a live target PID and checked its namespace links.
- You ran an explicit, read-only command in the required namespace.
- You understand that
--all, user namespaces and PID namespace forking can change credentials or process visibility. - You checked the working directory or root before running anything that writes, mounts or changes network state.