Systemd Timers for Periodic Scheduling in Debian

This article examines how the systemd init system provides robust, flexible alternatives to legacy cron daemons for periodic scheduling in Debian. It covers the dual-unit architecture of systemd timers, the distinct timing mechanisms available—including realtime calendar events and monotonic triggers—and the native features that make systemd-based automation more reliable for system administration.

The Systemd Timer Architecture

In Debian, systemd replaces standalone schedulers like cron and anacron using timer units (files ending in .timer). A systemd timer does not execute commands directly; instead, it binds to and activates a matching service unit (files ending in .service).

When a timer triggers, systemd starts the corresponding service unit, which executes the defined task within systemd’s managed execution environment. This provides access to advanced cgroup resource limits, structured logging through journald, and strict dependency resolution.

Realtime Timers (Calendar Events)

The primary alternative to traditional cron expressions in systemd is the realtime timer, configured using the OnCalendar= directive. Realtime timers trigger based on wall-clock time and calendar dates.

Unlike cron’s five-field format, systemd calendar events use human-readable syntax that supports granular specifications from years down to seconds:

  • OnCalendar=*-*-* 04:00:00 (daily at 4:00 AM)
  • OnCalendar=Mon,Fri *-*-* 18:30:00 (Mondays and Fridays at 6:30 PM)
  • OnCalendar=hourly or daily or weekly (convenient predefined shortcuts)

To match or exceed the functionality of anacron, systemd timers support the Persistent=true directive. If the machine is powered off or suspended when a scheduled run is due, systemd immediately executes the service upon the next boot.

Monotonic Timers (Relative Events)

Monotonic timers schedule jobs relative to varying system states rather than the wall clock. These timers do not drift when the system clock changes (e.g., due to daylight saving adjustments or NTP updates) and provide scheduling paradigms that traditional cron cannot replicate:

  • OnBootSec=: Triggers a specific duration after the kernel has booted.
  • OnStartupSec=: Triggers relative to when the systemd service manager itself initialized.
  • OnUnitActiveSec=: Schedules a task relative to the moment the associated service was last activated.
  • OnUnitInactiveSec=: Schedules a task relative to when the associated service finished its last execution, preventing task overlaps if a job runs longer than expected.

Multiple timing constraints can be combined in a single .timer file, allowing jobs to run at boot and subsequently repeat at regular intervals:

[Unit]
Description=Run maintenance script periodically

[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
Persistent=true

[Install]
WantedBy=timers.target

Transient Timers with systemd-run

For ad-hoc tasks or command-line scripting where creating persistent unit files on the filesystem is unnecessary, Debian users can generate transient timers via the systemd-run utility.

Transient timers create temporary timer and service units dynamically in memory:

  • Relative execution: systemd-run --on-active="2h" /usr/local/bin/backup.sh
  • Calendar execution: systemd-run --on-calendar="daily" /usr/local/bin/cleanup.sh

Managing and Auditing Timers

Systemd includes native tooling to inspect, track, and monitor scheduled jobs without parsing disparate crontab files or user tables.

  • View active timers: Run systemctl list-timers to display all active timers, their next scheduled run time, the time elapsed since their last execution, and their associated service units.
  • View execution logs: Run journalctl -u service-name.service to review dedicated stdout, stderr, and failure codes for the scheduled job.