Backoff exponencial no Bash

Já precisou baixar dez mil arquivos em um script? Escrever loops no shell é fácil, mas lidar com falhas intermitentes pode ser menos.

Uma técnica padrão é o backoff exponencial. Lá, dorme-se entre as tentativas, com cada duração do sono crescendo em algum esquema (geralmente geometricamente) conforme mais tentativas são necessárias. Este padrão pode ser extraído em um snippet reutilizável:

# Retries a command a with backoff.
#
# The retry count is given by ATTEMPTS (default 5), the
# initial backoff timeout is given by TIMEOUT in seconds
# (default 1.)
#
# Successive backoffs double the timeout.
#
# Beware of set -e killing your whole script!
function with_backoff {
local max_attempts=${ATTEMPTS-5}
local timeout=${TIMEOUT-1}
local attempt=0
local exitCode=0

while [[ $attempt < $max_attempts ]]
do
"$@"
exitCode
=$?

if [[ $exitCode == 0 ]]
then
break
fi

echo
"Failure! Retrying in $timeout.." 1>&2
sleep $timeout

attempt
=$(( attempt + 1 ))
timeout
=$(( timeout * 2 ))
done

if [[ $exitCode != 0 ]]
then
echo
"You've failed me for the last time! ($@)" 1>&2
fi

return $exitCode
}

Observe que a maioria das implementações do bash usa aritmética de inteiros, portanto, os tempos de sono são dobrados a cada passagem. Aqui está um exemplo de uso:

with_backoff curl 'http://monkeyfeathers.example.com/'

Postado novamente de SO: http://stackoverflow.com/a/8351489/580412