bitlvl
EN

systemd timer OnCalendar explainer

Type an OnCalendar expression or paste a cron line to convert. You get the meaning, the next ten runs, and a complete .timer + .service pair to drop into /etc/systemd/system.

Unit files

  

OnCalendar syntax

The format is [Weekday] Date Time, with each part optional: Mon..Fri *-*-* 06:30:00. Weekdays use three-letter names with .. ranges and commas. The date is YYYY-MM-DD with * for any; the time is HH:MM:SS (seconds default to 00). Any field accepts lists (1,15), ranges (8..18) and steps (*/15 or 0/15, 8..18/2). Shortcuts: minutely, hourly, daily, weekly, monthly, yearly, quarterly. A trailing zone name applies the expression in that zone (*-*-* 09:00 Europe/Belgrade).

CronOnCalendar
*/5 * * * **-*-* *:*/5:00
0 * * * *hourly
30 6 * * 1-5Mon..Fri *-*-* 06:30:00
0 9 1 * **-*-01 09:00:00
0 3 * * 0Sun *-*-* 03:00:00
0 0 L * **-*~01 00:00:00 (last day of month: ~ counts from the end)

What timers do that cron does not

  • Persistent=true: if the machine was off when the timer should have fired, run it at the next boot. Cron just misses it (anacron exists for this).
  • RandomizedDelaySec=: spread runs across a window so a fleet does not hit the server at the same second.
  • AccuracySec=: default one minute; set 1s if the exact time matters, or longer to batch wakeups and save power.
  • Logs go to the journal (journalctl -u name.service), the job runs with the service's sandboxing, dependencies and resource limits, and systemctl list-timers shows the next and last runs.

Checking an expression

systemd-analyze calendar "Mon..Fri *-*-* 06:30" prints the normalised form and the next elapse, which is what this page reproduces. After installing a timer: systemctl daemon-reload && systemctl enable --now name.timer, then systemctl list-timers --all.

Questions

Why does my timer run once and never again?

Usually the timer was started but not enabled (systemctl enable --now name.timer), or the service it triggers is a oneshot without a matching timer unit. Check systemctl list-timers and journalctl -u name.timer.

How do I run a timer as a normal user?

Put the units in ~/.config/systemd/user/, use systemctl --user, and run loginctl enable-linger $USER so they fire without an active login session.

Does OnCalendar use the system time zone?

Yes, unless the expression ends with a zone name, which systemd 243+ supports. Container and cloud images are usually UTC; set the zone explicitly if the schedule is meant in local time.

How do I express “every weekday at 9 and 17”?

Mon..Fri *-*-* 09,17:00:00. Lists work in any field.