Gemini on Question 14, Sep 11
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?The idiomatic way to handle this in Bash is to use the trap command combined with the EXIT pseudo-signal.
Here are the standard approaches, ranging from simple child processes to complex process trees.
1. The Standard Idiomatic Way (Direct Children)
If your script spawns background tasks and you want them to die when the script exits (normally, errors out, or receives Ctrl+C), trap the EXIT signal and kill the background jobs.
#!/bin/bash
# Define a cleanup function
cleanup() {
# jobs -p lists the PIDs of all background jobs started by this script
local pids=$(jobs -p)
if [[ -n "$pids" ]]; then
echo "Purging orphaned children..."
kill $pids 2>/dev/null
fi
}
# Trap the EXIT signal
trap cleanup EXIT
# --- Your script logic below ---
sleep 100 & # Child 1
sleep 200 & # Child 2
# Wait for children to finish (or script gets killed)
waitWhy this works: The EXIT trap in bash is special. It fires when the script finishes naturally, but it also fires if the script receives standard termination signals like SIGINT (Ctrl+C) or SIGTERM (standard kill).
2. The "Process Group" Way (Children of Children)
If your child processes spawn their own child processes, jobs -p isn't enough because it only knows about direct children. You need to kill the entire process group.
You can do this by sending a signal to 0 (which targets the current process group) or to -$$ (the negative PID of the current shell, which denotes its process group).
#!/bin/bash
cleanup() {
echo "Purging entire process group..."
# 1. Ignore the TERM signal so the parent doesn't kill itself recursively
trap '' TERM
# 2. Send SIGTERM to the entire process group
kill -TERM 0 2>/dev/null
# Optional: wait a moment and send SIGKILL if they are stubborn
# sleep 1; kill -KILL 0 2>/dev/null
}
trap cleanup EXIT
# --- Your script logic below ---
# Even if this script spawns children that spawn more children,
# they will all be purged.
./some_complex_subscript.sh &
wait3. The Uncatchable Exception: kill -9
Crucial Caveat: Bash scripts cannot catch SIGKILL (kill -9). If someone runs kill -9 <parent_pid>, the parent dies instantly, the trap never fires, and the children become orphans (re-parented to PID 1).
If you must guarantee that children die even if the parent receives kill -9, Bash alone cannot do it. You must rely on OS-level features:
- •Linux
prctl(PR_SET_PDEATHSIG): This tells the Linux kernel to send a signal to a child when its parent dies. You can't do this purely in Bash, but you can use a small wrapper. If you have Python installed, you can wrap your child process like this:
```bash
python3 -c "import ctypes, os, sys; libc = ctypes.CDLL(None); libc.prctl(1, 9); os.execvp(sys.argv[1], sys.argv[1:])" my_child_command &
``` - •systemd: If this is a daemon/service, let
systemdmanage it. By default, when asystemdservice stops or is killed, it uses cgroups to ruthlessly terminate every child process associated with it.
Summary Recommendation
For 95% of use cases, Method 1 (trap cleanup EXIT with jobs -p) is exactly what you want. It is clean, POSIX-compliant, highly readable, and firmly accepted as bash idiom.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-11 09:09:33 UTC
- Run
- 20260911T090002Z-da0dd3
- Served by
- Google · HTTP 200 · finish stop
- Size
- 3,348 characters · 2,339 tokens out incl. hidden reasoning · 20.5 s
End of response · 77 lines · 3,348 characters · sha256 da612f10b86d7a64ab579fae1b9f864682c859ed99d5c6df623f87e7a697204a