#!/bin/bash cmd="" timeoutSeconds=60 sleepSeconds=1 message="" messageInterval=5 startTimeSeconds=$(date +%s) elapsedSeconds=0 attempts=0 print_usage() { echo "Usage: $0 [options] " echo echo "Attempts to execute a given command periodically until it succeeds or a timeout occurs." echo echo "Options:" echo " -t, --timeout The maximum number of seconds to wait for the command to succeed (default: 60)" echo " -s, --sleep The number of seconds to sleep for between command attempts (default: 1)" echo " -m, --message The progress message to print after every attempt (default: '')" echo " Instances of {{elapsed}} and {{attempts}} in the message will be replaced by total" echo " elapsed time (in seconds) and total attempts respectively." echo " -i, --message-interval The number of command attempts to make before each printing of the progress message" echo " (default: 5)." echo " -e, --exit-command Optional command to run before exiting (default: '')" echo } print_progress() { if [ -n "$message" ]; then echo "$message" | sed "s/{{attempts}}/$attempts/g; s/{{elapsed}}/$elapsedSeconds/g" fi } # Parse options and arguments while [[ $# -gt 0 ]]; do case "$1" in -t | --timeout) shift timeoutSeconds="$1" ;; -s | --sleep) shift sleepSeconds="$1" ;; -m | --message) shift message="$1" ;; -i | --message-interval) shift messageInterval="$1" ;; -e | --exit-command) shift exitCommand="$1" ;; *) cmd="$@" break ;; esac shift done # Error if no command was provided if [ -z "$cmd" ]; then print_usage exit 1 fi # Loop until either the command succeeds or a timeout occurs. until [ "$elapsedSeconds" -gt "$timeoutSeconds" ] || eval "$cmd"; do sleep "$sleepSeconds" # Increment attempt counter. If we've hit the message interval, print the message attempts=$((attempts + 1)) if [ $((attempts % messageInterval)) -eq 0 ]; then print_progress fi # Recalculate $elapsedSeconds currentTimeSeconds=$(date +%s) elapsedSeconds=$((currentTimeSeconds - startTimeSeconds)) done # If we timed out, print the final progress message and exit with code 1. if [ "$elapsedSeconds" -gt "$timeoutSeconds" ]; then print_progress if [ -n "$exitCommand" ]; then eval "$exitCommand" fi exit 1 fi