Skip to content

Instantly share code, notes, and snippets.

@cGuille
Created March 20, 2024 14:21
Show Gist options
  • Save cGuille/b9100a6303a1a7bd36908e361645e3de to your computer and use it in GitHub Desktop.
Save cGuille/b9100a6303a1a7bd36908e361645e3de to your computer and use it in GitHub Desktop.
A Bash command to keep trying running a command until it succeeds or is canceled.
#!/usr/bin/env bash
set -eu
COLOR_ERROR='\033[0;31m'
COLOR_RESET='\e[0m'
prog_name="$(basename "$0")"
function usage() {
if [[ ${1:-} = '--with-desc' ]]
then
>&2 echo 'Run a given command until it succeeds or is cancelled.'
fi
>&2 cat <<USG
Usage:
${prog_name} [-d|--debug] [-c|--clear] [-e|--redirect-stderr DEST] [-b|--backoff BACKOFF] [--] COMMAND ARGS
USG
exit
}
function unexpected_arg() {
>&2 echo -e "${COLOR_ERROR}Error: unexpected argument '$1'.${COLOR_RESET}"
usage
}
backoff=1s
debug_mode=off
clear_mode=off
cmd_stderr=/dev/stderr
while [[ $# -gt 0 ]]
do
case "$1" in
-h|--help)
usage --with-desc
;;
-b|--backoff)
shift # flag
backoff="${1:-}"
shift # value
;;
-c|--clear)
shift # flag
clear_mode=on
;;
-d|--debug)
shift # flag
debug_mode=on
;;
-e|--redirect-stderr)
shift # flag
cmd_stderr="${1:-}"
shift # value
;;
--)
shift
break
;;
-*)
unexpected_arg "$1"
;;
*)
break
;;
esac
done
debug() {
if [[ $debug_mode = on ]]
then
>&2 echo "$@"
fi
}
cmd="${1:-}"
if [[ $cmd = '' ]]
then
>&2 echo -e "${COLOR_ERROR}Error: no command provided.${COLOR_RESET}"
usage
fi
shift
EXIT_SUCCESS=0
EXIT_CMD_NOT_FOUND=127
EXIT_CANCEL=130
while true
do
if [[ $clear_mode = on ]]
then
clear
fi
debug "Running command:" "$cmd" "$@"
set +e
"$cmd" "$@" 2> "$cmd_stderr"
exit_code=$?
set -e
debug -n "Command exited with: $exit_code."
if [[ $exit_code = $EXIT_SUCCESS || $exit_code = $EXIT_CMD_NOT_FOUND || $exit_code = $EXIT_CANCEL ]]
then
debug ''
exit $exit_code
fi
debug " Waiting $backoff before retry…"
sleep "$backoff"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment