Not a Cron Comparison Link to heading
Cron may still have its place in Linux administration, but I won’t be weighing in on that. What I’ve found from my junior administrators is a willingness to utilize systemd, but they find a lot of information overwhelming. Below is a very simple guide for reliably running a script at a requested inverval.
Overview Link to heading
Systemd needs 2 files in order for this to work - a .service file that tells the server what to do, and a .timer file that tells the server when to do it. These need to have the same name - for example: certbot-renewal.service and certbot-renewal.timer. This guide assumes you want the scripts ran as the root user. Both .service and .timer files should be placed in /etc/systemd/system/.
Service Files Link to heading
See below for a simple example that I tend to utilize as a scaffolding file -
[Unit]
Description=Run Certbot Renewal with Standalone Web Server Mode
After=nginx.service
[Service]
Type=oneshot
ExecStartPre=/bin/systemctl stop nginx
ExecStart=/usr/bin/certbot renew --quiet --standalone
ExecStartPost=/bin/systemctl start nginx
[Install]
WantedBy=multi-user.target
I like to use the above as an example because it tiptoes into the power of systemd service files by allowing us to set actions before and after the main script runs. This example first stops the nginx web server, runs certbot on port 80 to renew a certifcate, and then starts nginx after its done.
Note that we use absolute paths in the scripts, we aren’t simply calling certbot we’re calling /usr/bin/certbot
Now that we have a series of actions that we want to take periodically, we now tell systemd when to start this service.
If you want to test or run these steps to validate your .service file, run systemd start certbot-renewal.service. This starts the service in the same manner the .timer file would, and in this case the service is of type=oneshot so it just runs the script exits. And thanks to systemd we get automatic logging, more on that later.
Timer Files Link to heading
Here is the corresponding .timer file for the certbot renewal service above -
[Unit]
Description=Run Certbot Renewal every week
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
By default, weekly means Monday morning at Midnight, and this can be observed by running
sytemd-analyze calendar weekly and you can get a view of all your timers (and their next run) with systemctl list-timers --all
You can also override the time/date if you want, below is a line that would run the .service at 4AM EST, every first of the month
OnCalendar=*-*-01 04:00:00 America/New_York
and here is every day at 4AM EST -
OnCalendar=*-*-* 04:00:00 America/New_York
After you have a .timer file, all you need to do is run
systemctl enable --now certbot-renewal.timer
--nowmakes sure the .timer is also started. Otherwise you’d have to runsystemctl start certbot-renewal.timeras well.
Free Logging Link to heading
You wrote a .service file and you want to follow its log file live for errors -
journalctl -u certbot-renewal.service -f
You need to verify its been successful or not by checking its top 50 lines in the logfile -
journalctl -u certbot-renewal.service -n 50
Its been a few days/weeks and the timer should have ran a few times, but you want to spot check it -
systemctl status certbot-renewal.timer
Wrapping Up Link to heading
Eagle-eyed readers already familiar with systemd will notice that I made an “error”. The .service and .timer files don’t actually need the same name, but that is the configuration by default and I find that its easier to teach when we assume that to be true.
Anyway, hopefully this quick guide will help someone out there get started with using systemd to schedule tasks. Its incredibly powerful, but in my experience, this simple example goes a long way.