Operations 11 min read

Self‑Terminating Bash Scripts with trap, kill, and pkill

This article explains why background loops in Bash scripts can become orphaned under init/systemd, demonstrates how to reliably terminate such scripts by using trap handlers with kill, killall, pkill, and signal 0, and provides robust examples for various execution scenarios.

Open Source Linux
Open Source Linux
Open Source Linux
Self‑Terminating Bash Scripts with trap, kill, and pkill

Script Self‑Termination in Bash

When a Bash script launches background tasks (e.g., sleep) and then exits, those tasks may become children of the init / systemd process instead of terminating with the script. This can leave orphaned processes that continue running after the script is stopped.

Simple termination works for a single background job:

#!/bin/bash
 echo $BASHPID
 sleep 50 &
 kill $!

However, if the background job is inside a loop ( while, for, until), killing $! is insufficient because the loop itself runs in a subshell that also needs to be terminated.

One approach is to use killall to kill all processes with the script’s name before exiting:

#!/bin/bash
 trap 'killall `basename $0`' SIGINT
 echo $BASHPID
 while true; do
   sleep 50
   echo 1
 done &
 killall `basename $0`

To handle both execution styles ( ./script.sh and bash script.sh) and to ensure the background subshell is also killed, replace killall with pkill -f and explicitly kill the job stored in $!:

#!/bin/bash
 trap 'pkill -f `basename $0`' SIGINT
 echo $BASHPID
 while true; do
   sleep 50
   echo 1
 done &
 pid=$!
 kill $pid
 pkill -f `basename $0`

A more robust solution combines all cleanup steps in a single trap that handles SIGINT, SIGTERM, EXIT, and ERR:

#!/bin/bash
 trap 'pkill -f $(basename $0); exit 1' SIGINT SIGTERM EXIT ERR
 while true; do
   sleep 1
   echo "hello world!"
 done &
 # additional foreground work
 sleep 60

For cases where you want to kill every process in the script’s process group, sending a signal to PID 0 works:

#!/bin/bash
 trap 'echo "signal_handled:"; kill 0' SIGINT SIGTERM
 while true; do
   sleep 5
   echo "hello world! hello world!"
 done &
 sleep 60

Why does a background while create an extra Bash process? Bash built‑in commands ( while, for, until, etc.) run inside the current Bash process. When placed in the background, Bash spawns a new subshell to provide the required environment. If the script is the parent, that subshell becomes a child of the script; otherwise, an interactive shell creates a new Bash process. Killing the parent Bash process leaves the subshell (and its background jobs) re‑parented to init / systemd.

Examples of backgrounding built‑ins and observing the resulting process tree illustrate this behavior:

if true; then sleep 10; fi &
# or
while true; do sleep 2; done &

After killing the original Bash, the newly created subshell remains attached to init, showing why proper cleanup via trap and group‑wide signals is essential for reliable script termination.

In summary, using trap to catch termination signals and employing kill, killall, pkill, or kill 0 ensures that all background jobs spawned by a Bash script are terminated, preventing orphaned processes from persisting under the system init.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Bashscriptsignalstrapprocess-management
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.