Timers
Scope: scheduling with systemd instead of cron — a timer unit paired with a service unit, with real firings verified.
The pair
A timer never runs anything itself. It activates a
service (same name, .timer ↔ .service), usually a
Type=oneshot. The lab's pair, shipped in
examples/:
mere-log.service — the work: append a timestamp line to a file, then exit. Oneshot is exactly right: run, succeed, done.
mere-log.timer:
[Unit]
Description=Run mere-log.service every 15 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=15
AccuracySec=1
[Install]
WantedBy=timers.target
OnBootSec=10— first run 10s after boot.OnUnitActiveSec=15— then every 15s after the last activation. (For wall-clock schedules there'sOnCalendar=— below.)AccuracySec=1— systemd otherwise batches wakeups (default accuracy is a minute) to save power; for a demo, precision beats thrift.- Timers get enabled like services, attached to
timers.target.
sudo systemctl start mere-log.timer # or enable --now for keeps
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri 2026-10-16 18:32:27 CDT 14s Fri 2026-10-16 18:32:12 CDT 23ms ago mere-log.timer mere-log.service
and the proof, three ticks fifteen seconds apart:
tick 2026-10-16T23:32:12+00:00
tick 2026-10-16T23:32:27+00:00
tick 2026-10-16T23:32:43+00:00
OnCalendar: the cron dialect
OnCalendar=Mon..Fri 06:30
OnCalendar=daily (00:00)
OnCalendar=*-*-01 04:00 (the 1st, at 04:00)
systemd-analyze calendar "Mon..Fri 06:30" expands any
expression and shows the next firing — run it before
deploying a schedule, because calendar expressions are
write-only in every tool ever made.
Why not cron?
Cron still works and this guide won't pretend otherwise. Timers win on specifics:
- The work is a service — so it gets the journal
(
journalctl -u mere-log.service), dependencies, restart policy, sandboxing, everything in this guide, for free. Cron jobs get an email nobody reads. Persistent=true— a timer whose time passed while the machine was off fires at next boot. Cron just skips it. (The laptop-backup problem from the Backups guide has a native answer here.)- One list:
systemctl list-timers --allshows every schedule on the box, next and last, in one table — versus hunting through five crontabs and an/etc/cron.d.
Keep cron for what it's good at; reach for timers when the job is yours and deserves supervision.