systemd vs. cron
Table of Contents
Are you currently using cron to schedule recurrent tasks? Have you heard of systemd timers and wondered "why not just use cron for this?". There are actually some good reasons to use systemd over cron and this article explores them. It covers the basics of both systems, the technical tradeoffs between them and finishes with a simple example you can use to get started scheduling with systemd.
1. Background
cron is an unix scheduling system that's almost 40 years old. It's very simple. You control it via a file called the crontab file. Each line is a rule to schedule a task of the form:
# ┌───────────── minute (0 - 59) # │ ┌───────────── hour (0 - 23) # │ │ ┌───────────── day of the month (1 - 31) # │ │ │ ┌───────────── month (1 - 12) # │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday; # │ │ │ │ │ 7 is also Sunday on some systems) # │ │ │ │ │ # │ │ │ │ │ # * * * * * <command to execute>
While the syntax is a little odd at first, the overall idea is simple. Just specify when you want your job to run and what command to execute and your set.
systemd on the other hand is a suite of programs used to orchestrate various linux processes. That's a vague description because systemd does many things and one of those is scheduling.
systemd's approach is different. It's broken down into two parts, what is run and when it's run. These are called services and timers. Since systemd is also a suite of many systems it comes with additional tools for scheduling such as logging and the ability to handle dependencies.
2. Comparison
The two systems have a very different approach to scheduling. cron provides the bare minimum while systemd has many features which, creates the trade offs listed below. Trade offs are listed in the order that I found them most compelling for using systemd (with features, debug-ability and staying power being the most important imo).
2.1. Features
cron is simple. You give it a time pattern and a command and it runs. systemd on the other hand has a ton of extras. Some of my favorites are:
- Jobs can be scheduled relative to the last run.
- Jobs that didn't run can be recovered from. For example, you have a daily job scheduled at midnight but your machine powers off from 10pm-2am. When it boots back up at 2am it can run that job.
- Jobs can have dependencies on other jobs.
- Built in logging makes it easy to monitor jobs.
Those are just a handful of systemd features. Check out the man page for systemd.timer
for more.
2.2. Debug-ability
cron is a pain to debug when it's not working because it doesn't have any quick and obvious indicators for when a job isn't working.
If your using cron, don't forget to redirect stdout and sterr to logs for easier debugging!If your using cron, don't forget to redirect stdout and sterr to logs for easier debugging!If your using cron, don't forget to redirect stdout and sterr to logs for easier debugging!If your using cron, don't forget to redirect stdout and sterr to logs for easier debugging!
systemd on the other hand has logging and it's easy to use:
journalctl -u your-service-here.timer
Another pain point for developing cron jobs is that there is no way to manually trigger them. The hack around this is to set the job to run every minute. Your development cycle then turns into a process of making changes and waiting for the end of a miute for your job to run. systemd is better because the underlying service is decoupled from the timer. You can simple run your service to see if it's working.
2.3. Staying Power
cron has been around for almost 40 years. It's not going anywhere anytime soon. In fact, it's probably already running on most machines.
systemd has been around for a little over a decade. From what I can tell it will also be around for a while. It's already in use on a large number of linux distros. I also have access to it on GCP. Also, development seems fairly active, with what looks like around 100 commits this past week. One thing that worries me is that the higher learning curve and non obvious configuration key naming might hinder it's future adoption, relative to cron.
2.4. Reliability
Given a program you want to schedule and run and two valid configurations on each system, which one is more reliable? This is an important question for a scheduling system. Given my experience with cron and limited experience with systemd there isn't a clear winner. I trust both given how long cron has been around and the fact that systemd is driving many linux distros.
2.5. Configuration Speed
cron is much easier to set up and use. You can have a job scheduled in under a minute. Also, there aren't any other steps after writting your configuration to a crontab file.
systemd is more involved. You need to write a service and a timer. Both service and timer have multiple options that need to be configured and picking the right ones takes time to research. Once your service and timer configurations are done you need to enable the timer. While this is more involved than cron the whole process doesn't take that much time as we'll see in the example below.
3. Example
Let's create a simple example. Let's say you want to run the command below every minute to create a files who's name is the time:
touch ~/$(date '+%H_%M_%S')
3.1. Service
The first thing you need to do is wrap this in a service. Services are defined by config files that live in /etc/systemd/system
and end with the suffix .service
. Below is our test service that we can save to /etc/systemd/system/test.service
[Unit] Description=A service that creates a file. [Service] Type=simple ExecStart=/bin/bash -c "touch /home/you/foo_$(date '+%H_%M_%S')"
Before we can run this we need ask systemd to reload all configurations so that it's aware of our new one.
systemctl daemon-reload
Now we are ready to run our service.
systemctl start test
Once it's done we can view the status of the service with
systemctl status test
3.2. Timer
Now that we have a service we can set up a timer to run it. The configuration file will go in the same directory as the service but this time we will use a .timer
extension instead of .service
. Let's save this timer into /etc/systemd/system/test.timer
[Unit] Description=Timer for the test service [Timer] # Every minute Unit=test.service OnCalendar=*-*-* *:*:0
Once again, we need to reload our configs.
systemctl daemon-reload
Now, we can start the timer:
systemctl start test.timer
Our service will run every minute until our machine turns off. If we want the timer to start every time we run our machine we can enable it with:
systemctl enable test.time
Enabling a timer doesn't start it right away! You need to run both commands.
Monitoring the timer is the same as with the service, except this time we include the .test
extension.
systemctl status test.timer
4. Conclusion
cron and systemd have different approaches to scheduling. cron is much simpler but lacks the features that systemd provides for fine tuning and debugging. cron has also been around much longer than systemd but both systems will likely be around in the near future.
Personally, I'm happy I gave systemd timers a try. While they do take more time to configure they are much more flexible than cron jobs. My favorite benefit is that they are easier to develop with.