The Flaws of Traditional Cron
For decades, Linux administrators have relied on the cron daemon to schedule automated tasks like nightly database backups or weekly log rotations. While cron is ubiquitous, its design shows its age. It has terrible error handling, it provides almost no built-in logging, and crucially, if a server is powered off during a scheduled cron window, the task simply won’t run until the next scheduled interval.
Modern Linux distributions (like Ubuntu, CentOS, and Debian) use systemd as their init system. systemd includes a native scheduling feature called Timers. While the setup is slightly more verbose than adding a single line to a crontab, systemd timers offer massive advantages: automatic retries on failure, highly detailed logging via journalctl, and the ability to execute tasks that were missed while the machine was asleep or powered off.
How Systemd Timers Work
Unlike cron, a systemd timer requires two separate configuration files:
- A Service File (
.service): This file defines what script or command to run. - A Timer File (
.timer): This file defines when to trigger the corresponding service file.
Both files must have the exact same base name (e.g., backup.service and backup.timer) and are usually stored in /etc/systemd/system/.
Step 1: Create the Service File
First, define the task you want to run. Let’s assume you have a bash script located at /usr/local/bin/backup.sh.
Open a new service file using your preferred text editor (with sudo privileges):
sudo nano /etc/systemd/system/daily-backup.service
Add the following configuration:
[Unit]
Description=Run the nightly backup script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Note: Setting Type=oneshot is crucial. It tells systemd that this is a script that executes and exits, rather than a continuous background daemon (like a web server).
Step 2: Create the Timer File
Now, create the timer file that controls the schedule.
sudo nano /etc/systemd/system/daily-backup.timer
Add the following configuration to run the script every day at 2:00 AM:
[Unit]
Description=Timer for nightly backup script
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Understanding the Timer Settings
- OnCalendar: This uses a highly readable format:
Year-Month-Day Hour:Minute:Second. The asterisks (*-*-*) mean “every year, every month, every day.” You can also use human-readable strings likeOnCalendar=dailyorOnCalendar=Mon,Tue *-*-* 04:00:00. - Persistent=true: This is the killer feature. If the server is offline at 2:00 AM, setting this to true ensures systemd will immediately run the missed backup script the moment the server boots back up.
Step 3: Enable and Start the Timer
After creating the files, you must reload the systemd daemon to recognize them.
sudo systemctl daemon-reload
Enable the timer so it starts automatically on boot:
sudo systemctl enable daily-backup.timer
Start the timer right now:
sudo systemctl start daily-backup.timer
Note: You only start the .timer file, never the .service file. The timer will handle starting the service.
Step 4: Managing and Troubleshooting
To see a beautiful, organized list of all active timers and exactly when they will run next:
systemctl list-timers
If your script fails, you don’t have to hunt through obscure syslog files. Systemd captures all standard output automatically. To view the exact logs for your backup job:
journalctl -u daily-backup.service
Conclusion
While a one-line cron job might seem faster to deploy, the lack of persistence and abysmal logging makes cron unsuitable for modern, mission-critical infrastructure. By transitioning to systemd timers, you gain enterprise-grade scheduling reliability directly from the Linux kernel’s native init system.