Skip to main content
RunBook Academy

LinuxXXXVI · Scheduled Operationssystemd timers

systemd timers replacing cron - the modern scheduler

Intermediate⏱ ~12 minsystemd

What you'll learn

  • Create a systemd timer unit
  • Use OnCalendar and OnBootSec/OnUnitActiveSec
  • Replace cron with timers
  • Recognise timer advantages over cron

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

systemd timers are the modern replacement for cron. They integrate with systemd’s logging, dependencies, and resource control. This lesson covers timer syntax and migration from cron.

A timer unit

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup nightly at 02:30

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
Unit=backup.service

[Install]
WantedBy=timers.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

The timer fires the service at the specified time.

OnCalendar syntax

OnCalendar= uses a calendar expression:

OnCalendar=Mon..Fri 09:00           # weekdays at 09:00
OnCalendar=*-*-* 02:30:00            # every day at 02:30
OnCalendar=*:0/15                    # every 15 minutes
OnCalendar=Sun 03:00:00              # Sunday at 03:00
OnCalendar=2026-12-31 23:59:00       # specific date and time

man systemd.time has the full syntax. Test with systemd-analyze calendar "Mon..Fri 09:00".

Monotonic timers

For “every X minutes after boot” or “1 hour after the service started”:

[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
Unit=myservice.service

OnBootSec=5min triggers 5 minutes after boot. OnUnitActiveSec=1h triggers 1 hour after the unit was last active. Useful for “restart every hour”.

Persistent=true

With Persistent=true, the timer catches up on missed runs:

# If the machine was off at 02:30, run at next boot
Persistent=true

Without it, missed runs are dropped. Use Persistent=true for jobs that must run daily.

Advantages over cron

  • Logging: timer fires are logged in journald. cron only emails.
  • Dependencies: timer units can depend on other units (e.g. require network-online.target).
  • Resource control: services inherit systemd’s resource limits.
  • Catchup: Persistent=true catches missed runs.
  • Failure handling: failures trigger dependencies, not silent retries.

Migrate from cron

For each cron job:

  1. Create a .service unit that runs the command.
  2. Create a .timer unit that schedules the service.
  3. systemctl daemon-reload
  4. systemctl enable --now <name>.timer
  5. Remove from crontab (crontab -e, delete the line).

Test in staging first.

Knowledge check

Knowledge check · 3 questions

  1. Q1. What does OnCalendar=*-*-* 02:30:00 mean?

  2. Q2. systemd timers catch up on missed runs if Persistent=true is set.

  3. Q3. Which of the following are valid systemd timer options? Select all that apply.

Passing score: 75%. Answers are checked in this browser.