Zombie Processes in Linux: Find, Remove, Prevent
15 min read - May 19, 2026

Learn how to identify, remove, and prevent zombie processes in Linux. Commands, code fixes, and monitoring tips for server admins.
Zombie Processes in Linux: How to Find and Remove Them
A zombie process is a child process that has finished executing but still occupies a slot in the kernel's process table. It exists because the parent process hasn't called wait() to collect its exit status. Zombies don't consume CPU or memory, but each one holds a PID. Let enough of them pile up and your system can't spawn new processes. This post covers how to spot them, remove them, and stop them from appearing in the first place.
Why Zombie Processes Matter on Servers
A single zombie is harmless. The problem starts when they accumulate. Linux has a finite PID space: 32,768 on 32-bit systems, up to 4,194,304 on 64-bit. If zombie processes fill the process table, the kernel can't create new processes. That means no new connections, no new worker threads, no new anything.
Web servers like Apache and Nginx are particularly exposed because they fork child processes to handle traffic. Benchmarks have shown a 48% drop in throughput when zombies accumulate on a busy web server. In 2019, a Golang channel leak in a Kubernetes DNS pod created over 26,000 zombies on a single node, filling the process table and crashing DNS resolution cluster-wide.
The table below shows the key differences between a normal process and a zombie:
| Characteristic | Normal Process | Zombie Process |
|---|---|---|
| State symbol | R, S, D, or T | Z (defunct) |
| CPU / Memory | Active usage | 0% / 0 (already terminated) |
| Process table entry | One slot | One slot |
Response to kill -9 | Terminates immediately | No effect (already dead) |
| Kernel memory | Full process descriptor | Minimal exit status only |
The critical takeaway: you can't kill -9 a zombie. It's already dead. The only way to clear it is to make the parent process reap it, or kill the parent so init (PID 1) inherits and reaps it automatically.
How to Find Zombie Processes
Zombies show up with a Z in the STAT column and <defunct> next to the command name. List them with:
ps aux | grep -w ZTo see the parent process ID (PPID), which you'll need for removal:
ps -eo pid,ppid,stat,comm | grep -w ZThe top command also reports the total zombie count in its header line. For a quick non-interactive check:
top -bn1 | grep zombieTracing the parent with pstree
Once you have a zombie's PID, trace it back to the responsible parent:
pstree -p -s <zombie_pid>This shows the full ancestry from init down to the zombie. If pstree isn't installed, ps auxf gives a similar ASCII tree view.
Counting zombies for monitoring
A clean count that excludes the grep process itself:
ps aux | awk '$8 ~ /Z/ {count++} END {print count+0}'For continuous monitoring during troubleshooting:
watch -n 1 'ps aux | grep -w Z | wc -l'How to Remove Zombie Processes
Zombies can only be removed by having their exit status collected. That means working through the parent process.
1. Find the parent.
ps -o ppid= -p <zombie_pid>2. Signal the parent to reap its children.
kill -SIGCHLD <parent_pid>This tells the parent to call wait() on any terminated children. It's non-disruptive and works with well-behaved applications.
3. If SIGCHLD doesn't work, restart the service.
systemctl restart <service_name>4. If the parent is unresponsive, kill it.
kill <parent_pid>Or if it ignores SIGTERM:
kill -9 <parent_pid>When the parent dies, init (PID 1) or systemd adopts the orphaned zombies and reaps them immediately. Be careful on production systems. Killing the parent also terminates all its active children.
5. Verify the cleanup.
ps aux | awk '$8 ~ /Z/ {count++} END {print count+0}'If the count is 0, you're clear.
Preventing Zombie Processes
Handle child processes in your code
The root cause of most zombie buildups is a parent process that never calls wait(). Fix it at the source:
- C: Set
signal(SIGCHLD, SIG_IGN);to discard child exit info automatically, or use a signal handler withwaitpid(-1, NULL, WNOHANG)to reap asynchronously. - Python: Use
subprocess.run(), which waits automatically. If usingPopen, callproc.wait()explicitly. - Bash: Add
waitat the end of scripts that launch background jobs.
Configure systemd properly
For services managed by systemd, these settings prevent zombie buildup:
KillMode=control-groupensures all child processes are terminated together when the service stops.TimeoutStopSecgives the parent time to reap children before systemd sends SIGKILL.WatchdogSecrestarts unresponsive services automatically, catching cases where the parent hangs and stops reaping.
Monitor your process table
Set up a cron job that runs every 15 minutes to count zombies and alert if the count exceeds a threshold:
ps aux | awk '$8 ~ /Z/' | wc -lAlso monitor your process table usage by comparing the current count against /proc/sys/kernel/pid_max. If it exceeds 80%, investigate before it becomes a problem. A few transient zombies during normal operation are nothing to worry about. A growing count that doesn't drop back to zero points to an application bug that needs fixing.
Conclusion
Zombie processes are dead children that haven't been cleaned up. They don't use CPU or memory, but they hold PIDs, and a full process table stops your server from doing anything useful.
- Find them with
ps aux | grep -w Zand trace the parent withpstree. - Remove them by sending
SIGCHLDto the parent, restarting the service, or killing the parent as a last resort. - Prevent them by writing code that calls
wait(), configuring systemd correctly, and monitoring your process table.
If you're running high-traffic workloads and need reliable infrastructure with full root access, FDC's dedicated servers give you full control over your process management and system configuration.

Zombie Processes in Linux: Find, Remove, Prevent
Learn how to identify, remove, and prevent zombie processes in Linux. Commands, code fixes, and monitoring tips for server admins.
15 min read - May 19, 2026

Have questions or need a custom solution?
Flexible options
Global reach
Instant deployment
Flexible options
Global reach
Instant deployment