#!/usr/bin/python # # do-until - run a command until it succeeds # Copyright (C) 2008, 2011 Lars Wirzenius # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . '''Run a command until it succeeds.''' import cliapp import subprocess import sys import time class DoUntil(cliapp.Application): def add_settings(self): self.settings.boolean(['no-act', 'n'], 'Do not run command, just pretend to do it, ' 'and pretend that it succeeds.') self.settings.boolean(['verbose', 'v'], 'Print command before executing it.') self.settings.integer(['sleep'], 'Wait SECS seconds before re-trying a command. ' '(Default is %default.)', default=1) self.settings.integer(['max-tries'], 'Try at most COUNT times, with 0 meaning forever. ' '(Default is %default.)', default=0) def process_args(self, argv): tries = 0 max_tries = self.settings['max-tries'] while max_tries == 0 or tries < max_tries: tries += 1 if self.settings['verbose']: sys.stderr.write('do-until: attempt #%d: %s\n' % (tries, ' '.join(argv))) if self.settings['no-act']: sys.stderr.write('do-until: not running command, ' 'pretending it works anyway\n') break else: p = subprocess.Popen(argv) p.communicate() if p.returncode == 0: break sys.stderr.write('do-until: attempt %d failed, ' 'trying again in %d second(s)\n' % (tries, self.settings['sleep'])) time.sleep(self.settings['sleep']) if __name__ == '__main__': DoUntil().run()