{"id":18221774,"url":"https://github.com/karlicoss/dron","last_synced_at":"2025-04-09T12:07:06.563Z","repository":{"id":52287864,"uuid":"236066875","full_name":"karlicoss/dron","owner":"karlicoss","description":"What if cron and systemd had a baby?","archived":false,"fork":false,"pushed_at":"2024-10-08T00:55:25.000Z","size":214,"stargazers_count":57,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T09:08:51.601Z","etag":null,"topics":["cron","dsl","launchd","literate-readme","python","systemd"],"latest_commit_sha":null,"homepage":"https://beepb00p.xyz/scheduler.html","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karlicoss.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-24T19:14:14.000Z","updated_at":"2024-10-08T00:41:26.000Z","dependencies_parsed_at":"2023-01-30T17:30:53.140Z","dependency_job_id":"0fc9c4d4-d4c9-49ad-8f70-055e472b4264","html_url":"https://github.com/karlicoss/dron","commit_stats":{"total_commits":157,"total_committers":1,"mean_commits":157.0,"dds":0.0,"last_synced_commit":"7b51e4c564e96266269311540e7a78921f675a6a"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karlicoss%2Fdron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karlicoss%2Fdron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karlicoss%2Fdron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karlicoss%2Fdron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karlicoss","download_url":"https://codeload.github.com/karlicoss/dron/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248036065,"owners_count":21037092,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","dsl","launchd","literate-readme","python","systemd"],"created_at":"2024-11-03T22:04:21.408Z","updated_at":"2025-04-09T12:07:06.545Z","avatar_url":"https://github.com/karlicoss.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+begin_src python :results drawer :exports results \nimport dron; return dron.make_parser().description\n#+end_src\n\n#+RESULTS:\n:results:\ndron -- simple frontend for Systemd, inspired by cron.\n\n- *d* stands for 'Systemd'\n- *ron* stands for 'cron'\n\ndron is my attempt to overcome things that make working with Systemd tedious\n:end:\n\n\n#+begin_src python :results drawer :exports results \nimport dron; return dron.make_parser().epilog\n#+end_src\n\n#+RESULTS:\n:results:\n\n* What does it do?\nIn short, you type ~dron edit~ and edit your config file, similarly to ~crontab -e~:\n\n: from dron.api import job\n:\n: # at the moment you're expected to define jobs() function that yields jobs\n: # in the future I might add more mechanisms\n: def jobs():\n:     # simple job that doesn't do much\n:     yield job(\n:         'daily',\n:         '/home/user/scripts/run-borg /home/user',\n:         unit_name='borg-backup-home',\n:     )\n:\n:     yield job(\n:         'daily',\n:         'linkchecker https://beepb00p.xyz',\n:         unit_name='linkchecker-beepb00p',\n:     )\n:\n:     # drontab is simply python code!\n:     # so if you're annoyed by having to rememver Systemd syntax, you can use a helper function\n:     def every(*, mins: int) -\u003e str:\n:         return f'*:0/{mins}'\n:\n:     # make sure my website is alive, it will send local email on failure\n:     yield job(\n:         every(mins=10),\n:         'ping https://beepb00p.xyz',\n:         unit_name='ping-beepb00p',\n:     )\n\n\nAfter you save your changes and exit the editor, your drontab is checked for syntax and applied\n\n- if checks have passed, your jobs are mapped onto Systemd units and started up\n- if there are potential errors, you are prompted to fix them before retrying\n\n* Why?\nIn short, because I want to benefit from the heavy lifting that Systemd does: timeouts, resource management, restart policies, powerful scheduling specs and logging,\nwhile not having to manually manipulate numerous unit files and restart the daemon all over.\n\nI elaborate on what led me to implement it and motivation [[https://beepb00p.xyz/scheduler.html#what_do_i_want][here]]. Also:\n\n- why not just use [[https://beepb00p.xyz/scheduler.html#cron][cron]]?\n- why not just use [[https://beepb00p.xyz/scheduler.html#systemd][systemd]]?\n\n:end:\n\n\n* Setting up\n\n1. install system dependencies (see =.ci/run= ) -- these are necessary for =dbus-python= library\n2. install dron: =pip3 install --user git+https://github.com/karlicoss/dron=\n3. install =sendmail= from your package manager if you want to recieve job failure emails\n\n* Using\n  \n#+begin_src python :results value :exports results \nimport dron; \np = dron.make_parser()\np.prog = ''\np.epilog = ''\nreturn p.format_help()\n#+end_src\n\n#+RESULTS:\n#+begin_example\nusage: [-h] [--marker MARKER] {monitor,past,edit,apply,lint,uninstall} ...\n\ndron -- simple frontend for Systemd, inspired by cron.\n\n- *d* stands for 'Systemd'\n- *ron* stands for 'cron'\n\ndron is my attempt to overcome things that make working with Systemd tedious\n\npositional arguments:\n  {monitor,past,edit,apply,lint,uninstall}\n    monitor             Monitor services/timers managed by dron\n    past                List past job runs\n    edit                Edit  drontab (like 'crontab -e')\n    apply               Apply drontab (like 'crontab' with no args)\n    lint                Check drontab (no 'crontab' alternative, sadly!)\n    uninstall           Uninstall all managed jobs\n\noptions:\n  -h, --help            show this help message and exit\n  --marker MARKER       Use custom marker instead of default `(MANAGED BY DRON)`. Possibly useful for developing/testing.\n#+end_example\n\n\n* Job syntax\n  \nThe idea is that it's a simple python DSL that lets you define simple jobs with minimal friction.\n\nHowever, if you wish you can pass arbitrary unit properties as keyword arguments as well.\n\n* Caveats\n- older systemd versions would only accept absolute path for =ExecStart=. That should be caught during =dron edit= though\n  \n* Potential improvements\n- custom validation; at the moment it runs pylint, mypy and systemd verify\n- make it more atomic?\n\n  E.g. roll back all the changes until daemon-reload\n- more failure report mechanisms?\n\n  Ideally, benefit from [[https://github.com/dschep/ntfy][ntfy]]\n  \n** TODO add issues with various questions that I had in code?\n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarlicoss%2Fdron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarlicoss%2Fdron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarlicoss%2Fdron/lists"}