How to Use Systemd Timers to Schedule Tasks in Ubuntu

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.

  1. Open a text editor to create a new service file in /etc/systemd/system/. We will name it daily-backup.service:
sudo nano /etc/systemd/system/daily-backup.service
  1. 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.

  1. Create the timer file:
sudo nano /etc/systemd/system/daily-backup.timer
  1. 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:00 means 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.