Is there any way to invoke a subprocess so that it and all its descendants are sent an interrupt, just as if you Ctrl-C a foreground task? I’m trying to kill a launcher script that invokes a long-running child. I’ve tried
kill -SIGINT $child
kill -SIGINT -$child
test.sh --child &
if [ "$1" = "--child" ]; then
elif [ "$1" = "--parent" ]; then
"$0" --child &
for child in $(jobs -p); do
echo kill -SIGINT "-$child" && kill -SIGINT "-$child"
wait $(jobs -p)
echo "Must be invoked with --child or --parent."
To facilitate the implementation of the user interface to job control, the operating system maintains the notion of a current terminal process group ID. Members of this process group (processes whose process group ID is equal to the current terminal process group ID) receive keyboard- generated signals such as SIGINT. These processes are said to be in the foreground. Background processes are those whose process group ID differs from the terminal's; such processes are immune to keyboard-gen‐ erated signals.
bash differentiates background processes from foreground processes by the process group ID. If the process group id is equal to process id, then the process is a foreground process, and will terminate when it receives a
SIGINT signal. Otherwise it will not terminate (unless it is trapped).
You can see the process group Id with
ps x -o "%p %r %y %x %c "
Thus, when you run a background process (with
&) from within a script, it will ignore the
SIGINT signal, unless it is trapped.
However, you can still kill the child process with other signals, such as
For example, if you change your script to the following it will successfully kill the child process:
#!/bin/bash if [ "$1" = "--child" ]; then sleep 1000 elif [ "$1" = "--parent" ]; then "$0" --child & for child in $(jobs -p); do echo kill "$child" && kill "$child" done wait $(jobs -p) else echo "Must be invoked with --child or --parent." fi
$ ./test.sh --parent kill 2187 ./test.sh: line 10: 2187 Terminated "$0" --child