Both your example and the accepted answer are overly complicated, why do you not only use timeout
since that is exactly its use case? The timeout
command even has an inbuilt option (-k
) to send SIGKILL
after sending the initial signal to terminate the command (SIGTERM
by default) if the command is still running after sending the initial signal (see man timeout
).
If the script doesn’t necessarily require to wait
and resume control flow after waiting it’s simply a matter of
timeout -k 60s 60s app1 &
timeout -k 60s 60s app2 &
# [...]
If it does, however, that’s just as easy by saving the timeout
PIDs instead:
pids=()
timeout -k 60s 60s app1 &
pids+=($!)
timeout -k 60s 60s app2 &
pids+=($!)
wait "${pids[@]}"
# [...]
E.g.
$ cat t.sh
#!/bin/bash
echo "$(date +%H:%M:%S): start"
pids=()
timeout 10 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 1 terminated successfully"' &
pids+=($!)
timeout 2 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 2 terminated successfully"' &
pids+=($!)
wait "${pids[@]}"
echo "$(date +%H:%M:%S): done waiting. both jobs terminated on their own or via timeout; resuming script"
.
$ ./t.sh
08:59:42: start
08:59:47: job 1 terminated successfully
08:59:47: done waiting. both jobs terminated on their own or via timeout; resuming script