↓Skip to main content
  1. Categories
  2. Linux

Systemd

Stop using cron! Systemd Timers Explained

·5 mins
Stop using cron! Systemd Timers Explained

Stepping into the vast world of Linux, I was armed with a mission: schedule my Python backup script to run regularly. The criteria seemed straightforward — execute every 30 minutes, refrain from overlapping runs, and have an option for manual testing. Simple, right?

I was in for a surprise.

In this post I’ll be diving into the world of task scheduling on Linux, covering cron and systemd timers along the way.

1.0 Intro

Coming from a Windows background, I thought setting up scheduled tasks on Linux would be straightforward. Windows has been handling these tasks with ease for a long time. However, I quickly realized that Linux had its own set of challenges.

That’s where systemd comes in.

systemd manages services on many Linux distributions.

Info

Currently, systemd is the default for many popular Linux distributions, including:

  • Red Hat Enterprise Linux (RHEL)
  • CentOS
  • Ubuntu
  • Debian
  • SUSE
  • Arch

With that background, let’s dive into systemd timers and explore why they might be a better choice than the traditional cron.

2.0 Systemd Unit Files

Consider a typical crontab entry:

*/30 * * * * /usr/bin/python3 /path/to/your/script.py

This cron job runs at minute 0 and 30 of each hour. The systemd example below uses a boot-relative interval instead. Two separate unit files are needed:

  • Service File: Defines what you want to run.
  • Timer File: Specifies when and how the service should execute.

Here’s how these files are structured:

Service File (/etc/systemd/system/myscript.service):

[Unit]
Description=Execute my python script

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /path/to/your/script.py

Timer File (/etc/systemd/system/myscript.timer):

[Unit]
Description=Run myscript.service every 30 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=30min

[Install]
WantedBy=timers.target

After saving the files, load and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now myscript.timer
systemctl status myscript.timer

Replace the placeholder script path first. Record systemd --version and the distribution release when testing, and inspect the journal after both a scheduled run and a manual start.

3.0 Benefits

3.1 Non-overlapping

An already-active service is left running when its timer elapses; a second instance is not queued. This does not prevent someone running the script separately.

3.2 On-demand execution

Systemd allows you to manually start tasks:

$ systemctl start myscript.service

This feature enables immediate testing or intervention, removing the guesswork of “Will it run correctly next time?”.

You can also run a cron command manually. Starting the systemd service uses its configured execution environment and logging.

3.3 Unified Logging

systemd provides central logging through journald.

With the service’s default output settings, stdout and stderr go to the journal. Cron output can also be mailed or redirected to a log; the script does not need its own logging implementation.

To probe the logs for our myscript.service, execute:

$ journalctl -u myscript.service

This command retrieves the service’s activity logs, streamlining troubleshooting and performance assessment.

3.4 Granular Timing

OnCalendar accepts seconds, but the default AccuracySec=1min permits coalescing within a one-minute window. Tighten that window explicitly:

[Timer]
OnCalendar=*-*-* 12:00:15
AccuracySec=1s

This is not an exact-second guarantee: timer slack, system load and service startup can delay execution. Times use the local timezone unless specified otherwise.

For spreading work, use RandomizedDelaySec; AccuracySec primarily coalesces wake-ups:

[Timer]
OnCalendar=hourly
RandomizedDelaySec=15m

A boot-relative timer needs no persistence setting:

[Timer]
OnBootSec=15min

Persistent=true only affects OnCalendar timers. A calendar alternative to the boot-relative example is:

[Timer]
OnCalendar=*-*-* *:00,30:00
Persistent=true

Reactivation catches up with one invocation if at least one run was missed, not one per missed interval; any randomised delay still applies.

These semantics were checked against the official systemd.timer manual on 28 September 2026. The examples have not been rerun on a Linux host for this revision; check your installed man systemd.timer for version-specific behaviour.

3.5 Error Handling

Imagine a task fails. Rather than just shrugging it off, systemd can kick off another service to handle the mishap.

Dreaming of getting notified on Slack when something’s amiss? There’s a Slack notifier for that! Old school and prefer a trusty email? Dive into this mailto script.

In contrast, cron offers a simpler, more limited approach.

3.6 Birds Eye View

Gaining a unified perspective of all scheduled tasks in systemd is a breeze:

$ systemctl list-timers --all

This lists timers loaded by the system manager, including inactive ones. Use systemctl --user list-timers --all for the current user’s manager; it is not an inventory of every user’s timers. See the systemctl manual.

Contrast this with cron. Each user’s tasks lie within individual crontabs. To inspect, you’d hop between users:

$ crontab -u <username> -l

And don’t forget the system wide tasks in /etc/crontab and /etc/cron.d. In this realm, systemd offers clarity where cron asks for a scavenger hunt.

3.7 Dependencies

Systemd timers execute tasks intellligently.

Ever been in a situation where you need to confirm a database service is alive and kicking before running that crucial backup?

Systemd’s got your back:

[Unit]
Description=Backup service
Requires=database.service
After=database.service

What about ensuring NFS file shares are mounted beforehand?

[Unit]
Description=MySQL backup task
Requires=mybackupshare.mount
After=mybackupshare.mount

4.0 Drawbacks

4.1 Complexity

Cron’s beauty lies in its simplicity.

Simply drop a line in a crontab you’ve got a task set to run periodically:

* * * * * /path/to/script.sh

On the flip side, systemd, while undeniably robust, can feel like a double-edged sword. Setting up a timer isn’t a brief affair. It mandates two separate unit files: the service and the timer.

Essentially, you’re looking at double the configuration, doubling the chances for an oversight.

5.0 Summary

Cron and systemd timers serve distinct roles in the Linux world. While cron remains the go-to for straightforward scheduling, systemd timers cater to modern system management with precise timing, advanced error handling, and dependency management capabilities.

Choosing between the two boils down to the task at hand. Having both tools in your toolkit ensures you’re well-prepared for any scheduling challenge.

Thanks for reading, and happy scheduling!