Arguably the most important bit of information about timers is how to express a schedule, whether a repeating period of time (which the manual usually refers to as a time span) versus a calendar event (or a timestamp). Fortunately, I think the man page for this under systemd.time(7) is actually very good with plenty of examples. You should use it as the first resource when writing timers; it's good (or better) than, uh, casual blog posts by casual writers.
systemd also ships with a command-line tool called systemd-analyze which includes the ability to validate and explain time expressions from the command line directly in an imperative way to help understand them. You can even disambiguate the classic wildcard cron expression which systemd-analyzer can parse and then explain to you, complete with the expected execution times:
shell
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:* Next elapse: Sat 2026-04-18 16:44:26 MDT (in UTC): Sat 2026-04-18 22:44:26 UTC From now: 431ms left
This blog post is not the place to reproduce the entirety of systemd.time(7) verbatim, so I encourage you to Read The Helpful Manual (RTHM). Writ small, you can pretty simply define either a recurring wallclock period or, in contrast to plain old cron , a recurring period of time against some previous event.
The first category of time expressions is easy to envision. For example, in fully-qualified form, daily means:
*-*-* 00:00:00 │ │ │ │ │ ╰── at second 00 │ │ │ │ ╰───── at minute 00 │ │ │ ╰──────── at hour 00 │ │ ╰────────── every day │ ╰──────────── every month ╰────────────── every year
You can use shorthand terms like daily , write out the complete form, or use any other supported value listed out in systemd.time(7) and subsequently validate your assumptions against systemd-analyze .
The second category of time expressions apply to "run this relative to some other event." This distinction from "run at the same time very day" is very often what you actually want. Consider a job that clears out a temporary directory, for example: if a cron expression lapsed right after boot, there probably isn't much to clean out of /tmp at all. But if you encode "execute an hour after my computer has started and then every hour after that", the schedule logic is meaningful for what the related service is actually doing.
... continue reading