top shows 1 zombie, or ps lists processes marked <defunct> with state Z. Zombies sound alarming, but a few are usually harmless. Here’s what they are, when they matter, and how to get rid of them. Hint: kill -9 on the zombie won’t work.
What a zombie is
When a process exits, it doesn’t vanish immediately. The kernel keeps a tiny entry (PID, exit status, resource usage) until the parent process reads that exit status with wait(). This is called reaping. Between exiting and being reaped, the process is a zombie.
A zombie:
- uses no CPU and no memory beyond its process table entry;
- can’t be killed, because it’s already dead;
- disappears when its parent reaps it, or when the parent itself exits.
Short-lived zombies are normal. Persistent zombies mean the parent program has a bug: it starts children and never waits for them.
Find zombies
top # "zombie" count in the Tasks line
ps aux | awk '$8 ~ /^Z/' # STAT column starts with Z
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /^Z/'
PID PPID STAT CMD
4821 4410 Z [php] <defunct>
4822 4410 Z [php] <defunct>
The PPID column is the important one. It identifies the parent that isn’t reaping.
ps -o pid,user,cmd -p 4410
When do they matter?
- A handful: cosmetic. Monitoring may complain, but there’s no resource impact.
- Thousands and growing: each zombie holds a PID. If the system reaches the PID limit (
/proc/sys/kernel/pid_max), or a cgroup’sTasksMax, new processes can’t start. Fork failures follow: “Resource temporarily unavailable”.
ps -eo stat | grep -c '^Z'
cat /proc/sys/kernel/pid_max
How to clear them
You can’t kill a zombie. You deal with its parent.
1. Ask the parent to reap. Some programs reap on SIGCHLD:
kill -s SIGCHLD 4410
This often does nothing with buggy parents, but it’s harmless to try.
2. Restart the parent. When the parent exits, its zombies are re-parented to PID 1 (systemd), which reaps them immediately:
sudo systemctl restart myapp # if the parent is a service
kill 4410 # or terminate the parent process
This is the reliable fix. Plan it for a quiet moment if the parent is an important service.
3. If the parent is PID 1 (systemd) and zombies persist, something is unusual. Check journalctl for errors. Inside a container, see below.
Prevent zombies
In your own code
Always wait for child processes:
- Python: use
subprocess.run()(it waits), or call.wait()/.communicate()onPopenobjects. - Node.js:
child_processhandles reaping. Make sure you handleexitandcloseevents, and don’t leak spawned processes. - Bash: background jobs started with
&are reaped by the shell. Usewaitin long-running scripts that spawn many jobs. - C/Go and others: handle SIGCHLD or call
waitpid().
In Docker containers
This is a very common source of zombies. Your app runs as PID 1 in the container. If it spawns child processes (shell scripts, PhantomJS/Chrome, git, ImageMagick) and doesn’t reap them, zombies pile up, because PID 1 normally reaps orphans and your app doesn’t know it has to.
Fix it with a minimal init process:
docker run --init myimage
# docker-compose.yml
services:
app:
image: myimage
init: true
Or include tini or dumb-init as the entrypoint in your Dockerfile:
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]
The init also forwards signals properly. See Linux signals and Dockerfile tutorial.
Zombie vs orphan vs stuck (D state)
| State | Meaning | Fix |
|---|---|---|
| Z (zombie) | Dead, waiting to be reaped | Restart or fix the parent |
| Orphan | Running, parent died, adopted by PID 1 | Usually fine. Stop it if unwanted |
| D (uninterruptible sleep) | Alive, stuck waiting on I/O (disk, NFS) | Fix the I/O issue. Can’t be killed while in D |
D-state processes raise the load average without using CPU. See load average.
Quick reference
| Task | Command |
|---|---|
| Count zombies | ps -eo stat | grep -c '^Z' |
| List with parent | ps -eo pid,ppid,stat,cmd | awk '$3 ~ /^Z/' |
| Show parent | ps -o pid,cmd -p PPID |
| Nudge parent | kill -s SIGCHLD PPID |
| Real fix | Restart the parent / fix its code |
| Docker | --init or init: true |
Related: ps command and kill a process.