Processes and jobs
pstree
Display running processes as a tree, showing which process started which.
pstree [OPTION...] [PID | USER]
pstree draws the parent/child relationships that ps shows only as a PPID column. With no
argument it starts at PID 1 (on a normal system, systemd or init) and shows everything below
it; give a PID to see one subtree, or a user name to see the trees of that user's processes.
It answers questions like "what started this process?", "what will die if I kill this
service?" and "why does this container have forty workers?".
To keep the picture small, identical sibling subtrees are merged: 4*[nginx] means four
nginx children with no children of their own, and threads appear in braces, {python3}. Add
-p for PIDs (which also turns the merging off, since each PID is different), -a for command
lines, -s to show the ancestors of a PID, and -u to mark where the user changes.
In this sandbox, PID 1 is the runner, a python3 process, with sshd and the bash -c shell of
each example below it, so the trees are small. On a real machine pstree -p | less is the way
to read the whole thing.
Examples
Show the whole process tree
(sleep 300 & sleep 301 & wait) &
sleep 0.2
pstree
kill %1
python3-+-bash-+-bash---2*[sleep]
| `-pstree
|-sshd
`-2*[{python3}] PID 1 is the root, here the sandbox's runner. Below it are sshd and the example's shell,
whose children are pstree itself and the subshell. 2*[sleep] merges the subshell's two
identical sleep children, and 2*[{python3}] stands for two threads of the runner.
Show PIDs
(sleep 300 & sleep 301 & wait) &
sleep 0.2
pstree -p
kill %1
python3(1)-+-bash(1929)-+-bash(1930)-+-sleep(1932)
| | `-sleep(1933)
| `-pstree(1934)
|-sshd(8)
|-{python3}(9)
`-{python3}(10) -p puts each PID in parentheses and stops merging identical subtrees, so both sleep
processes get their own line. Thread IDs appear in braces.
Show the tree under one process
(sleep 300 & sleep 301 & wait) &
sleep 0.2
pstree -p $$
kill %1
bash(1935)-+-bash(1936)-+-sleep(1938)
| `-sleep(1939)
`-pstree(1940) Giving a PID limits the tree to that process and its descendants; $$ is the current shell,
so this shows what the example started.
Show command lines
sleep 300 &
python3 -c 'import time; time.sleep(300)' &
sleep 0.2
pstree -a $$
kill %1 %2
bash -c... |-pstree -a 1941 |-python3 -c import time; time.sleep(300) `-sleep 300
-a adds each process's arguments. Long command lines, like the shell's own, are cut short
with ...; -l stops the truncation.
Find out what started a process
(sleep 300 & wait) &
sleep 0.2
pstree -s -p "$(pgrep -n -x sleep)"
kill %1
python3(1)---bash(1946)---bash(1947)---sleep(1949)
-s prints the chain of parents above the given PID, all the way to PID 1. On a server this
answers "which service or login session does this process belong to?".
Show or hide threads
python3 -c 'import threading, time
for _ in range(2): threading.Thread(target=time.sleep, args=(30,)).start()' &
sleep 0.3
pstree -p $!
pstree -p -T $!
python3(1953)-+-{python3}(1955)
`-{python3}(1956)
python3(1953) Threads are listed in braces with their thread IDs. -T hides them, which makes busy
servers with hundreds of threads readable.
Show where the user changes
sleep 300 &
pstree -u
kill %1
python3-+-bash(dev)-+-pstree
| `-sleep
|-sshd
`-2*[{python3}] -u adds the user name in parentheses wherever a process runs as a different user from its
parent: here the root-owned runner starts the bash that runs as dev. Useful for spotting
privilege drops (or unexpected privilege) in daemons.
Show only one user's process trees
(sleep 300 & wait) &
sleep 0.2
pstree dev
kill %1
bash-+-bash---sleep
`-pstree A user name instead of a PID shows the trees rooted at that user's top-level processes, leaving out everything above them.
Sort children by PID
sleep 300 &
sleep 0.1
pstree -n -p 1
kill %1
python3(1)-+-sshd(8)
|-{python3}(9)
|-{python3}(10)
`-bash(1966)-+-sleep(1967)
`-pstree(1969) By default siblings are sorted by name; -n sorts them by PID, which shows them in the order
they were started.
A PID that does not exist is not an error
pstree 99999
echo "exit status: $?"
exit status: 0
pstree prints nothing and still exits 0, so it cannot double as an existence test.
Use kill -0 PID or ps -p PID for that.
Common pitfalls
Reading
3*[worker]as one process. It is three identical children merged; add-p(or-c) to see each one.Expecting box-drawing characters in logs or pipes to look right.
pstreechooses line style by terminal and locale; force plain ASCII with-Awhen the output goes to a file or e-mail.Forgetting that orphans are re-parented. When a parent dies its children move under PID 1 (or a subreaper such as
systemd --user), so the tree no longer shows who originally started them.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
pstreeis from psmisc and is Linux-specific; macOS has nopstreeby default (Homebrew has a different implementation with different options). FreeBSD offers it as a port.ps -ef --forestorps axjfgive a similar view on Linux without psmisc.
Options worth knowing
A selection, described in our own words. For the full list, see pstree(1) or pstree --help.
| Option | What it does |
|---|---|
-p, --show-pids | Show PIDs; also stops merging identical subtrees. |
-a, --arguments | Show each process's command-line arguments. |
-l, --long | Do not truncate long lines. |
-s, --show-parents | Show the ancestors of the given PID. |
-u, --uid-changes | Show the user name where it differs from the parent's. |
-n, --numeric-sort | Sort siblings by PID instead of by name. |
-c, --compact-not | Do not merge identical subtrees. |
-g, --show-pgids | Show process group IDs. |
-T, --hide-threads | Hide threads, show processes only. |
-t, --thread-names | Show threads' own names instead of the process name. |
-h, --highlight-all | Highlight the current process and its ancestors. |
-H, --highlight-pid PID | Highlight PID and its ancestors. |
-A, --ascii | Draw the tree with plain ASCII characters. |
-U, --unicode | Draw the tree with Unicode line characters. |
-S, --ns-changes | Show where processes enter a different namespace. |
-V, --version | Print the version and exit. |
Related
psPrint a snapshot of running processes, with the columns, filters and sort order you choose.pgrepPrint the PIDs of processes whose name (or full command line) matches a pattern, with filters by user, parent and age.topShow a live, sorted view of processes and system load; batch mode prints snapshots for logs and scripts.killSend a signal to processes by PID or job number; by default TERM, which asks a process to exit.