Gemini on Question 14, Sep 15
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?The most idiomatic way to handle this in Bash is by using the trap command hooked to the EXIT pseudo-signal.
When you trap EXIT, Bash guarantees that the trap will run whether the script finishes normally, aborts due to set -e, or receives a standard termination signal (like SIGINT/Ctrl+C or SIGTERM).
Here are the two standard approaches, depending on how aggressive you need to be.
1. The Safe Way: Killing known background jobs
This method explicitly kills only the processes that Bash started in the background using &.
#!/bin/bash
# Define the cleanup function
cleanup() {
echo "Parent dying. Cleaning up children..."
# jobs -p lists the PIDs of all background jobs started by this script
# 2>/dev/null hides errors if the children already exited naturally
kill $(jobs -p) 2>/dev/null
}
# Register the cleanup function to run on EXIT
trap cleanup EXIT
# --- Your script logic below ---
echo "Starting child 1..."
sleep 100 &
echo "Starting child 2..."
sleep 200 &
# Wait for all background jobs to finish normally
wait2. The Aggressive Way: Killing the whole Process Group
If your background children spawn their own children (grandchildren), jobs -p won't catch them. To kill the script, its children, and its grandchildren, you send a signal to the entire process group using kill 0.
#!/bin/bash # Send SIGTERM to the entire process group trap 'trap - EXIT; kill 0' EXIT sleep 100 & bash -c 'sleep 200' & # A child that spawns a grandchild wait
Note: trap - EXIT is included inside the trap to unregister it. This prevents an infinite loop where the script sends a kill signal to its group, receives it, triggers the trap again, etc.
⚠️ The Fatal Flaw of Bash (and how to fix it)
No bash trap can catch kill -9 (SIGKILL).
If your parent script is killed via SIGKILL or an Out-Of-Memory (OOM) event, the trap will not fire, and your children will become orphaned.
If you need a 100% bulletproof guarantee (on Linux) that children will die when the parent dies, pure bash cannot do it. You have to ask the Linux kernel to do it using prctl(PR_SET_PDEATHSIG).
Since Bash can't make system calls directly, you can wrap your child processes in a tiny Python or Perl one-liner when you launch them:
#!/bin/bash # This child will die instantly if the parent bash script is kill -9'd perl -MPOSIX -e 'require "syscall.ph"; syscall(&SYS_prctl, 1, 9); exec @ARGV' -- sleep 100 & wait
(In the perl command above, 1 is PR_SET_PDEATHSIG and 9 is SIGKILL. When the parent dies, the kernel immediately sends SIGKILL to the child).
Summary: Stick to the trap cleanup EXIT with jobs -p for 99% of use cases. Only reach for the Perl/kernel trick if you have a strict requirement that no orphans can ever exist, even in the event of SIGKILL.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-15 09:07:23 UTC
- Run
- 20260915T090004Z-599f39
- Served by
- Google · HTTP 200 · finish stop
- Size
- 2,894 characters · 2,169 tokens out incl. hidden reasoning · 19.7 s
End of response · 72 lines · 2,894 characters · sha256 b7e1b87fa8649d338c42b8d75dd096ebd2ed3d3360325441b2c35929e877f6cf