Skip to content

Instantly share code, notes, and snippets.

@garymacindoe
Created February 1, 2018 17:02
Show Gist options
  • Save garymacindoe/b6363d5e60900bb53cd7a9b0ae862958 to your computer and use it in GitHub Desktop.
Save garymacindoe/b6363d5e60900bb53cd7a9b0ae862958 to your computer and use it in GitHub Desktop.
Run a command with exponential backoff, stopping when the command exits with a certain status and (optionally) outputs a specified string
#!/bin/bash
args=$(getopt n:t:r:o: ${*})
if [ $? -ne 0 ] || [ $# -lt 1 ]
then
echo "Usage: ${0} [-n=<max-attempts>] [-t=<initial-timeout>] [-r=0] [-o=<output>] <command> <args...>"
echo "Runs <command> with <args> a maximum of <max-attempts> times until it succeeds. \"Succeeds\" is"
echo "defined as returning <r> to the shell (default 0) and printing <output> to the console."
echo "Waits <initial-timeout> between the first and second attempts, and doubles the timeout each time"
echo "the command is run"
exit 2
fi
set -- ${args}
max_attempts=5
timeout=1
output=
return_code=0
for i
do
case "$i" in
-n)
max_attempts="${2}"; shift; shift;;
-t)
timeout="${2}"; shift; shift;;
-r)
return_code="${2}"; shift; shift;;
-o)
output="${2}"; shift; shift;;
--)
shift; break;;
esac
done
attempt=0
ret=0
while [[ ${attempt} < ${max_attempts} ]]
do
out=$("${@}")
ret=$?
if [[ ${ret} == ${return_code} && ( -z ${output} || ${out} = ${output} ) ]]
then
break
fi
sleep ${timeout}
attempt=$((attempt + 1))
timeout=$((timeout * 2))
done
echo "${out}"
exit ${ret}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment