#!/usr/bin/python # Copyright 2013 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 . import cliapp import time import sys import yaml __version__ = '0.0' class DesktopCronish(cliapp.Application): def add_settings(self): self.settings.integer( ['max-jobs'], 'run at least N jobs, then quit (use 0 for infinite)', metavar='N', default=0) def process_args(self, args): self.jobs = {} self.previously = {} self.process_inputs(args) self.execute_jobs() def process_input(self, filename): with self.open_input(filename, 'r') as f: job_dict = yaml.safe_load(f) self.jobs.update(job_dict) def execute_jobs(self): n = 0 max_jobs = self.settings['max-jobs'] while max_jobs == 0 or n < max_jobs: job_name, when = self.choose_job() self.wait_until(when) self.execute_job(job_name) n += 1 def choose_job(self): next_job_name = None next_when = 0 for job_name, job in self.jobs.items(): job_when = self.previously.get(job_name, 0) + job['interval'] if next_job_name is None or job_when <= next_when: next_job_name = job_name next_when = job_when return next_job_name, next_when def wait_until(self, when): while self.now() < when: time.sleep(when - self.now()) def execute_job(self, job_name): job = self.jobs[job_name] argv = ['sh', '-c', job['command']] if 'timeout' in job: argv = ['timeout', str(job['timeout'])] + argv exit, out, err = cliapp.runcmd_unchecked(argv) self.output.write(out) if exit != 0: sys.stderr.write( 'ERROR: Job %s: Command failed: %s\n' % (job_name, ' '.join(argv))) sys.stderr.write(err) self.previously[job_name] = self.now() def now(self): return time.time() DesktopCronish(version=__version__).run()