Skip to main content
added 587 characters in body
Source Link
ilkkachu
  • 147.9k
  • 16
  • 268
  • 441

Of course, we need a loop to repeat running the program. (This isAn alternative to command substitution would be to use a bit uglytemporary file to store the error output and could possibly be made prettierlook into it afterwards.) This makes it easier to have the standard output of the command visible, too, so let's do that:

#!/bin/bash
re="known error message$"

retries=0
max_retries=5
while errormsg=$errorfile=$(mktemp)                       # temp file for the errors
trap 'rm "$errorfile"' EXIT               # remove the temp file on exit

while cmd "$@" 2>&12> >/dev/null"$errorfile"; )          # run the command
      ret=$?;                             # save the exit code
      [[ $errormsg$( < $errorfile ) =~ $re ]]; do  # check the output
    cat "$errorfile" >&2                  # print the errors to
                                          # the script's stderr, too

    retries=$((retries+1))                # retry a couple of times
    echo -n "cmd failed with known message"
    if [[ $retries -lt $max_retries ]]; then
        echo ", retrying."
    else
        echo ", exit."
        exit 1
    fi
done
cat "$errorfile" >&2
echo "cmd completed succesfully";with status $ret";    # use saved exit code, since it might
exit "$ret"                               # have failed for other reasons

(while cmd1; cmd2; do ... runs cmd1 at the very start, then runs cmd2 as the loop condition.)

An alternative would be to use a temporary file to store the error output and look into it afterwards. This would make it easier to have the standard output of the command visible, too.

Of course, we need a loop to repeat running the program. (This is a bit ugly and could possibly be made prettier.)

#!/bin/bash
re="known error message$"

retries=0
max_retries=5
while errormsg=$( cmd "$@" 2>&1 >/dev/null );
      [[ $errormsg =~ $re ]]; do
    retries=$((retries+1))
    echo -n "cmd failed with known message"
    if [[ $retries -lt $max_retries ]]; then
        echo ", retrying."
    else
        echo ", exit."
        exit 1
    fi
done
echo "cmd completed succesfully";

(while cmd1; cmd2; do ... runs cmd1 at the very start, then runs cmd2 as the loop condition.)

An alternative would be to use a temporary file to store the error output and look into it afterwards. This would make it easier to have the standard output of the command visible, too.

Of course, we need a loop to repeat running the program. An alternative to command substitution would be to use a temporary file to store the error output and look into it afterwards. This makes it easier to have the standard output of the command visible, too, so let's do that:

#!/bin/bash
re="known error message$"

retries=0
max_retries=5
errorfile=$(mktemp)                       # temp file for the errors
trap 'rm "$errorfile"' EXIT               # remove the temp file on exit

while cmd "$@" 2> "$errorfile";           # run the command
      ret=$?;                             # save the exit code
      [[ $( < $errorfile ) =~ $re ]]; do  # check the output
    cat "$errorfile" >&2                  # print the errors to
                                          # the script's stderr, too

    retries=$((retries+1))                # retry a couple of times
    echo -n "cmd failed with known message"
    if [[ $retries -lt $max_retries ]]; then
        echo ", retrying."
    else
        echo ", exit."
        exit 1
    fi
done
cat "$errorfile" >&2
echo "cmd completed with status $ret";    # use saved exit code, since it might
exit "$ret"                               # have failed for other reasons

(while cmd1; cmd2; do ... runs cmd1 at the very start, then runs cmd2 as the loop condition.)

Source Link
ilkkachu
  • 147.9k
  • 16
  • 268
  • 441

We'll need to capture the output of the command then. It's easiest if we can capture all of it (or just ignore the standard output):

#!/bin/bash
errormsg=$( cmd "$@" 2>&1 >/dev/null )
re="known error message$"
if [[ $errormsg =~ $re ]]; then
    echo "cmd failed with known message
fi

The command substitution $(..) and the redirections within it capture the standard error output of the command, and redirect the non-error output to /dev/null. Then we compare that against a regular expression, where the $ at the end signifies the end of the string. (The command substitution removes all trailing newlines, so the regex doesn't need to match those.) "$@" expands to the script's arguments, passing them as arguments to cmd.

Of course, we need a loop to repeat running the program. (This is a bit ugly and could possibly be made prettier.)

#!/bin/bash
re="known error message$"

retries=0
max_retries=5
while errormsg=$( cmd "$@" 2>&1 >/dev/null );
      [[ $errormsg =~ $re ]]; do
    retries=$((retries+1))
    echo -n "cmd failed with known message"
    if [[ $retries -lt $max_retries ]]; then
        echo ", retrying."
    else
        echo ", exit."
        exit 1
    fi
done
echo "cmd completed succesfully";

(while cmd1; cmd2; do ... runs cmd1 at the very start, then runs cmd2 as the loop condition.)

An alternative would be to use a temporary file to store the error output and look into it afterwards. This would make it easier to have the standard output of the command visible, too.

In the above, I ignored the actual exit status of the command and looked just at the output. You'll need to change the script if you want to take the exit status into account.