Gemini on Question 14, Sep 20
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?The most idiomatic and reliable way to handle this in a Bash script is using the trap command hooked to the EXIT pseudo-signal, combined with jobs -p.
Here is the standard, best-practice pattern:
#!/bin/bash
# Define a cleanup function
cleanup() {
echo "Parent dying, cleaning up children..."
# Get PIDs of all background jobs started by this script
local pids=$(jobs -p)
if [[ -n "$pids" ]]; then
# Send SIGTERM to all children, suppress errors if they already died
kill $pids 2>/dev/null
fi
}
# Trap the EXIT signal to run the cleanup function
trap cleanup EXIT
# --- Your script logic below ---
# Example child processes
sleep 100 &
sleep 200 &
echo "Parent doing work... (Press Ctrl+C to test)"
sleep 10Why this is idiomatic:
- 1.
trap ... EXIT: In Bash, theEXITtrap triggers when the script ends naturally, but it also triggers if the script is killed viaSIGINT(Ctrl+C) orSIGTERM(a standardkill). - 2.
jobs -p: This safely prints the Process IDs of all background jobs currently managed by this specific shell instance. - 3.
2>/dev/null: If a child process happens to finish right before the script exits,killwill complain that the process doesn't exist. This suppresses that harmless error.
Advanced Edge Cases
Depending on your needs, the standard idiom above might have a few blind spots. Here is how to address them:
1. What if your children spawn their own children (Grandchildren)?
jobs -p only tracks direct children. If your script launches a Python script in the background, and that Python script launches a subprocess, the grandchild will be orphaned.
To kill the entire process tree, you can kill the Process Group. By default, scripts run in the same process group as the terminal that spawned them, so you must explicitly put your background process in its own group using set -m (monitor mode):
#!/bin/bash
set -m # Enable job control so background jobs get their own process group
cleanup() {
local pids=$(jobs -p)
if [[ -n "$pids" ]]; then
# The negative sign (-) tells kill to target the whole process group
# This kills the child and any grandchildren it spawned
kill -- -${pids//$'\n'/ -} 2>/dev/null
fi
}
trap cleanup EXIT
# ...2. The SIGKILL (kill -9) problem
No script can trap SIGKILL (kill -9). If your parent script is killed with -9, the EXIT trap will not run, and the children will be orphaned.
If absolute guarantee against orphaning is required, you must rely on Linux kernel features rather than Bash features. The standard modern way to do this is to run your script as a Systemd transient service:
# Instead of running: ./myscript.sh # Run it like this: systemd-run --user --scope ./myscript.sh
When you do this, Linux places the script and all its children/grandchildren into a cgroup. If the parent dies (even by kill -9), systemd will mercilessly purge every child process in that cgroup.
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-20 09:07:33 UTC
- Run
- 20260920T090019Z-bbedf3
- Served by
- Google AI Studio · HTTP 200 · finish stop
- Size
- 3,061 characters · 2,268 tokens out incl. hidden reasoning · 32.1 s
End of response · 77 lines · 3,061 characters · sha256 23a0a55e8d5834a93425cd63a3491e2c55354d199ce31714368effddbec8d7c1