Your nightly report is scheduled for 2:30 a.m. The server is powered off at 2:30 and comes back online at 8:00. Does the job run late, wait until tomorrow, or get lost?
With systemd timers, the answer depends on a few settings you can read in a small configuration file. This guide explains which clock each timer uses, what happens after downtime, and how to check a schedule before trusting it on a server.
OnCalendar= schedules by the clock on the wall. OnBootSec= schedules relative to boot time. OnUnitActiveSec= schedules relative to when the associated unit was last activated. OnUnitInactiveSec= measures from when it finished and deactivated. Persistent=true can trigger one catch-up activation for a missed OnCalendar= event when the timer becomes active again; it does not replay every missed occurrence.
- 1. How systemd timers start services
- 2. Which clock do systemd timers use?
- 3. Read this timer before copying anything
- 4. What happens when systemd timers miss a run?
- One late activation
- Wait for the next match
- A different rule entirely
- 5. Two read-only checks for systemd timers
- Check the next three calendar matches
- See which timers your system knows about
- 6. Five essential rules for safe scheduling
- Quick knowledge check
- Technical references
1. How systemd timers start services
The easiest way to understand systemd timers is to separate when from what. A .timer unit holds the timing rules; the associated .service unit runs the command. By default, daily-report.timer activates daily-report.service. A timer can target a different unit using Unit=.
OnCalendar=ExecStart=This separation is useful when a job fails: you can check whether its schedule elapsed, then inspect the service for the actual execution result. If you’re new to systemd units, the systemd units and boot process guide covers the bigger picture.
If the service is already active when the timer elapses, systemd does not start another copy of that unit. It also does not create a queue of missed copies. This differs from assuming every clock tick launches a separate process. A recurring Type=oneshot service also generally should not use RemainAfterExit=yes, because that would leave the service active after the command finishes.
2. Which clock do systemd timers use?
Not all systemd timers mean “run at 2:30.” Some schedules follow civil time; others follow elapsed time since a particular event.
OnCalendar=Matches a calendar expression such as every day at 02:30. This follows the system’s wall clock and configured timezone.
OnBootSec=Counts from the machine’s boot time, such as five minutes after startup. This is not an everyday calendar event.
OnUnitActiveSec=Counts from the last activation of the target unit. Useful for repeated work tied to previous activations.
| Goal | Setting | How to read it |
|---|---|---|
| Report every morning at 02:30 | OnCalendar=*-*-* 02:30:00 | Use calendar time; check timezone and clock synchronization. |
| Run once five minutes after startup | OnBootSec=5min | Measured relative to boot. If the timer is activated after that point has already passed, it can elapse immediately. |
| Repeat ten minutes after each activation | OnUnitActiveSec=10min | Measured from activation, not ten minutes after the job finishes. |
| Wait ten minutes after each completed run | OnUnitInactiveSec=10min | Measured from when the activated unit becomes inactive; provide a separate initial trigger or start the service first. |
Systemd timers can also combine multiple timing directives: whichever condition becomes due can trigger the associated unit. For instance, OnBootSec=5min plus OnUnitActiveSec=1h is a common shape for periodic work that begins after startup. Source: systemd.timer(5).
In a user systemd manager, OnStartupSec= is often the more relevant reference point: it counts from when that user manager started. Do not assume a user timer and a system timer share identical boot-time behavior.
3. Read this timer before copying anything
Consider a hypothetical nightly status report scheduled with systemd timers on one Linux server. It should run around 02:30 every day, and if the machine was switched off overnight, one late run after startup is acceptable. These are example unit files for understanding the relationship, not a record of a tested deployment.
[Unit]
Description=Example daily status report
[Service]
Type=oneshot
ExecStart=/usr/bin/uptime[Unit]
Description=Schedule the example daily report
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
AccuracySec=1min
Unit=daily-report.service
[Install]
WantedBy=timers.targetType=oneshot tells systemd to run a finite task rather than keep a daemon alive. The command here only reports uptime; an actual deployment should use a deliberate script, account, permissions, and logging policy. See how to write a systemd service unit for that groundwork.
AccuracySec=1min?Systemd timers are not guaranteed to dispatch at a microsecond-precise instant. The default accuracy window is one minute; this line makes the intended tolerance visible. For wider scheduling windows or reduced load spikes, systemd also offers RandomizedDelaySec=, which adds a random delay. It solves a different problem from AccuracySec=.
4. What happens when systemd timers miss a run?
OnCalendar= and Persistent=true, a late activation may be requested when the timer becomes active again; individual missed events are not queued.For systemd timers, the missed-run behavior is often the deciding detail. Imagine the report is due at 02:30, but the server is offline from midnight to 08:00. Compare the conditions below.
One late activation
With OnCalendar= and Persistent=true, activating the timer again can request a catch-up start because at least one scheduled event passed while it was inactive.
Wait for the next match
Without persistence, the timer ordinarily waits for its next scheduled calendar match after activation. Yesterday’s slot is not treated as pending work.
A different rule entirely
OnBootSec=5min has no “yesterday’s 02:30” to recover. It becomes due relative to boot, and a past boot-relative deadline may elapse immediately when activated.
Crucial limit: even if the server missed three daily calendar events, Persistent=true is not an instruction to execute the task three times. It allows a catch-up activation, not a durable work queue. And a catch-up is still affected by applicable scheduling delays and whether the associated unit is already active. Source: systemd.timer(5), Persistent=.
For billing, payment reconciliation, or other work that must process each date exactly once, let the application track completed periods in durable storage. A systemd timer decides when to try to run a service; it does not prove business-level completion or replay each missed transaction.
5. Two read-only checks for systemd timers
You can inspect systemd timers without adding files to /etc/systemd/system, enabling anything, or modifying existing services. These commands are read-only; they require systemd tooling on your Linux machine.
Check the next three calendar matches
systemd-analyze calendar --iterations=3 '*-*-* 02:30:00'Look for the normalized expression and its next three matching dates. The exact dates and timezone depend on your machine and when you run the command. If the expression is invalid, the parser reports an error rather than installing a bad schedule. This tests the calendar expression—not whether a service will succeed.
For this guide, we ran the command above in an isolated Debian 13 environment using systemd 257.9. The parser accepted the expression, normalized it to *-*-* 02:30:00, and produced three future daily matches. No production timer or service execution was tested.
See which timers your system knows about
systemctl list-timers --allRead the NEXT, LAST, UNIT, and ACTIVATES columns. Unit names and timestamps vary by distribution. An absent or blank NEXT value is a reason to inspect that timer’s state, not automatic proof that the underlying application failed. For command details, see systemd-analyze(1) and systemctl(1).
A calendar rule describes when the timer becomes due. A service’s exit status and logs tell you what the work actually did. Once you create a test timer in Lesson 02, inspect both sides rather than relying on one “active” label. For log-reading basics, see journalctl Explained.
6. Five essential rules for safe scheduling
Use these five rules when choosing settings for systemd timers. Each one prevents a different scheduling assumption from turning into a surprise.
- Fixed wall-clock time: start with
OnCalendar=. Verify how your timezone and daylight-saving changes affect that time. - Once shortly after startup: consider
OnBootSec=. Understand what happens if the timer activates after the chosen interval. - Repeat relative to the previous start: consider
OnUnitActiveSec=. For a gap after completion, compareOnUnitInactiveSec=. - One catch-up after a missed calendar slot: add
Persistent=true, but do not assume it queues all missed work. - Precise dispatch or distributed load: review
AccuracySec=andRandomizedDelaySec=deliberately instead of accepting timing assumptions.
If your job already runs well with cron, you do not need to replace it merely because timers exist. The separate Cron vs systemd Timers comparison helps with that choice. If you’re still learning cron syntax, start with Linux Cron Jobs Explained.
Quick knowledge check
A service starts at 10:00 and finishes at 10:07. What does OnUnitActiveSec=10min measure from?
From the unit’s last activation at 10:00, not from its finish at 10:07. Compare OnUnitInactiveSec= for an interval measured from deactivation.
The machine misses five daily slots. Does Persistent=true launch five jobs on reboot?
No. It can request a catch-up activation for a missed calendar event, but it is not a queue containing five executions.
What should you check after systemd-analyze confirms the calendar expression?
Check the timer’s activation status and the associated service’s actual result and logs. A valid schedule alone does not guarantee successful work.
When configuring systemd timers, choose the reference clock first. Decide whether one late run is useful after downtime. Then keep the schedule and the work separate enough that you can inspect both. In Lesson 02, we’ll turn this model into a working timer and a safe test script.
Technical references
- systemd.timer(5) — timer directives, elapsed-time rules, persistence, and accuracy.
- systemd.time(7) — calendar and time-span expression syntax.
- systemd-analyze(1) — validation of calendar schedules.
- systemd.service(5) — one-shot service behavior.
- systemd upstream source documentation — latest directive definitions; use your installed
man systemd.timerfor version-specific behavior.
Version note: systemd options differ across releases. Check systemd --version and the manual pages installed on your server before relying on settings that may be unavailable in an older distribution. For service deployment and hardening, follow your distribution’s security guidance.








