How to start at the same time but exit 1 if any of them fail?

I have the following sh file:

#!/usr/bin/env bash
ecs deploy [some not relevant stuff here] & \
ecs deploy [some not relevant stuff here] & \
ecs deploy [some not relevant stuff here] & \
ecs deploy [some not relevant stuff here] & \
ecs deploy [some not relevant stuff here] & \
ecs deploy [some not relevant stuff here]

      

This works in part because it runs the deployment commands at the same time, but I have to return the appropriate exit code if any of the deployment completion code is greater than 0.

Is there a way to do this with bash only? If possible, without using any tmp files, just variables.

+3


source to share


4 answers


It is not clear why you need the largest exit code; without further information, I would assume that you just want to return a non-zero exit code if any of the other processes have a non-zero exit code.



ecs deploy [some not relevant stuff here] & pids+=($!)
ecs deploy [some not relevant stuff here] & pids+=($!)
ecs deploy [some not relevant stuff here] & pids+=($!)
ecs deploy [some not relevant stuff here] & pids+=($!)
ecs deploy [some not relevant stuff here] & pids+=($!)
ecs deploy [some not relevant stuff here] & pids+=($!)

rv=0
for pid in "${pids[@]}"; do
  wait "$pid" || rv=1
done
exit "$rv"

      

+4


source


First of all, for managing subprocesses, I would recommend switching to python, as it has several modules that just do it better than anything you can ever write with bash.

There are many OK answers here, but I would do it.

#!/bin/bash

sleep 4; /bin/false &
pids+=("$!")
sleep 5 &
pids+=("$!")
sleep 5 &
pids+=("$!")
sleep 5 &
pids+=("$!")
sleep 5 &
pids+=("$!")

declare -A -g exit_tracker=()

rc=0
for pid in ${pids[@]}; do
    wait $pid
    if (( $? == 1 )); then
        exit_tracker[$pid]="FAIL"
    else
        exit_tracker[$pid]="SUCCESS"
    fi
done

for key in ${!exit_tracker[@]}; do
    printf "%s\n" "$key PID STATUS: ${exit_tracker[$key]}"
done

      

IF YOU WANT TO GET A SPIRITUAL CRYER! ... You can call each return code an associative array and figure out which pid failed. You can add your own names where you see sleep_fail, sleep_pass_1, etc.



#!/bin/bash

declare -A -g pid_names=()

sleep 4; /bin/false &
pid_names["sleep_fail"]="$!"
sleep 5 &
pid_names["sleep_pass_1"]="$!"
sleep 5 &
pid_names["sleep_pass_2"]="$!"
sleep 5 &
pid_names["sleep_pass_3"]="$!"
sleep 5 &
pid_names["sleep_pass_4"]="$!"

declare -A -g exit_tracker=()

rc=0
for pid in ${!pid_names[@]}; do
    wait ${pid_names[$pid]}
    if (( $? == 1 )); then
        exit_tracker[$pid]="FAIL"
    else
        exit_tracker[$pid]="SUCCESS"
    fi
done

for key in ${!exit_tracker[@]}; do
    printf "%s\n" "$key PID STATUS: ${exit_tracker[$key]}"
done

      

The output from the above would look like this:

dumbledore@ansible1a [OPS]:~ > bash test.sh
sleep_fail PID STATUS: FAIL
sleep_pass_4 PID STATUS: SUCCESS
sleep_pass_2 PID STATUS: SUCCESS
sleep_pass_3 PID STATUS: SUCCESS
sleep_pass_1 PID STATUS: SUCCESS

      

+1


source


# note normal single quotes in following line
CMD='curl -I shoudfail.com'

# run the command, and log it IF IT FAILS
( $CMD || echo $CMD >> tmpout ) &

# rinse, lather, repeat
CMD='curl -I somecmdthatwillfail.com'

# run the command, and log it IF IT FAILS
( $CMD || echo $CMD >> tmpout ) &

...

while [ ! -z `jobs` ]  
do
   sleep 5
done

      

If you are using readline to populate the CMD rather than literals in your code, then you can use the output of one iteration as input to the next.

0


source


#!/usr/bin/env bash
# This array will store process ID of background processes
declare -a pid

# Run curl and save add its pid to array
curl -I shoudfail.com; echo $? >> tmpout &
pid+=( $! )

# Run another curl and save add its pid to array
curl -I somecmdthatwillfail.com a; echo $? >> tmpout & \
pid+=( $! )

# Run a third curl and save add its pid to array
curl -I google.com; echo $? >> tmpout;
pid+=( $! )

# Wait for all background processes to stop
wait

# Loop through array of pids
for proc in "${pid[@]}"; do
    # Get return value of process from wait
    wait "$proc"
    retval=$?

    # Replace maxret if the return value is larger
    [ "$retval" -gt "$maxret" ] && maxret="$retval"

done

echo "$maxret"

      

0


source







All Articles