Run multiple teams in parallel and return when one of them fails or all of them succeed

I saw the following question: Bash run two commands and get output to both that almost answer my needs.

However, the wait command is blocked, so this means that if command 2 fails before command 1 succeeds, the command will not return when command 2 fails, but only when command 1 is successful.

Is it possible to run several commands in parallel and return 1 when one of them fails and returns 0 if all of them are successful (and as soon as possible)?

It would be even better if it were possible using standard commands (for example, xargs or parallel), but also good if it is written using bash.

+5
source share
2 answers

This code gives the correct exit code and kills the survivor process:

#/bin/bash # trap for SIGTERM and set RET_VALUE to false trap "RET_VAL=false" SIGTERM MY_PID=$$ # Initialize RET_VALUE to true RET_VAL=true # This function will executed be in a separate job (see below) thread_listener() { # Starts the long time job ./longJob.sh & PID=$! # trap for sigterm and kill the long time process trap "kill $PID" SIGTERM echo waiting for $PID echo Parent $MY_PID # Send a SIGTERM to parent job in case of failure wait $PID || kill $MY_PID exit } echo $MY_PID # Runs thread listener in a separate job thread_listener & PID1=$! # Runs thread listener in a separate job thread_listener & PID2=$! wait # send sigterm to PID1 and PID2 if present kill $PID1 2> /dev/null kill $PID2 2> /dev/null # returns RET_VALUE $RET_VAL 

See comments for an explanation of the code. The trick is to run tasks that can receive or send a signal to parental work, if necessary.

The child task sends a signal to the parent in case of failure of its long-term task, and the parent sends a signal to its children after waiting (the parent receives a signal that expects to return immediately)

+2
source

Recent versions of GNU Parallel have focused on this particular problem. Kill the running children if one of them fails:

 parallel --halt now,fail=1 'echo {};{}' ::: true false true true false 

Kill the running children if one succeeds:

 parallel --halt now,success=1 'echo {};{}' ::: true false true true false 

Kill working children if they failed to complete 20%:

 parallel -j1 --halt now,fail=20% 'echo {#} {};{}' ::: true true true false true true false true false true 

Kill a child with the TERM, TERM, TERM, KILL signals, waiting for 50 ms between each signal:

 parallel --termseq TERM,50,TERM,50,TERM,50,KILL -u --halt now,fail=1 'trap "echo TERM" SIGTERM; sleep 1;echo {};{}' ::: true false true true false 
+1
source

All Articles