A bash retry loop

February 24, 2019
bash

Every now and then you’ll find yourself writing a script with a step that does not always work first time: perhaps a remote service is temporarily down, or a DNS lookup fails intermittently. One strategy for dealing with this is simply to keep trying the command until it succeeds or you decide you’ve tried too many times and give up.

The following snippet implements a simple retry loop in bash:

declare -i N=1
while ! /usr/local/bin/some-command
do
    if [[ $N -lt 6 ]]
    then
        (( N++ ))
        sleep 5
    else
        echo "Failed to run some-command after $N attempts" >&2
        exit 3
    fi
done

When I first wrote this, I initialized the counter N to zero, but the script failed unexpectedly in the retry loop when run with the set -e option. It was the (( N++ )) expression that caused the script to abort and after some head scratching and further reading of the bash manual I found:

((expression))

The expression is evaluated according to the rules described below under ARITHMETIC EVALUATION. If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1.

Do you see the problem? If you start with N=0 then N++ increments N to 1 but, as it’s a post-increment operator, the value of the expression is the initial value of N, in this case 0. So the return status is 1, causing set -e to abort the script.

Migrating from count to for_each

Updating a Terraform manifest to the new for_each loop construct
terraform devops bash