For decades, system administrators have relied on cron to schedule recurring tasks on Linux. While cron is simple and ubiquitous, modern Ubuntu systems use systemd, which provides a more robust and flexible alternative: systemd timers. Systemd timers offer several advantages over traditional cron jobs, including precise execution logging, dependency management, avoiding overlapping executions, and the ability to trigger tasks based on system events rather than just calendar time.
This guide explains how to create and manage systemd timers as a modern replacement for cron jobs on Ubuntu.
Understanding Systemd Timers vs Cron
Before creating a timer, it helps to understand why you might choose it over cron:
- No overlaps: If a script takes longer to run than the interval between executions, cron will start a second instance, potentially causing conflicts. Systemd timers will wait for the current execution to finish.
- Better logging: Output from a cron job is typically emailed or sent to a local mail file, which is often unconfigured and ignored. Systemd timer output goes directly into the systemd journal (viewable with
journalctl). - Dependencies: A systemd timer can wait for the network to be online or a specific database to be running before executing.
- Microsecond precision: Cron is limited to one-minute intervals. Systemd timers can trigger down to the microsecond.
The main trade-off is complexity. While cron requires a single line in a crontab, systemd timers require two separate files: a Service unit (what to run) and a Timer unit (when to run it).
Step 1: Create the Service Unit File
First, define the task that needs to be executed. We will create a service unit for a hypothetical backup script.
- Open a text editor to create a new service file in
/etc/systemd/system/. We will name itdaily-backup.service:
sudo nano /etc/systemd/system/daily-backup.service
- Add the following configuration:
[Unit]
Description=Daily Database Backup
Requires=network.target
After=network.target
[Service]
Type=oneshot
User=root
ExecStart=/opt/scripts/backup.sh
Notice there is no [Install] section. This service does not start automatically on boot; it will be triggered exclusively by our timer.
Step 2: Create the Timer Unit File
Now, create the timer unit that controls the schedule. The timer file must have the exact same name as the service file, but with a .timer extension.
- Create the timer file:
sudo nano /etc/systemd/system/daily-backup.timer
- Define the schedule. Here is an example that runs every day at 2:00 AM:
[Unit]
Description=Timer for Daily Database Backup
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Understanding the [Timer] Section
- OnCalendar: This defines the schedule using the format
DayOfWeek Year-Month-Day Hour:Minute:Second. The asterisks (*) mean “every”. So*-*-* 02:00:00means every year, month, and day at 2:00 AM. - Persistent=true: This is a crucial feature. If the server is powered off or rebooting at 2:00 AM, a traditional cron job simply misses its run. With
Persistent=true, systemd remembers the missed execution and runs the task immediately when the system boots up.
Alternative Scheduling Options
Systemd offers more flexible scheduling than cron. Instead of OnCalendar (absolute time), you can use monotonic time (relative time):
OnBootSec=15min— Runs 15 minutes after the system boots.OnUnitActiveSec=1h— Runs exactly 1 hour after the last time this timer triggered the service. (Use this to create a recurring interval, like running every hour).
Example of a timer running every hour:
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
Step 3: Enable and Start the Timer
After creating the files, reload systemd to recognise them:
sudo systemctl daemon-reload
Enable the timer to start automatically at boot (note: you enable the timer, not the service):
sudo systemctl enable daily-backup.timer
Start the timer immediately:
sudo systemctl start daily-backup.timer
Step 4: Verify and Manage Timers
To see all active timers on your system, when they next run, and when they last ran, use:
systemctl list-timers
You can check the specific status of your timer with:
systemctl status daily-backup.timer
To view the execution logs of your backup script, query the journal for the service (not the timer):
journalctl -u daily-backup.service
If you need to test your script immediately without waiting for the scheduled time, you can manually trigger the service:
sudo systemctl start daily-backup.service
While creating two files requires slightly more upfront effort than a single crontab entry, systemd timers provide a significantly more predictable, observable, and controllable environment for automating critical system tasks on Ubuntu.