Gemini on Question 14, Oct 3
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 tied to the EXIT pseudo-signal.
When you set a trap on EXIT, Bash guarantees that the trap will execute when the script terminates, whether it finishes naturally, errors out, or is killed by a standard signal (like SIGINT/Ctrl+C or SIGTERM).
Here are the two standard approaches, depending on how complex your child processes are.
1. The Standard Way: Kill immediate background jobs
If your script spawns background processes (&), you can use jobs -p to get their PIDs and kill them when the parent exits.
#!/bin/bash # Set a trap to kill all background jobs when the script exits trap 'kill $(jobs -p) 2>/dev/null' EXIT echo "Starting background tasks..." sleep 100 & sleep 200 & echo "Doing some work in the parent..." sleep 5 echo "Parent exiting. Trap will now kill the sleep processes."
Note: We redirect to /dev/null to suppress errors in case some child processes have already finished naturally before the parent exits.
2. The Deep Tree Way: Kill the Process Group (kill 0)
If your background processes spawn their own child processes (grandchildren), jobs -p won't be enough, as it only kills the immediate children. The grandchildren will still orphan.
To fix this, you can kill the entire process group by sending a signal to PID 0.
#!/bin/bash # Ensure the script runs in its own process group. # (By default, it might share a process group with the terminal). set -m # Kill the entire process group on exit trap 'trap - EXIT; kill 0' EXIT echo "Starting a complex background script..." ./some_script_that_spawns_more_scripts.sh & sleep 5
(Note: trap - EXIT inside the trap clears the trap so it doesn't recursively trigger itself).
⚠️ The SIGKILL Caveat (and how to fix it)
The trap command cannot catch SIGKILL (kill -9).
If the Linux Out-Of-Memory (OOM) killer targets your parent script, or a user runs kill -9, the trap will not execute, and the children will become orphans.
If your script requires bulletproof orphan prevention (even against kill -9), pure Bash isn't enough. You have two options:
Option A: The Subshell Polling Trick (Pure Bash but slightly hacky)
You can spawn a watcher process that checks if the parent is alive, and kills the child if the parent disappears.
#!/bin/bash
# Start a background task
sleep 100 &
CHILD_PID=$!
# Start a disowned watcher subshell
(
# Wait for parent PID to disappear
while kill -0 $PPID 2>/dev/null; do
sleep 1
done
# Parent died, kill the child!
kill -9 $CHILD_PID 2>/dev/null
) & disownOption B: The Linux Kernel Way (prctl)
Linux has a feature called PR_SET_PDEATHSIG, which tells the kernel itself to send a signal to a child when its parent dies.
You can access this via standard Linux utilities like prlimit or a tiny python wrapper.
#!/bin/bash # Using python to wrap the child execution and set the death signal python3 -c "import ctypes, os, sys; ctypes.CDLL(None).prctl(1, 9); os.execvp(sys.argv[1], sys.argv[1:])" sleep 100 &
(In this example, 1 is PR_SET_PDEATHSIG and 9 is SIGKILL. If the parent bash script dies for ANY reason, the kernel instantly kills sleep 100).
Summary
- •Use
trap 'kill $(jobs -p) 2>/dev/null' EXITfor 95% of use cases. It is standard, readable, and highly idiomatic. - •Use the subshell watcher or
prctlonly if you explicitly need protection againstkill -9or the OOM killer.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-10-03 09:06:35 UTC
- Run
- 20261003T090008Z-b2d35e
- Served by
- Google · HTTP 200 · finish stop
- Size
- 3,570 characters · 2,755 tokens out incl. hidden reasoning · 25.1 s
End of response · 91 lines · 3,570 characters · sha256 ce3c60283d9998738c4908c62bab149bf560e155409aa721ed6282ef1d5a3533