4
#!/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?

Velkan
  • 7,067
  • 6
  • 43
  • 87
  • See if you can rewrite your code to use parallel in its normal mode instead. Then it works out of the box. (And consider running --bibtex just once). – Ole Tange Jan 24 '17 at 21:22

1 Answers1

2

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 command
    • kill -15 -- -PID_GROUP : sends the SIGTERM signal to all processes belonging to the group PID_GROUP
Aserre
  • 4,916
  • 5
  • 33
  • 56