Skip to content

Instantly share code, notes, and snippets.

@vsemionov
Created February 7, 2024 04:55
Show Gist options
  • Save vsemionov/95bdaec858abf02caa53ad37689c6d02 to your computer and use it in GitHub Desktop.
Save vsemionov/95bdaec858abf02caa53ad37689c6d02 to your computer and use it in GitHub Desktop.
Cron in one screenful of Python
#!/usr/bin/env python
import os
import sys
import time
from crontab import CronTab
def main():
assert len(sys.argv) == 2, 'Usage: cron.py <filename>'
get_next_run = lambda tab, last_run: last_run + tab.next(last_run, default_utc=True)
entries: list[tuple[CronTab, str, float]] = []
now = time.time()
with open(sys.argv[1]) as f:
for idx, line in enumerate(f):
line = line.strip()
if not line or line.startswith('#'):
continue
fields = line.split(maxsplit=5)
assert len(fields) == 6, f'Invalid entry on line {idx + 1}.'
timespec, command = ' '.join(fields[:5]), fields[5]
tab = CronTab(timespec)
next_run = get_next_run(tab, now)
entries.append((tab, command, next_run))
while True:
for idx, (tab, command, next_run) in enumerate(entries):
now = time.time()
if next_run <= now:
os.system(command)
next_run = get_next_run(tab, now)
entries[idx] = (tab, command, next_run)
now = time.time()
delay = min(next_run - now for _, _, next_run in entries)
delay = min(max(delay, 0), 60)
time.sleep(delay)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment