Reputation: 11730
I have the following in bash:
foo | bar
I want foo
to die when the script is terminated (using a TERM signal). Unfortunately, none of them dies. I tried this:
exec foo | bar
This achieved absolutely nothing. Then I tried this:
function run() {
"$@" &
pid=$!
trap "kill $pid" EXIT
wait
}
run foo | bar
Again, nothing. Now I have one more process, and none of them dies when I terminate the parent.
Upvotes: 7
Views: 1287
Reputation: 1563
By killing the whole process group instead of just bash
(the parent), you can send the kill signal to all children as well.
Syntax examples are:
kill -SIGTERM -$!
kill -- -$!
Example:
bash -c 'sleep 50 | sleep 40' & sleep 1; kill -SIGTERM -$!; wait; ps -ef | grep -c sleep
[1] 14683
[1]+ Terminated bash -c 'sleep 50 | sleep 40'
1
Note that wait
here waits for bash to be effectively killed which takes some milliseconds.
Also note that the final result (1) is the 'grep sleep' itself. A result of 3 would show that this did not work as two additional sleep processes would still be running.
The kill
manual mentions:
-n
where n is larger than 1. All processes in process group n are signaled.
When an argument of the form '-n' is given, and it is meant to denote a
process group, either the signal must be specified first, or the argument
must be preceded by a '--' option, otherwise it will be taken as the signal
to send.
Upvotes: 1
Reputation: 531135
I would use a named pipe, which makes it easier to get the process ID of foo
specifically.
trap 'kill $foo_pid; rm -f foo_out' EXIT
mkfifo foo_out
foo > foo_out & foo_pid=$!
bar < foo_out
Upvotes: 1