Claude on Question 13, Sep 15
How do I kill a zombie process in Linux that won't respond to SIGTERM?Short answer: you can't kill a zombie — it's already dead
A zombie (state Z, sometimes shown as defunct) is not a running process. It has already terminated and released its memory, file descriptors, and CPU. All that remains is an entry in the kernel's process table holding its exit status, waiting for the parent to collect it with wait()/waitpid().
Since there's no code executing, there's nothing to deliver a signal to. SIGTERM, SIGKILL, kill -9 — all no-ops. The fix is always to get the parent to reap it.
Confirm it's actually a zombie
ps -eo pid,ppid,stat,comm | awk '$3 ~ /^Z/'
Or find them with their parents:
ps -eo pid,ppid,stat,cmd --sort=stat | grep -w Z
Step 1: Nudge the parent
The parent may just have missed the SIGCHLD. Send it manually:
kill -CHLD <parent_pid>
Well-written parents will call wait() and the zombie disappears. Buggy ones ignore it.
Step 2: Kill the parent
If the parent won't reap, kill it. The zombie is then re-parented to PID 1 (init/systemd), which reaps orphans automatically:
kill -TERM <parent_pid> # if it doesn't exit: kill -KILL <parent_pid>
The zombies vanish within moments. Obviously, weigh the cost of restarting the parent service — for a daemon, prefer a graceful restart:
systemctl restart <service>
Step 3: If the parent is PID 1
If ppid is 1 and the zombie persists, systemd (or your container's init) is failing to reap. That's unusual and indicates a bug or a stuck init. Options:
- •Check for a
D-state process blocking things (see below) - •
systemctl daemon-reexec— re-executes systemd, often clears the backlog - •Reboot as a last resort
In containers, this is common: if your entrypoint is an application rather than a proper init, it won't reap orphans. Fix it structurally with docker run --init, or use tini/dumb-init as PID 1.
Do you actually need to do anything?
A handful of zombies is harmless — each consumes one process table slot and a few hundred bytes. Act only if:
- •Zombies are accumulating (a leak that will exhaust the PID space)
- •You're approaching the limit: compare
ps -e | wc -lagainstcat /proc/sys/kernel/pid_max
Watch the trend rather than the snapshot:
watch -n 5 'ps -eo stat | grep -c "^Z"'
Common confusion: D state, not Z
If a process genuinely ignores SIGKILL and is consuming resources, it's likely in uninterruptible sleep (D), blocked in a kernel call — typically hung NFS, a failing disk, or a stuck device driver. Signals are queued but not delivered until the syscall returns.
ps -eo pid,stat,wchan:30,cmd | awk '$2 ~ /^D/' cat /proc/<pid>/stack # requires root; shows where it's blocked
These can't be killed either, but the remedy is different: fix the underlying I/O problem (remount the hung NFS share with umount -f -l, replace the failing disk, reset the device). Check dmesg -T | tail -50 for I/O errors first.
Preventing recurrence
If it's your own code, reap children properly:
/* Simplest: let the kernel discard exit statuses */
signal(SIGCHLD, SIG_IGN);
/* Or handle them explicitly, looping to catch multiple children */
void reaper(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
signal(SIGCHLD, reaper);In shell scripts, wait on background jobs. In Python, subprocess.Popen.wait() or .poll(). Long-running supervisors that spawn children need an explicit reaping strategy — forgetting it is the single most common cause of zombie accumulation.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-15 09:05:44 UTC
- Run
- 20260915T090004Z-599f39
- Served by
- Claude Platform on AWS · HTTP 200 · finish stop
- Size
- 3,594 characters · 1,839 tokens out incl. hidden reasoning · 25.9 s
End of response · 94 lines · 3,594 characters · sha256 8e9f5b241d444ffda78071f928b8ad7693f5286f5ed17e24be6dbf70916b9ff5