#!/usr/bin/python3 # # 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()