Reputation:
Is there any built in feature in bash to wait for 1 out of many processes to finish? And then kill remaining processes?
pids=""
# Run five concurrent processes
for i in {1..5}; do
( longprocess ) &
# store PID of process
pids+=" $!"
done
if [ "one of them finished" ]; then
kill_rest_of_them;
fi
I'm looking for "one of them finished" command. Is there any?
Upvotes: 8
Views: 5407
Reputation: 532113
bash
4.3 added a -n
flag to the built-in wait
command, which causes the script to wait for the next child to complete. The -p
option to jobs
also means you don't need to store the list of pids, as long as there aren't any background jobs that you don't want to wait on.
# Run five concurrent processes
for i in {1..5}; do
( longprocess ) &
done
wait -n
kill $(jobs -p)
Note that if there is another background job other than the 5 long processes that completes first, wait -n
will exit when it completes. That would also mean you would still want to save the list of process ids to kill, rather than killing whatever jobs -p
returns.
Upvotes: 13
Reputation: 1
It's actually fairly easy:
#!/bin/bash
set -o monitor
killAll()
{
# code to kill all child processes
}
# call function to kill all children on SIGCHLD from the first one
trap killAll SIGCHLD
# start your child processes here
# now wait for them to finish
wait
You just have to be really careful in your script to use only bash built-in commands. You can't start any utilities that run as a separate process after you issue the trap
command - any child process exiting will send SIGCHLD
- and you can't tell where it came from.
Upvotes: 4