systemd timer

On this page 7

A systemd timer is a unit of type .timer that activates another unit, usually a service, at a defined time or after a defined interval. In Linux system initialization and service management, timers are the native systemd mechanism for scheduled and delayed tasks, covering the work that cron and at traditionally handled.

Because a timer only triggers a unit, the scheduled job itself runs as an ordinary systemd service with its own logging, resource limits, dependencies and security settings. This separation of when from what is the defining design choice of systemd timers and the source of most of their advantages.

How a timer activates its service

A timer works as a pair of unit files. The file backup.timer holds the schedule, and by default it activates backup.service with the same base name. A different target can be named with the `Unit=` directive. When the timer elapses, systemd starts the service exactly as if an administrator had run systemctl start.

The timer is enabled and started like any other unit, typically with systemctl enable --now backup.timer, and it is pulled in at boot through `timers.target`. The service itself is usually not enabled, because it should run only when the timer fires, not at every boot.

If the service is still running when the timer elapses again, systemd does not start a second instance. This built-in protection against overlapping runs is something cron does not provide, where long jobs need external locking with tools such as flock.

Timers also work with template units. A file named snapshot@.timer can be enabled as snapshot@home.timer and snapshot@var.timer, and each instance activates the matching snapshot@.service instance with the instance name as a parameter. One pair of files then schedules the same job for many targets without duplication.

Monotonic and realtime timers

Systemd distinguishes monotonic timers, which count from an event such as boot, from realtime timers, which follow the wall clock and calendar. A single timer unit may combine several directives, and it fires whenever any of them elapses.

The following table lists the main schedule directives and what each one measures.

DirectiveKindMeasured fromExample
OnBootSec=MonotonicSystem bootOnBootSec=10min
OnStartupSec=MonotonicStart of the service managerOnStartupSec=5min
OnActiveSec=MonotonicActivation of the timerOnActiveSec=1h
OnUnitActiveSec=MonotonicLast activation of the target unitOnUnitActiveSec=6h
OnUnitInactiveSec=MonotonicLast deactivation of the target unitOnUnitInactiveSec=30min
OnCalendar=RealtimeCalendar expressionOnCalendar=Mon..Fri 02:30
Schedule directives in a timer unit

Calendar expressions use the format `DayOfWeek Year-Month-Day Hour:Minute:Second`, with shortcuts such as hourly, daily, weekly and monthly. The command `systemd-analyze calendar` parses an expression and prints the next elapse time, which makes schedule errors easy to catch before deployment.

Directives that control precision and catch-up

Several directives tune how exactly and how reliably a timer fires. They matter on laptops, on fleets of servers and for jobs that must not be skipped.

DirectiveDefaultEffect
Persistent=falseRuns a missed calendar job at next boot
AccuracySec=1minAllows coalescing within this window to save power
RandomizedDelaySec=0Adds a random delay to spread load
WakeSystem=falseWakes a suspended machine to run the job
FixedRandomDelay=falseKeeps the random offset stable per host
Tuning directives and their effect

Persistent=true stores the last trigger time on disk, so a daily job missed while the machine was off runs shortly after the next boot. This replaces the role of anacron on desktops. RandomizedDelaySec= is essential on large fleets, because hundreds of hosts running OnCalendar=daily would otherwise hit a shared repository at the same second after midnight.

For tasks that need second-level precision, AccuracySec=1s or lower must be set explicitly, because the default one-minute window lets systemd delay elapses to batch wakeups.

Systemd timers compared with cron

Timers and cron solve the same scheduling problem with different trade-offs. Cron remains simpler for a quick one-line job, while timers integrate scheduling into the service manager that already controls the rest of the system.

Aspectsystemd timerCron
ConfigurationTwo unit filesOne crontab line
LoggingJournal per unit, readable with journalctlMail or manual redirection
Overlap protectionBuilt inRequires external locking
Missed runsCaught up with Persistent=trueLost unless anacron is used
Resource controlCgroup limits, sandboxingOnly what the script sets up
DependenciesCan order after mounts or networkNone
Per-user jobsUser units with lingeringUser crontabs
Systemd timers and cron side by side

The decisive advantage of timers is observability. systemctl list-timers shows every timer with its last and next run, and journalctl -u backup.service shows the complete output of each run with timestamps and exit codes, without any mail configuration.

Pitfalls when writing timer units

Most timer failures come from mismatched names, missing enablement or wrong service type. The following list covers the problems administrators encounter most often.

  • Enabling the service instead of the timer: the job then runs at boot and never on schedule.
  • Forgetting daemon-reload: after editing unit files, systemctl daemon-reload is required before changes take effect.
  • Using Type=simple for batch jobs: Type=oneshot is the correct type for a task that runs to completion.
  • Relying on a user shell environment: services start with a minimal environment, so paths and variables must be set in the unit.
  • User timers that stop at logout: per-user timers need loginctl enable-linger to run without an active session.

For one-off delayed tasks, `systemd-run –on-active=30min` creates a transient timer and service without writing any files, which is the systemd counterpart of the at command.

The simple explanation

A systemd timer is an alarm clock for the computer. You write down when the alarm should ring, such as every night at two, and what should happen when it rings, such as starting a backup. The computer takes care of the rest.

Unlike a simple alarm, this one also keeps a diary. It remembers whether the task ran, what it printed and whether it failed, and it can catch up on a missed alarm if the computer was switched off at the scheduled time.

How it is used in practice

An operations team runs a database backup on forty Linux servers. Under cron, all forty started at exactly 02:00, overloaded the shared storage and occasionally overlapped with the previous run, while failures went unnoticed because nobody read the cron mail.

The team replaces the cron line with db-backup.service of Type=oneshot and db-backup.timer containing OnCalendar=*-*-* 02:00, `RandomizedDelaySec=45min` and Persistent=true. A monitoring check reads the service result from systemd every morning.

Backups now spread across a 45-minute window, storage load stays flat, no run ever overlaps the previous one, and a failed backup appears immediately as a failed unit with its full log in the journal.