Skip to content

Instantly share code, notes, and snippets.

@Feuermurmel
Created April 3, 2015 23:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Feuermurmel/3113d4fcc3d93b62549c to your computer and use it in GitHub Desktop.
Save Feuermurmel/3113d4fcc3d93b62549c to your computer and use it in GitHub Desktop.
retry.py
#! /usr/bin/env python3
import sys, os, argparse, subprocess, time
class UserError(Exception):
def __init__(self, msg, *args):
super().__init__(msg.format(*args))
def log(msg, *args):
print('{}: {}'.format(os.path.basename(sys.argv[0]), msg.format(*args)), file = sys.stderr)
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('command', nargs = argparse.REMAINDER, help = 'Command to execute.')
parser.add_argument('-i', '--min-interval', type = float, default = 10, help = 'Minimum time in seconds since the command has been started the last time before it is started again. Defaults to 10 seconds.')
parser.add_argument('-w', '--min-wait', type = float, default = 0, help = 'Minimum time in seconds after the command has terminated before it is started again. Defaults to no wait time.')
parser.add_argument('-r', '--restart-always', action = 'store_const', dest = 'restart', const = 'always', help = 'Restart the command whether it completes successfully or with a failure. By default, the command is only restarted until it succeeds.')
parser.add_argument('-R', '--restart-on-success', action = 'store_const', dest = 'restart', const = 'success', help = 'Restart the command as long as it succeeds.')
return parser.parse_args()
def main():
args = parse_args()
start_time = 0
min_wait = 0
while True:
current_time = time.time()
start_time = max(start_time + args.min_interval, current_time + min_wait)
wait_time = start_time - current_time
if wait_time > 0:
log('Waiting {:.1f} seconds before restarting the command.', wait_time)
time.sleep(wait_time)
else:
start_time = current_time
process = subprocess.Popen(args.command)
process.wait()
if process.returncode:
log('Process exited with status {}.', process.returncode)
if args.restart == 'success':
raise UserError('Command failed with exit code {}.', process.returncode)
else:
if not args.restart:
break
min_wait = args.min_wait
try:
main()
except UserError as e:
log('Error: {}', e)
sys.exit(1)
except KeyboardInterrupt:
log('Operation interrupted.')
sys.exit(2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment