systemd timers offer a modern alternative to cron for scheduling tasks — with better logging integration, dependency handling, and more flexible scheduling options. This guide covers setting them up.
Why Consider systemd Timers Over Cron
- Output and errors are automatically captured in
journalctl, no manual log redirection needed - Timers can depend on other systemd units (e.g. only run after a specific service is active)
- Built-in handling for missed runs (e.g. if the server was off when a job should have run)
Step 1 — Create a Service Unit for the Task
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Daily backup task
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-script.sh
Type=oneshot is appropriate for a task that runs to completion and exits, rather than a persistent daemon.
Step 2 — Create a Matching Timer Unit
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run backup.service daily
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Persistent=true ensures a missed run (e.g. server was off at 2 AM) executes as soon as possible after the system is back up — a genuine advantage over standard cron, which simply skips missed runs.
Step 3 — Enable and Start the Timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Step 4 — Verify the Timer Is Scheduled
systemctl list-timers
Shows all active timers along with their next scheduled run time.
Common OnCalendar Syntax Examples
OnCalendar=hourly
OnCalendar=daily
OnCalendar=*-*-* 03:30:00
OnCalendar=Mon,Wed,Fri 09:00:00
OnCalendar=*-*-01 00:00:00 # first of every month
Testing the Service Manually (Without Waiting for the Timer)
sudo systemctl start backup.service
Checking Execution History and Logs
journalctl -u backup.service
All output, including errors, is automatically captured here — no need to manually redirect output to a log file as is common practice with cron.
Using Relative/Monotonic Timers (Alternative to Calendar-Based)
[Timer]
OnBootSec=15min
OnUnitActiveSec=1h
Runs 15 minutes after boot, then repeats every hour after each completion — useful for tasks that should run periodically relative to the last run rather than a fixed clock time.
When Cron Is Still a Reasonable Choice
For simple, personal scripts, traditional cron remains perfectly valid and often quicker to set up — systemd timers earn their added complexity specifically when you want better logging integration, dependency handling, or the missed-run catch-up behavior.
Common Errors
Timer is active but the service never runs — verify the timer unit's [Timer] section references the correct service name, and check systemctl list-timers for the actual next scheduled time.
"Unit not found" errors — run sudo systemctl daemon-reload after creating or editing any unit file, which is required for systemd to recognize new/changed unit files.
Continue Reading
- How to Schedule Tasks with Cron on a Linux VPS
- How to Manage Services with systemd and systemctl
- How to Read and Analyze Linux Logs with journalctl
Browse more articles in Linux Server Administration.