Systemd timers: A Modern Replacement for cron

Back in the day, cron was the go-to tool for scheduling recurring tasks on Unix-like systems. It was simple, battle-tested, and did the job. But times have changed, and systemd — the modern init system — brings with it a more powerful, flexible, and robust alternative: systemd timers.

In this article, we’ll dive into what systemd timers are, how they compare to cron, and how to use them effectively. If you’re an old-school Linux sysadmin (like me), you might find yourself pleasantly surprised by how clean and capable this modern replacement really is.


The Problem with Traditional cron

Cron has served us well, but it has limitations:

  • No native support for logging
  • Limited error handling
  • Hard to track missed or failed jobs
  • Jobs can silently fail
  • No dependency management

Sure, you can work around these issues with scripts and redirection hacks, but why not use something built to solve them from the start?


Say “Hello” to systemd Timers

A systemd timer is a unit that schedules the execution of a corresponding service unit. Think of it as the modern equivalent of a cron job, but tightly integrated into systemd’s ecosystem.

Benefits Over cron:

  • Native logging via journalctl
  • Service state awareness (systemctl status)
  • Dependency management (e.g. run only after network is up)
  • Flexible time formats (calendar and monotonic time)
  • Handles missed events on boot or downtime with Persistent=true

Anatomy of a systemd Timer

A timer unit usually comes with a matching service unit:

  • myjob.service
  • myjob.timer

Let’s say that, for some odd reason, we want to log the current time every 10 minutes starting 5 minutes after system boots. Not so easy to do with cron, right? With systemd timers it is simple:

Step 1: Create the Service

sudo nano /etc/systemd/system/logtime.service
[Unit]
Description=Log the current time

[Service]
Type=oneshot
ExecStart=/usr/bin/date >> /var/log/time.log

Step 2: Create the Timer

sudo nano /etc/systemd/system/logtime.timer
[Unit]
Description=Run logtime.service every 10 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=10min
Unit=logtime.service

[Install]
WantedBy=timers.target

Where:

  • OnBootSec=5min: Wait 5 minutes after boot before first run
  • OnUnitActiveSec=10min: Run 10 minutes after the last activation
  • Unit=logtime.service: The service to trigger

Enable and Test It

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

Check status:

systemctl list-timers
systemctl status logtime.timer
journalctl -u logtime.service

Different Scheduling Options

Monotonic Timers:

Triggered after a relative time (e.g., 10min after boot).

  • OnBootSec=30s
  • OnStartupSec=1h
  • OnUnitActiveSec=5min
  • OnUnitInactiveSec=15min

Calendar Timers:

More like traditional cron — specify actual date/time patterns.

[Timer]
OnCalendar=*-*-* 03:00:00

Examples:

  • OnCalendar=daily
  • OnCalendar=Mon *-*-* 08:00:00
  • OnCalendar=*-*-01 00:00:00 (first of every month)

Validate calendar expressions:

systemd-analyze calendar "Mon *-*-* 08:00:00"

Real-World Examples

1. Daily Backup at 2 AM

backup.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

backup.timer

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

2. Weekly Maintenance on Sundays

[Timer]
OnCalendar=Sun *-*-* 01:00:00
Persistent=true

3. Run Task Every Hour, Starting 5 Min After Boot

[Timer]
OnBootSec=5min
OnUnitActiveSec=1h

Handling Missed Runs

The Persistent=true setting ensures that a missed timer (e.g., system was down) runs immediately on boot.


Security and Isolation

Since timers are paired with services, you get all the benefits of systemd sandboxing:

  • Run as specific user (User=backup)
  • Restrict file access (ProtectSystem=full, etc.)
  • CPU/memory limits (CPUQuota=, MemoryMax=)

Example:

[Service]
User=backup
ExecStart=/usr/local/bin/backup.sh
ProtectSystem=full
MemoryMax=500M

Pro Tips

  • Use systemctl list-timers to audit all active timers
  • Always test your service standalone first with systemctl start your.service
  • Use journalctl -u your.service to debug output
  • Use calendar timers for precise scheduling
  • Use Type=oneshot for short-lived tasks

Final Thoughts

systemd timers bring modern scheduling to Linux systems. While cron will always have its place in history, systemd gives us a cleaner, more maintainable, and powerful way to schedule recurring jobs. Once you make the switch, I am sure you won’t go back.

** The official documentation for systemd timers can be found here

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top