seyshee.dev

I replaced cron with systemd timers and I'm not going back

For years my servers had a crontab with ten lines and no idea whether any of them worked. Moving them to systemd timers took an afternoon. Here's what I got for it.

Two files instead of one line

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly database backup
After=network-online.target

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

[Timer]
OnCalendar=*-*-* 03:15
RandomizedDelaySec=20m
Persistent=true

[Install]
WantedBy=timers.target

Then systemctl enable --now backup.timer.

What you get

  • Logs. journalctl -u backup shows every run, its output and exit code. With cron I had >> /var/log/backup.log 2>&1 and hoped.
  • Missed runs. Persistent=true runs the job at boot if the machine was off at 03:15.
  • No thundering herd. RandomizedDelaySec spreads jobs across servers that share a config.
  • Status at a glance. systemctl list-timers shows the last and next run of everything.
  • Failure hooks. OnFailure=notify@%n.service in the [Unit] section, and a tiny template unit that sends a message. This alone was worth the move.

What you lose

The one-line convenience. For quick experiments I still use systemd-run --on-calendar=... which gives a transient timer without writing files.

OnCalendar syntax takes a minute to learn; systemd-analyze calendar "Mon *-*-* 09:00" prints the next trigger times, which helps.