I want to run a series of commands concurrently such that if one of them dies they all stop.
If you've got Bash 4.3 (2014) or later, this Shellcheck-clean code demonstrates one way to do it:
#! /bin/bash -p
# Start some concurrent processes
sleep 30 & sleep 31 & sleep 32 & sleep 33 & sleep 34 & sleep 35 & sleep 36 &
sleep 5 &
# Wait for any job to complete
wait -n
# Get the list of still running jobs, and kill them
jobs=$(jobs -r)
while read -r num _ cmd; do
printf 'Killing: %s\n' "$cmd" >&2
kill "%${num//[^[:digit:]]/}"
done <<<"$jobs"
-n
option for wait
was introduced in Bash 4.3, so the code will not work with older versions of Bash.num
variable is [3]+
. ${num//[^[:digit:]]/}
extracts the job number (3
in this case) by removing all non-digit characters. See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)) for more information about ${var//old/}
.