#!/bin/bash
for i in {1..3}; do
sem --no-notice --id $$ -j+0 sleep 10 ";" echo Done
done
sem --no-notice --id $$ --wait
Launch it, then how to make Ctrl+C to terminate all the sleeps?
#!/bin/bash
for i in {1..3}; do
sem --no-notice --id $$ -j+0 sleep 10 ";" echo Done
done
sem --no-notice --id $$ --wait
Launch it, then how to make Ctrl+C to terminate all the sleeps?
You could use traps to catch your SIGINT
signal and manually kill all the processes spawned by your semaphores. Have a look at the following script :
#!/bin/bash
shopt -s nullglob #safety needed so that globs return empty strings when no files are present
trap kill_sem INT
function kill_sem() {
for s in ~/.parallel/semaphores/id-$$/*@*;
do
kill -15 -- -$(basename ${s%%@*})
done
}
for i in {1..3}; do
sem --no-notice --id $$ -j+0 sleep 45 ";" echo Done
done
sem --no-notice --id $$ --wait
Explanation :
trap kill_sem INT
: Acts somewhat similarily to try ... catch
blocks in other languages, but with signals rather than exception. Here, it waits for the INT
signal (CTRL+C) and executes the kill_sem
function when this happens. Link to trap documentation.
When you create a semaphore with sem
, it will create a file using the following naming pattern: ~/.parallel/semaphore/id-MYSCRIPT_PID/SEM_PID@HOST
$(basename ${s%%@*})
: extracts the SEM_PID
from all of those files, and use it as the PID_GROUP
in the kill commandkill -15 -- -PID_GROUP
: sends the SIGTERM
signal to all processes belonging to the group PID_GROUP