Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Bash retry function
# Retry a command up to a specific numer of times until it exits successfully,
# with exponential back off.
#
# $ retry 5 echo Hello
# Hello
#
# $ retry 5 false
# Retry 1/5 exited 1, retrying in 1 seconds...
# Retry 2/5 exited 1, retrying in 2 seconds...
# Retry 3/5 exited 1, retrying in 4 seconds...
# Retry 4/5 exited 1, retrying in 8 seconds...
# Retry 5/5 exited 1, no more retries left.
#
function retry {
local retries=$1
shift
local count=0
until "$@"; do
exit=$?
wait=$((2 ** $count))
count=$(($count + 1))
if [ $count -lt $retries ]; then
echo "Retry $count/$retries exited $exit, retrying in $wait seconds..."
sleep $wait
else
echo "Retry $count/$retries exited $exit, no more retries left."
return $exit
fi
done
return 0
}
@ronronshaiko

This comment has been minimized.

Copy link

@ronronshaiko ronronshaiko commented Sep 5, 2019

Great function !! thanks

@hughsaunders

This comment has been minimized.

Copy link

@hughsaunders hughsaunders commented Oct 8, 2019

Thanks, going to include this in https://github.com/cyberark/bash-lib, hope you don't mind :)

@gtarnaras

This comment has been minimized.

Copy link

@gtarnaras gtarnaras commented Oct 16, 2019

Thanks for sharing!

@hunter-richardson

This comment has been minimized.

Copy link

@hunter-richardson hunter-richardson commented Oct 16, 2019

Translated to fish (using printf instead of echo) with the humanize_duration function:

#!/usr/bin/fish
function retry -d 'Retry a command up to a specified number of times, until it exits successfully'
  if test (count $argv) -lt 2; or string match -irqv '^[0-9]+$' $argv[1]
    printf 'Proper use: %s [number of attempts until giving up] [command to attempt]\n' (status function);
    return 23
  else
    set -l retries $argv[1]
    set -l command (string split -m 1 ' ' "$argv")[2];
      and printf 'eval %s\n' (printf '%s ' $command)
    for i in (seq $retries)
      eval $command
      set -l cmd_status $status
      if test $cmd_status -eq 0
        printf 'Try #%d of %d succeeded.\n' $i $retries
        return 0
      else if test $i -eq $retries
        set -l exit $status
        printf 'Final try #%d exited %d.\n' $i $cmd_status
        return $cmd_status
      else
        set -l wait (math "2 ^ ($i - 1)")
        printf 'Try #%d of %d exited %d, retrying in %s...\n\n' $i $retries $cmd_status (math "1000 * $wait" | humanize_duration)
        sleep $wait
      end
    end
  end
end

Available here.

Examples:

$ retry a echo Hello
Proper use: retry [number of attempts before giving up] [command to attempt]
#  exit code 23

$ retry 5
Proper use: retry [number of attempts before giving up] [command to attempt]
#  exit code 23

$ retry 8 false
eval false
Try #1 of 8 exited 1, retrying in 1s...
Try #2 of 8 exited 1, retrying in 2s...
Try #3 of 8 exited 1, retrying in 4s...
Try #4 of 8 exited 1, retrying in 8s...
Try #5 of 8 exited 1, retrying in 16s...
Try #6 of 8 exited 1, retrying in 32s...
Try #7 of 8 exited 1, retrying in 1m 4s...
Final try #8 exited 1.
#  exit code 1

$ retry 5 echo Hello
eval echo Hello
Hello
Try #1 of 5 succeeded.
#  exit code 0

$ retry 5 ping -n -1 -w 1 google.com
eval ping -n 1 -w 1 google.com

Pinging google.com [172.217.164.174] with 32 bytes of data:
Request timed out.

Ping statistics for 172.217.164.174:
    Packets: Send =1, Received = 0, Lost = 1 (100% loss),
Try #1 of 5 exited 1, retrying in 1s...

Pinging google.com [172.217.164.174] with 32 bytes of data:
Reply from 172.217.164.174:  bytes=32 time=30ms TTL=55

Ping statistics for 172.217.164.174:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss)
Approximate round trip times in milliseconds:
    Minimum = 30ms, Maximum = 30ms, Average = 30ms
Try #2 of 5 succeeded.
#  exit code 0
@ypid

This comment has been minimized.

Copy link

@ypid ypid commented Nov 17, 2019

Well done! I hope you don’t mind, I am using it in hashbang/aosp-build#8. I reworked it a bit so that it passes ShellCheck.

@valm13

This comment has been minimized.

Copy link

@valm13 valm13 commented May 27, 2021

Thanks, it's very useful and easy to use!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment