DEV Community

Celso Nery
Celso Nery

Posted on

Scheduling Tasks on Linux with Systemd Timers

🇧🇷 Leia a versão em português aqui.

Routines like automatic backups, log cleanup, or any script that needs to run at a fixed time are traditionally handled with cron. But on modern Linux distributions based on systemd, there's a native, more robust alternative: Systemd Timers.

Compared to cron, Systemd Timers bring a few practical advantages: direct integration with journalctl logs (making it easier to diagnose failures), support for Persistent=true (running missed tasks if the machine was off at the scheduled time), and configuration through unit files, following the same pattern used by any other system service.

In this article, I use a timer that runs an automated backup script daily as an example.

How it works

A Systemd Timer always works together with a Service of the same name: the .timer defines when the task should run, and the .service defines what should be executed. Both files need to have exactly the same base name for systemd to automatically associate them.

Creating the timer

Create a file in the /lib/systemd/system/ folder, choosing a name for the timer — for example, daily-db-backup.timer:

[Unit]
Description=Daily Docmost Backup Timer

[Timer]
OnCalendar=Mon..Sat 23:00
Persistent=true

[Install]
WantedBy=timers.target
Enter fullscreen mode Exit fullscreen mode

Explaining the main fields:

  • OnCalendar=Mon..Sat 23:00: defines when the task runs — in this example, every day from Monday to Saturday, at 11 PM;
  • Persistent=true: ensures that if the machine was off at the scheduled time, the task will run as soon as the system boots back up (instead of simply skipping that day's execution).

Creating the service

Create a second file in the same folder, using the same base name as the timer — in the example, daily-db-backup.service:

[Unit]
Description=Daily Docmost Backup Service

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/docmost-backup.sh

[Install]
WantedBy=default.target
Enter fullscreen mode Exit fullscreen mode

Where:

  • Type=simple: indicates the main process is the command defined in ExecStart itself (the most common type for scripts that run and finish);
  • User=root: defines which user the script will run as — adjust according to your script's permission needs;
  • ExecStart: full path to the script that will be executed when the timer fires.

The script path (/usr/local/bin/docmost-backup.sh, in the example) needs to exist and have execute permission (chmod +x) before activating the timer.

Activating the timer

After creating both files, reload systemd's configuration so it recognizes the new units:

systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

Enable and start the timer immediately:

systemctl enable --now daily-db-backup.timer
Enter fullscreen mode Exit fullscreen mode

⚠️ Notice that the name used in the enable command needs to exactly match the .timer file's name — a common mistake is typing a slightly different name (for example, daily-docmost-backup.timer instead of daily-db-backup.timer), which makes systemd complain that the unit doesn't exist.

Checking that it's active

To list all scheduled timers on the system, including the time of the next run:

systemctl list-timers --all
Enter fullscreen mode Exit fullscreen mode

This command shows columns like NEXT (next scheduled run) and LAST (last run), useful for confirming the schedule is correct.

Monitoring execution

To watch in real time whether the service is running correctly (or to investigate failures after the timer fires):

journalctl -f --system
Enter fullscreen mode Exit fullscreen mode

This command follows the system logs in real time (-f, for follow) — it's where you'll see both the script's output and any execution errors logged by systemd.

To specifically check the logs for the created service (without needing to manually filter through all system logs):

journalctl -u daily-db-backup.service
Enter fullscreen mode Exit fullscreen mode

Final thoughts

Systemd Timers are a modern, well-integrated alternative to traditional cron, especially useful when you already rely on systemd to manage other services on the machine — keeping everything under the same configuration pattern makes both maintenance and troubleshooting easier, since logs are centralized in journalctl alongside the rest of the system.

Top comments (0)