git / moonbite-core / ci/retry/retry · raw

#!/usr/bin/env bashGETOPT_BIN=$IN_GETOPT_BINGETOPT_BIN=${GETOPT_BIN:-getopt}__sleep_amount() {  if [ -n "$constant_sleep" ]; then    sleep_time=$constant_sleep  else    #TODO: check for awk    #TODO: check if user would rather use one of the other possible dependencies: python, ruby, bc, dc    sleep_time=`awk "BEGIN {t = $min_sleep * $(( (1<<($attempts -1)) )); print (t > $max_sleep ? $max_sleep : t)}"`  fi}__log_out() {  echo "$1" 1>&2}# Parameters: max_tries min_sleep max_sleep constant_sleep fail_script EXECUTION_COMMANDretry(){  local max_tries="$1"; shift  local min_sleep="$1"; shift  local max_sleep="$1"; shift  local constant_sleep="$1"; shift  local fail_script="$1"; shift  if [ -n "$VERBOSE" ]; then    __log_out "Retry Parameters: max_tries=$max_tries min_sleep=$min_sleep max_sleep=$max_sleep constant_sleep=$constant_sleep"    if [ -n "$fail_script" ]; then __log_out "Fail script: $fail_script"; fi    __log_out ""    __log_out "Execution Command: $*"    __log_out ""  fi  local attempts=0  local return_code=1  while [[ $return_code -ne 0 && $attempts -le $max_tries ]]; do    if [ $attempts -gt 0 ]; then      __sleep_amount      __log_out "Before retry #$attempts: sleeping $sleep_time seconds"      sleep $sleep_time    fi    P="$1"    for param in "${@:2}"; do P="$P '$param'"; done    #TODO: replace single quotes in each arg with '"'"' ?    export RETRY_ATTEMPT=$attempts    bash -c "$P"    return_code=$?    #__log_out "Process returned $return_code on attempt $attempts"    if [ $return_code -eq 127 ]; then      # command not found      exit $return_code    elif [ $return_code -ne 0 ]; then      attempts=$[$attempts +1]    fi  done  if [ $attempts -gt $max_tries ]; then    if [ -n "$fail_script" ]; then      __log_out "Retries exhausted, running fail script"      eval $fail_script    else      __log_out "Retries exhausted"    fi  fi  exit $return_code}# If we're being sourced, don't worry about such thingsif [ "$BASH_SOURCE" == "$0" ]; then  # Prints the help text  help()  {    local retry=$(basename $0)    cat <<EOFUsage: $retry [options] -- execute command    -h, -?, --help    -v, --verbose                    Verbose output    -t, --tries=#                    Set max retries: Default 10    -s, --sleep=secs                 Constant sleep amount (seconds)    -m, --min=secs                   Exponential Backoff: minimum sleep amount (seconds): Default 0.3    -x, --max=secs                   Exponential Backoff: maximum sleep amount (seconds): Default 60    -f, --fail="script +cmds"        Fail Script: run in case of final failureEOF  }  # show help for no arguments if stdin is a terminal  if { [ -z "$1" ] && [ -t 0 ] ; } || [ "$1" == '-h' ] || [ "$1" == '-?' ] || [ "$1" == '--help' ]  then    help    exit 0  fi  $GETOPT_BIN --test > /dev/null  if [[ $? -ne 4 ]]; then      echo "I’m sorry, 'getopt --test' failed in this environment. Please load GNU getopt."      exit 1  fi  OPTIONS=vt:s:m:x:f:  LONGOPTIONS=verbose,tries:,sleep:,min:,max:,fail:  PARSED=$($GETOPT_BIN --options="$OPTIONS" --longoptions="$LONGOPTIONS" --name "$0" -- "$@")  if [[ $? -ne 0 ]]; then    # e.g. $? == 1    #  then getopt has complained about wrong arguments to stdout    exit 2  fi  # read getopt’s output this way to handle the quoting right:  eval set -- "$PARSED"  max_tries=10  min_sleep=0.3  max_sleep=60.0  constant_sleep=  fail_script=  # now enjoy the options in order and nicely split until we see --  while true; do      case "$1" in          -v|--verbose)              VERBOSE=true              shift              ;;          -t|--tries)              max_tries="$2"              shift 2              ;;          -s|--sleep)              constant_sleep="$2"              shift 2              ;;          -m|--min)              min_sleep="$2"              shift 2              ;;          -x|--max)              max_sleep="$2"              shift 2              ;;          -f|--fail)              fail_script="$2"              shift 2              ;;          --)              shift              break              ;;          *)              echo "Programming error"              exit 3              ;;      esac  done  retry "$max_tries" "$min_sleep" "$max_sleep" "$constant_sleep" "$fail_script" "$@"fi