How to wait in bash for several subprocesses to finish and return exit code !=0 when any subprocess ends with code !=0?

后端 未结 30 2410
悲哀的现实
悲哀的现实 2020-11-22 03:50

How to wait in a bash script for several subprocesses spawned from that script to finish and return exit code !=0 when any of the subprocesses ends with code !=0 ?

S

相关标签:
30条回答
  • 2020-11-22 04:26

    I've had a go at this and combined all the best parts from the other examples here. This script will execute the checkpids function when any background process exits, and output the exit status without resorting to polling.

    #!/bin/bash
    
    set -o monitor
    
    sleep 2 &
    sleep 4 && exit 1 &
    sleep 6 &
    
    pids=`jobs -p`
    
    checkpids() {
        for pid in $pids; do
            if kill -0 $pid 2>/dev/null; then
                echo $pid is still alive.
            elif wait $pid; then
                echo $pid exited with zero exit status.
            else
                echo $pid exited with non-zero exit status.
            fi
        done
        echo
    }
    
    trap checkpids CHLD
    
    wait
    
    0 讨论(0)
  • 2020-11-22 04:26

    There are already a lot of answers here, but I am surprised no one seems to have suggested using arrays... So here's what I did - this might be useful to some in the future.

    n=10 # run 10 jobs
    c=0
    PIDS=()
    
    while true
    
        my_function_or_command &
        PID=$!
        echo "Launched job as PID=$PID"
        PIDS+=($PID)
    
        (( c+=1 ))
    
        # required to prevent any exit due to error
        # caused by additional commands run which you
        # may add when modifying this example
        true
    
    do
    
        if (( c < n ))
        then
            continue
        else
            break
        fi
    done 
    
    
    # collect launched jobs
    
    for pid in "${PIDS[@]}"
    do
        wait $pid || echo "failed job PID=$pid"
    done
    
    0 讨论(0)
  • 2020-11-22 04:28

    Just store the results out of the shell, e.g. in a file.

    #!/bin/bash
    tmp=/tmp/results
    
    : > $tmp  #clean the file
    
    for i in `seq 0 9`; do
      (doCalculations $i; echo $i:$?>>$tmp)&
    done      #iterate
    
    wait      #wait until all ready
    
    sort $tmp | grep -v ':0'  #... handle as required
    
    0 讨论(0)
  • 2020-11-22 04:29

    This is something that I use:

    #wait for jobs
    for job in `jobs -p`; do wait ${job}; done
    
    0 讨论(0)
  • 2020-11-22 04:30

    How about simply:

    #!/bin/bash
    
    pids=""
    
    for i in `seq 0 9`; do
       doCalculations $i &
       pids="$pids $!"
    done
    
    wait $pids
    
    ...code continued here ...
    

    Update:

    As pointed by multiple commenters, the above waits for all processes to be completed before continuing, but does not exit and fail if one of them fails, it can be made to do with the following modification suggested by @Bryan, @SamBrightman, and others:

    #!/bin/bash
    
    pids=""
    RESULT=0
    
    
    for i in `seq 0 9`; do
       doCalculations $i &
       pids="$pids $!"
    done
    
    for pid in $pids; do
        wait $pid || let "RESULT=1"
    done
    
    if [ "$RESULT" == "1" ];
        then
           exit 1
    fi
    
    ...code continued here ...
    
    0 讨论(0)
  • 2020-11-22 04:32

    I don't believe it's possible with Bash's builtin functionality.

    You can get notification when a child exits:

    #!/bin/sh
    set -o monitor        # enable script job control
    trap 'echo "child died"' CHLD
    

    However there's no apparent way to get the child's exit status in the signal handler.

    Getting that child status is usually the job of the wait family of functions in the lower level POSIX APIs. Unfortunately Bash's support for that is limited - you can wait for one specific child process (and get its exit status) or you can wait for all of them, and always get a 0 result.

    What it appears impossible to do is the equivalent of waitpid(-1), which blocks until any child process returns.

    0 讨论(0)
提交回复
热议问题