For decades, Linux administrators have relied on cron to schedule recurring background tasks, such as nightly database backups or weekly log rotations. While cron is incredibly simple to use, it is a relic of the 1970s. It lacks native logging, it struggles with handling missed jobs if the server was powered off during the scheduled time, and it has no concept of dependencies (e.g., “do not run the backup script until the network is active”).
In modern Linux distributions (Ubuntu, RHEL, Debian), the init system has been completely replaced by systemd. Along with managing services, systemd includes a powerful, modern replacement for cron called systemd timers.
The Two-File Architecture
Unlike a single line in a crontab file, a systemd timer requires two separate configuration files. This separation of concerns makes systemd infinitely more flexible.
- The Service File (.service): Defines what command or script to execute.
- The Timer File (.timer): Defines when to execute that service file.
Step 1: Create the Service File
First, we must define the job we want to run. We will create a simple service that runs a hypothetical backup script.
Open your terminal and create a new service file using the nano text editor:
sudo nano /etc/systemd/system/daily-backup.service
Add the following configuration:
[Unit]
Description=Run the daily backup script
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Save and close the file. (Notice there is no [Install] section. We do not want this service to start on boot; we only want the timer to trigger it).
Step 2: Create the Timer File
Next, we create the timer file. It must have the exact same name as the service file, but with a .timer extension.
sudo nano /etc/systemd/system/daily-backup.timer
Add the following configuration to schedule the job to run every day at 2:00 AM:
[Unit]
Description=Timer for daily backup script
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Understanding the Timer rules:
OnCalendar: This is the systemd equivalent of the cron schedule. The syntax isYear-Month-Day Hour:Minute:Second. The asterisks mean “every year, every month, every day” at exactly 02:00:00.Persistent=true: This is the killer feature that cron lacks. If the server is offline for maintenance at 2:00 AM, systemd will remember that the job was missed, and will immediately run the backup script the exact second the server boots back up.
Step 3: Enable and Start the Timer
Because you added new files to the systemd directory, you must reload the daemon so it recognizes them.
sudo systemctl daemon-reload
Now, enable the timer so it starts automatically every time the server boots, and start it for the current session.
sudo systemctl enable --now daily-backup.timer
How to Check Your Scheduled Timers
To verify that your timer is active and to see exactly when it will trigger next, systemd provides a fantastic visualization tool. Run this command:
systemctl list-timers --all
This will output a clean, organized table showing the exact date and time your job will run, how much time is left until execution, and the exact time it last executed. Furthermore, any output or errors generated by your backup script will be automatically captured by the system journal, meaning you can easily debug failures by typing sudo journalctl -u daily-backup.service.