Gemini on Question 14, Sep 14
I'm writing a bash script to purge orphaned children after the parent dies. What's the idiomatic way?The most idiomatic, pure-bash way to clean up child processes is to use the trap builtin combined with jobs -p or process group signaling, hooked to the EXIT pseudo-signal.
Here are the two standard approaches, depending on whether your child processes spawn their own children.
1. The Standard Idiom (Direct Children Only)
If your script spawns background processes (&) and you only need to kill those direct children, use jobs -p:
#!/bin/bash # 1. Set the trap to kill all background jobs spawned by this shell trap 'kill $(jobs -p) 2>/dev/null' EXIT # 2. Start some background tasks sleep 100 & sleep 200 & echo "Running... Press Ctrl+C or let the script exit to see cleanup." sleep 5
Why this works:
- •
EXIT: This pseudo-signal is triggered when the script exits naturally, errors out (ifset -eis used), or receives a standard termination signal (SIGINT,SIGTERM). - •
jobs -p: Returns the Process IDs (PIDs) of all background jobs currently tracked by the shell. - •
2>/dev/null: Suppresses error messages just in case some of the children have already finished and exited on their own.
2. The "Process Group" Idiom (Children and Grandchildren)
If your background tasks spawn their own subprocesses, jobs -p isn't enough (the grandchildren will be orphaned). You need to kill the entire process group.
#!/bin/bash # Send SIGTERM to the script's entire process group trap 'trap - EXIT; kill 0' EXIT # Start a child that spawns a grandchild ( sleep 10 ; sleep 20 ) & echo "Running..." sleep 5
Why this works:
- •
kill 0: Sends aSIGTERMto all processes in the current process group. - •
trap - EXIT: This is crucial. Becausekill 0sends a signal to the whole group (which includes the parent script itself), it can cause an infinite loop where the script catches its own exit, tries to exit again, and triggers the trap again. Unsetting the trap first prevents this.
⚠️ The Fatal Flaw of Bash Traps (SIGKILL)
Both methods above rely on the shell catching a signal and running the trap. They will fail if the parent script is killed with SIGKILL (kill -9). SIGKILL cannot be intercepted by bash.
If you need bulletproof protection against kill -9 or Out-Of-Memory (OOM) kills, Bash alone cannot help you. You must use operating system features:
Linux-specific bulletproof alternative (systemd):
If you are on Linux, you can run your script inside a temporary systemd scope. Systemd uses cgroups, meaning when the scope ends or is killed, the kernel ruthlessly wipes out every child and grandchild inside it automatically.
# Run your script this way instead of directly: systemd-run --user --scope ./your_script.sh
Linux-specific bulletproof alternative (prctl):
If you are writing wrappers in C, Python, or Go, you can use the prctl(PR_SET_PDEATHSIG, SIGTERM) system call. This tells the Linux kernel to automatically send a signal to the child when the parent thread dies, regardless of how the parent died. (Bash doesn't have access to this without external C-bindings/binaries like pdeathsig).
Exact recordShowHideThe model id, the run, the verbatim text with line numbers and its full sha256
- Scored
- answered
- Received
- 2026-09-14 09:07:57 UTC
- Run
- 20260914T090022Z-e98262
- Served by
- Google · HTTP 200 · finish stop
- Size
- 3,149 characters · 2,287 tokens out incl. hidden reasoning · 21.2 s
End of response · 63 lines · 3,149 characters · sha256 64e1758a61f540dcef19322c7e60f48a746a6179b805572af7f20550d37a803f