pstree takes the flat, scrolling mess that ps gives you and turns it into an actual tree, showing which process spawned which. Instead of hunting through PIDs and PPIDs by hand, you see the parent-child chain laid out in front of you.
LinuxTeck
I first reached for pstree years ago while trying to figure out why a cron job kept spawning zombie children on a Rocky Linux box, and ps aux just wasn't giving me the relationship between them fast enough. Once you get comfortable with the flags below, you will start using pstree before ps for anything involving parent-child confusion.
How to Install pstree in Linux
pstree ships as part of the psmisc package, which is already installed on most desktop distros. If it's missing on a minimal server image, grab it with your package manager below.
LinuxTeck
linuxteck@rocky:~$ sudo dnf install psmisc
linuxteck@arch:~$ sudo pacman -S psmisc
Building dependency tree... Done
psmisc is already the newest version (23.7-1).
0 upgraded, 0 newly installed, 0 to remove.
1. Display the Full Process Tree with the pstree Command
Run pstree with no arguments and it walks every process on the system starting from init or systemd and prints them as a tree, using square brackets to collapse repeated identical branches like threads.
LinuxTeck
├─containerd───11*[{containerd}]
├─cron
├─dbus-daemon
├─networkd-dispatcher───2*[{networkd-dispat}]
├─nginx───2*[nginx]
├─sshd───sshd───bash───pstree
└─systemd-journald
Square brackets and curly braces mean two different things here. Square brackets like 2*[agetty] mark identical sibling processes that pstree compacted into one line with a repeat count. Curly braces like {containerd} mark threads belonging to that process rather than separate processes, so 11*[{containerd}] reads as eleven identical threads under containerd, not eleven child processes.
2. Show Command-Line Arguments with -a
By default pstree hides the flags a process was started with. Add -a when you need to see exactly how something was invoked, which is handy when you're chasing down which script launched a runaway process.
LinuxTeck
├─cron -f
├─nginx -g daemon on; master_process on;
│ └─nginx -g daemon on; master_process on;
└─sshd -D
└─sshd
└─bash
└─pstree -a
Notice the tree loses the compaction brackets once -a is active, since each process now needs its own line to show its arguments.
3. Display PIDs Next to Each Process with -p
Add -p to print the process ID after every name in parentheses. This is the flag I reach for most, since it lets you jump straight from a visual tree to a ps or kill command without a second lookup.
LinuxTeck
├─nginx(1190)───nginx(1191)
└─sshd(2201)───sshd(2340)───bash(2341)───pstree(2410)
4. Expand Identical Subtrees with -c
pstree merges identical branches by default to save space. If you actually want to see every worker process listed on its own line instead of collapsed into a count, pass -c to turn that compaction off. Just note that combining -c with -p is redundant, since -p already forces every process onto its own line by disabling compaction on its own.
LinuxTeck
├─nginx
├─nginx
└─nginx
Compare that against the collapsed 4*[nginx] style output from example 1. If you also need the PIDs for each worker, use -p on its own instead of stacking it with -c.
5. Sort Child Processes by PID with -n
pstree normally sorts siblings alphabetically by process name. When you're trying to see the order processes were actually spawned in, -n sorts them numerically by PID instead.
LinuxTeck
├─cron(842)
├─nginx(1190)
└─sshd(2201)
6. Show Which User Owns Each Process with -u
Add -u and pstree prints the username in parentheses every time ownership changes down the tree, which makes it obvious when a process is running under a different account than its parent, like a web server dropping from root to www-data.
LinuxTeck
└─sshd───sshd(linuxteck)───bash
Production Tip:
On a shared server, running pstree -u is a fast way to spot a process running under the wrong account before it becomes a permissions incident. If you're hosting on a managed platform, this kind of privilege drop is usually handled for you already, which is one of the reasons people move sites to managed stacks like the one covered in this Kinsta review instead of self-managing every worker process.
7. Highlight the Current Process and Its Ancestors with -h
When you run pstree from inside a deep terminal session, it can be hard to spot yourself in a wall of text. The -h flag highlights your current shell and every process above it back to init, assuming your terminal supports highlighting.
LinuxTeck
(bash and pstree appear highlighted in your terminal)
Concept:
-h relies on your terminal's ANSI escape support to actually draw the highlight. Run it over SSH into a dumb terminal, inside a script, or redirect the output to a file, and pstree silently falls back to plain text with no visible highlighting at all. It's not broken, there's just nothing for it to highlight with.
8. View the Process Tree for a Specific User
pstree accepts a username as its argument and shows only the branches rooted at processes owned by that account, which beats scrolling through a full system tree on a box with dozens of logged-in users.
LinuxTeck
└─vim
9. View the Process Tree Rooted at a Specific PID
Pass a PID instead of a username and pstree treats it as the root of the tree, showing only that process and everything spawned underneath it. This is useful once you already know the PID from top or htop and just want to see its children.
LinuxTeck
├─nginx
└─nginx
10. Trace Parent Processes of a PID with -s
Sometimes you need to go the other direction and see what launched a process rather than what it launched. The -s flag shows the full chain of parents leading up to the given PID.
LinuxTeck
Reading upward like this is often faster than piecing the chain together manually from a raw ps -ef dump, especially in the process management cheat sheet workflow.
11. Passing More Than One PID or Username to pstree
People coming from ps often try to hand pstree a list of targets at once, expecting it to print a tree for each. pstree's own syntax only ever documents a single trailing pid or user slot, not a list, and that has held true across every released version of the tool. Depending on your version, a second target is either ignored or rejected with a usage error, it is not a supported way to get multiple trees.
LinuxTeck
└─nginx
(the second argument, 2341, is not used)
Common Mistake:
pstree only accepts one PID or username as its trailing argument. If you need to check on two or three services at once, run pstree once per target instead of stacking arguments on a single line.
LinuxTeck
└─nginx
systemd───sshd───sshd───bash(2341)
Separating the two commands with a semicolon runs them back to back regardless of whether the first one succeeds, which is what you actually want when you are just glancing at two unrelated trees.
12. Trace a Zombie Child Back to the Parent That Should Reap It
This is the situation from the intro. pstree does not mark zombie processes with any symbol of its own, that detail still comes from ps, but once you know a PID is stuck in the Z state, pstree is the fastest way to find out which parent owns it, since a zombie cannot be killed directly and only its parent can clear it.
LinuxTeck
4821 4790 Z backup.sh
ps confirms PID 4821 is a zombie and tells you its parent is 4790. Feed that parent PID into pstree with -p to see exactly where it sits in the wider tree, including the cron entry that ultimately kicked it off.
LinuxTeck
Production Tip:
You cannot kill a zombie, there is no running code left to receive a signal. Instead, deal with the parent shown by pstree: if 4790 is still alive and just never called wait() on its child, sending it SIGCHLD is often enough to clear the zombie. If the parent itself is hung, you have to restart or kill that parent, at which point init or systemd adopts and reaps the orphaned zombie automatically. Either way, pstree is what tells you which process to act on instead of guessing.
Questions I Get Asked About pstree All the Time
What's the actual difference between pstree and ps?
ps gives you a flat list of processes with columns of data, while pstree takes that same information and arranges it by parent-child relationship. You'd use the ps command when you need specific fields like CPU or memory, and pstree when you just need to understand the hierarchy fast.
Can pstree kill a process directly?
No, pstree is read only. Once you've found the PID you need with pstree -p, you still hand it off to kill or killall yourself.
Why does my output show something like 4*[nginx] instead of listing each process?
That's pstree's compaction behavior. When several sibling processes have identical command lines, it collapses them into one line with a count instead of repeating the same name over and over. Pass -c if you want them listed individually.
Conclusion
pstree turns a confusing pile of PIDs into something you can actually read at a glance, and once -p and -a become muscle memory you'll reach for it before ps most days. It's also the tool that finally solved that cron zombie mess from the intro, tracing the stuck child back to its parent in one shot instead of piecing it together by hand. If you want the rest of your process toolkit in one place, the system monitoring cheat sheet is a good next stop. Which pstree example do you find most useful? Share your experience in the comments below.
From your first terminal command to advanced sysadmin skills, every guide here is written in plain English with real examples you can run right now. Explore more in our beginner command guides or check the basic Linux commands library, plus job control with fg and bg and the systemd targets guide for more on how the process tree gets built at boot. For the full flag reference, see the official pstree man page.
