Home

Awesome

recur

recur is a command-line tool that runs a single command repeatedly until it succeeds or no more attempts are left. It implements optional exponential backoff with configurable jitter. It lets you write the success condition in Starlark.

Requirements

Installation

Install Go, then run the following command:

go install github.com/dbohdan/recur@latest

Usage

Usage: recur [-a <attempts>] [-b <backoff>] [-c <condition>] [-d <delay>] [-f]
[-j <jitter>] [-m <max-delay>] [-t <timeout>] [-v] <command> [<arg> ...]

Retry a command with exponential backoff and jitter.

Arguments:
  <command>
  Command to run.

  [<arg> ...]
  Arguments to the command.

Flags:
  -h, --help
  Print this help message and exit.

  -V, --version
  Print version number and exit.

  -a, --attempts 10
  Maximum number of attempts (negative for infinite).

  -b, --backoff 0
  Base for exponential backoff (duration).

  -c, --condition "code == 0"
  Success condition (Starlark expression).

  -d, --delay 0
  Constant delay (duration).

  -f, --forever
  Infinite attempts.

  -j, --jitter "0,0"
  Additional random delay (maximum duration or 'min,max' duration).

  -m, --max-delay 1h
  Maximum allowed sum of constant delay and exponential backoff (duration).

  -t, --timeout -1s
  Timeout for each attempt (duration; negative for no timeout).

  -v, --verbose
  Increase verbosity (up to 3 times).

The "duration" arguments take Go duration strings; for example, 0, 100ms, 2.5s, 0.5m, or 1h. The value of -j/--jitter must be either one duration string or two joined with a comma, like 1s,2s.

Setting the delay (-d/--delay) increases the maximum delay (-m/--max-delay) to that value when the maximum delay is shorter. Use -m/--max-delay after -d/--delay if you want a shorter maximum delay.

recur exits with the last command's exit code unless the user overrides this in the condition. When the command is not found during the last attempt, recur exits with the code 255.

Conditions

recur supports a limited form of scripting. You can define the success condition using an expression in Starlark, a small scripting language derived from Python. The default condition is code == 0. It means recur will stop retrying when the exit code of the command is zero.

If you know Python, you can quickly start writing recur conditions in Starlark. The most significant differences between Starlark and Python for this purpose are:

You can use the following variables in the condition expression:

recur defines one custom function:

This function allows you to override the default behavior of returning the last command's exit code. For example, you can make recur exit with success when the command fails.

recur --condition 'code != 0 and exit(0)' sh -c 'exit 1'
# or
recur --condition 'False if code == 0 else exit(0)' sh -c 'exit 1'

In the following example we stop early and do not retry when the command's exit code indicates incorrect usage or a problem with the installation.

recur --condition 'code == 0 or (code in (1, 2, 3, 4) and exit(code))' curl "$url"

License

MIT.

Alternatives

recur was inspired by retry-cli. I wanted something like retry-cli but without the Node.js dependency.

There are other similar tools: