Ali Şentaş

Setting up a simple systemd timer

This article is also available in Turkish.

I’ll keep this short, for my app KOU Cafeteria, I had written a simple Python script which retrives and parses cafeteria menu from schools website. The script worked and still works fine but there was one slight problem. I had to call the script the first thing every month, and sometimes I forgot that and it made me lose a lot of users. Also one time the school changed the menu but the app didn’t so.. (ciao more users). But I had enough, I knew I had to set up a cron job but I knew nothing about them (tried to set one but couldn’t) so I thought learning how systemd timers work wouldbe a good idea.

I’ll write here what I did to set up a timer correctly

Write a shell script

First thing one should do (this is the same for cron jobs) is to write a shell script which calls your python script with the absolute path. Something like this:

/usr/bin/python3 /home/ali/path/to/my/script.py

In your scripts, prepend every file with their absolute names or they won’t work.

Set up a systemd service

Go to /etc/systemd/system/ and create your a file called myscript.service. In it one should write:

[Unit]
Description=A short description for your script or service

[Service]
ExecStart=/bin/bash /home/ali/path/to/your/script.sh

Description is pretty self-explanatory and ExecStart tells the service what should it do to start the service. Here we tell that it should run our .sh file with bash.

Important thing to note here is that you should prepend your scripts path with /bin/bash or your service won’t work.

Now that you created your service it’s time to enable it. Enter

sudo systemctl enable myscript.service

Create a .timer file

Now for the last step, in that same directory we need to create a .timer file. Create a file called myscript.timer and enter this in it:

[Unit]
Description=Runs script every 60 seconds

[Timer]
# Time to wait after booting before we run first time
OnBootSec=10min
# Time between running each consecutive time
OnUnitActiveSec=60
Unit=myscript.service

[Install]
WantedBy=multi-user.target

Again [unit] is self-explanatory, important part here is [timer] part. OnBootSec sets how much the service should wait after system has been booted. OnUnitActiveSec sets script should be called every x seconds. x here is 60, I want my script to run every minute, that’s how you do it with systemd timers. Unit defines which unit file should run after timer fires.

After having done that you need to enable and start your service:

sudo systemctl enable myscript.timer
sudo systemctl start myscript.timer