systemd Timers Without the Guesswork
Create a small systemd timer, inspect its next run, and make missed jobs predictable after downtime.

Photo: Unsplash.
A systemd timer separates the schedule from the job. That gives you logs, dependency handling, and a way to inspect the next run without decoding a crontab.
Create /etc/systemd/system/blog-backup.service:
[Unit]
Description=Back up the blog database
[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/sbin/blog-backup
Then /etc/systemd/system/blog-backup.timer:
[Unit]
Description=Run the blog backup every night
[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true
RandomizedDelaySec=10m
[Install]
WantedBy=timers.target
Persistent=true tells systemd to trigger a missed calendar run after the machine returns. RandomizedDelaySec avoids making every scheduled task start on the same second.
Load and enable it:
sudo systemctl daemon-reload
sudo systemctl enable --now blog-backup.timer
systemctl list-timers blog-backup.timer
Test the command separately before waiting for the timer:
sudo systemctl start blog-backup.service
journalctl -u blog-backup.service --since today
Validate calendar expressions with the same parser systemd uses:
systemd-analyze calendar '*-*-* 02:15:00'
The timer’s user does not inherit your interactive shell, so use absolute paths and put required environment values in a protected EnvironmentFile. A successful timer only proves the service was started; make the script fail with a nonzero exit status when the backup itself fails.
