linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Processes & resources/systemd-timers

kb/processes ── Processes & resources ── intermediate

systemd timers as a cron replacement

A systemd timer is a `.timer` unit that runs a paired `.service` on a schedule or after an interval from an event (boot, last run). It replaces cron with logs in [[cmd-journalctl]] and dependencies.

view as markdownaka: timer-unit, oncalendar, onbootsec, systemd-cron

Why not cron

cron does one thing: "run a script at this minute." A systemd timer can do more:

  • Run after an interval from an event (5 minutes after boot, 1 hour after the previous run), beyond a fixed point in time.
  • Catch up on missed runs after the host was powered off (Persistent=true).
  • Write stdout/stderr automatically to cmd-journalctl, with no >> /var/log/myapp.log 2>&1 in the script.
  • Use the whole systemd infrastructure: dependencies (After=/Requires=), sandbox isolation (PrivateTmp=, ProtectSystem=), cgroup limits (MemoryMax=).
  • Randomize the start (RandomizedDelaySec=) so that 200 hosts do not hit the backup server at the same moment.

cron is still here, and it is not deprecated. For new code a systemd timer is more convenient.

Pairing .timer + .service

A timer always works alongside a service unit with the same name (or one named explicitly):

/etc/systemd/system/backup.timer    ← when to run
/etc/systemd/system/backup.service  ← what to run

By default backup.timer triggers backup.service. If the names differ, name the service explicitly:

ini
[Timer]
Unit=other-backup.service

Trigger types

DirectiveTypeWhen it fires
OnCalendar=calendarAt the given calendar time (like cron)
OnBootSec=monotonicN after the kernel boots
OnStartupSec=monotonicN after systemd starts (≈ the same as boot)
OnActiveSec=monotonicN after the timer itself is activated
OnUnitActiveSec=monotonicN after the paired service last started
OnUnitInactiveSec=monotonicN after the paired service last finished

Monotonic = counted from an event, not from the wall clock. It is not persistent by default (the counter resets after a reboot). This is handy for "run 10 minutes after boot, then every 6 hours."

You can combine these. Put several On* in one [Timer], and it fires on any condition.

OnCalendar syntax

Format: DOW YYYY-MM-DD HH:MM:SS. DOW and any fields can be omitted (*).

ExpressionWhat it means
*-*-* 03:00:00every day at 03:00
Mon..Fri *-*-* 09:00on weekdays at 09:00
Mon *-*-* 00:00:00every Monday at midnight (= weekly)
*-*-01 00:00:00the first of every month (= monthly)
*-*-* *:0/15:00every 15 minutes
2026-6,7,8-1,15 01:15:00June 1 and 15, July, August 2026
Mon *-05~03first Monday counting third from the end of May
*-05~03/2third from the end of May, then every 2 days

Aliases: minutely, hourly, daily, weekly, monthly, yearly.

Always check an expression before you commit it:

bash
systemd-analyze calendar "Mon..Fri *-*-* 09:00"
# Original form: Mon..Fri *-*-* 09:00
# Normalized form: Mon..Fri *-*-* 09:00:00
# Next elapse: Wed 2026-04-30 09:00:00 EDT
# From now: 14h left

AccuracySec and RandomizedDelaySec, why it is not exact

By default systemd does not fire a timer at the exact second you specify. It fires in a 1-minute window starting from the given time. This is deliberate: if 5 timers are set to daily (= 00:00:00), they would start at once and saturate I/O.

ini
[Timer]
OnCalendar=daily
AccuracySec=1us           # narrow window, fires at the exact second
RandomizedDelaySec=30min  # plus a random delay of up to 30 min

Most system timers default to AccuracySec=1h or more. Narrow it only when the job really is time-critical.

Persistent, catching up after downtime

By default, if the host was powered off at the firing time, the event is missed. With Persistent=true (for OnCalendar= only) systemd records the last run time in /var/lib/systemd/timers/ and checks it at startup. If a run was missed, it triggers right away.

ini
[Timer]
OnCalendar=daily
Persistent=true       # critical for backups on laptops and dev VMs

Minimal example: backup every 6 hours

/etc/systemd/system/backup.service:

ini
[Unit]
Description=Nightly backup
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/do-backup.sh
User=backup

/etc/systemd/system/backup.timer:

ini
[Unit]
Description=Backup every 6h after boot
[Timer]
OnBootSec=15min
OnUnitActiveSec=6h
Persistent=true
RandomizedDelaySec=5min
[Install]
WantedBy=timers.target

Activate it:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer

Note: WantedBy=timers.target (not multi-user.target), otherwise the timer will not be picked up at boot.

Viewing and debugging

bash
systemctl list-timers --all              # all timers with next/last run
systemctl status backup.timer            # state of one timer
systemctl cat backup.timer               # the effective unit with drop-ins
journalctl -u backup.service -S today    # what the triggered service wrote
systemd-analyze calendar 'Mon *-*-* 04:00'   # check OnCalendar
systemd-analyze timespan '15days 6h'         # parse a time span

Remove an unwanted default timer (no SSD means no need for fstrim):

bash
sudo systemctl disable --now fstrim.timer

§ команды

bash
systemctl list-timers --all

All timers with next/last run and the paired service. An overview of the host schedule.

bash
systemd-analyze calendar 'Mon..Fri *-*-* 09:00'

Check that an OnCalendar expression is valid and see when it will fire.

bash
journalctl -u backup.service -S today

Logs of the triggered service for today's runs.

bash
systemctl cat backup.timer

The effective unit with drop-ins applied, what systemd actually reads.

bash
sudo systemctl enable --now backup.timer

Activate the timer now and at boot (the timer, not the service).

§ см. также

  • systemdsystemd: the init system and service managersystemd is the Linux init system: PID 1 that starts everything else, tracks dependencies, restarts what crashes, and collects the logs.
  • cmd-systemctlsystemctl: managing systemd services`systemctl` is the main CLI for managing systemd units: services, timers, mounts, and sockets. It replaces SysV init and `service` on modern distros.
  • cmd-journalctljournalctl: systemd journal`journalctl` reads the binary journal written by systemd-journald. It is the central log for the system: kernel, systemd services, syslog, all through one interface.
  • cmd-cron-crontabcron and crontab: scheduling taskscron is a daemon that reads crontab files and runs jobs on a schedule. Format: `min hour day month weekday command`. anacron handles machines that are powered off. On systemd systems, timers are often used instead.
  • systemd-unit-typessystemd unit typesA unit is a resource managed by systemd. The file extension equals the type: `.service` (daemon), `.socket` (lazy start on a socket), `.timer`, `.mount`, `.path`, `.slice`/`.scope` (cgroups), `.target` (a group).
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies