I have several jobs that require running at least once a day. What I do is start the scripts for these jobs every hour (or more often) and the scripts themselve check if they have already run by checking a status file on disc.
If the status file exists and is up-to-date then the script exits.
If that file is to old (i.e. last written the day before) or doesn't exists the script does run and on successful termination writes the status file.
If you cannot build this functionality into an existing program, it is simple to make wrapper script that checks if the program must run, calls the program if necessary, and on success (exit value, parsed output) writes the status file.
#! /usr/bin/env python
first parameter is a path to a file /..../daily/some_name
That is a status/script file and the /daily/ indicates it needs to run at least
once a day (after reboot, after midnight).
The rest of the parameters is the command executed and its parameters.
If there are no more parameters beyond the first the actual status
file is /..../daily/some_name.status and is expected to be updated by calling
the /....daily/some_name script (which has to be executable). That
script doesn't need to know about the frequency and gets called with
the status file as first (and only) argument.
Valid directory names and their functioning:
/daily/ run once a day (UTC)
/hourly/ run once an hour
The actual scheduling and frequency to check if running is necessary, is
done using a crontab entry:
# month, hour, day_of_month, month day_of_week command
*/5 * * * * $CU $CUD/daily/getlogs curl ....
If mulitple days (or hours) have gone by, no runs are made for skipped
If subprocess.check_output() fails the status file is not updated.
verbose = False # set to True to debug
if len(sys.argv) < 2:
print 'not enough parameters for', sys.argv
if len(sys.argv) == 2:
status_file_name = sys.argv + '.status'
cmd = [sys.argv]
status_file_name = sys.argv
cmd = sys.argv[2:]
freq = sys.argv.rsplit('/', 2)[-2]
print 'cmd', cmd
print 'status', status_file_name
print 'frequency', freq
last_status = datetime.datetime.strptime(
except (IOError, ValueError):
last_status = datetime.datetime(2000, 1, 1)
now = datetime.datetime.utcnow().replace(microsecond=0)
print 'now', now.isoformat()
if freq == 'daily':
if last_status.date() < now.date():
print 'already done today'
elif freq == 'hourly':
if last_status.date() < now.date() or \
last_status.date() == now.date() and \
last_status.hour < now.hour:
print 'already done this hour'
with open(status_file_name, 'w') as fp:
if __name__ == "__main__":