Why am I writing this? I omitted installing the cron package on my Linux box since systemd provides a timers function. Who needs two packages to do one thing? Heh… for a moment I thought maybe I do because some of the documentation out there is a little confusing. Or I’m just dumb. Or both. 😛 So here’s a quick and dirty mash up of the Arch Linux wiki for User units and systemd Timers (because I want this to run when my user is logged in!).
Timers require two files – the service file and the timer file. I’m pretty sure you can call them whatever you want, including different names since the timer config references the service by its name. For simplicity, I named mine the same thing. User unit files live in the .config directory for systemd within your home dir. Here’s mine:
ls -l /home/jimmie/.config/systemd/user
drwxr-xr-x 2 jimmie jimmie 4.0K Jan 16 16:51 default.target.wants
drwxr-xr-x 2 jimmie jimmie 4.0K Jan 4 09:03 sockets.target.wants
drwxr-xr-x 2 jimmie jimmie 4.0K Jan 17 08:53 timers.target.wants
-rw-r--r-- 1 jimmie jimmie 179 Jan 16 16:43 update-blocklists.service
-rw-r--r-- 1 jimmie jimmie 142 Jan 16 16:45 update-blocklists.timer
The timer unit file (update-blocklists.timer) just tells systemd when to do a thing. This unit executes every 180 minutes.
[Unit]
Description=Run "Update Blocklists" every 180 minutes
[Timer]
OnBootSec=3min
OnUnitActiveSec=180min
[Install]
WantedBy=timers.target
The service unit file (update-blocklists.service) tells systemd what to do.
[Unit]
Description=Update Blocklists
After=network.target
[Service]
Type=oneshot
WorkingDirectory=%h
ExecStart=%h/Scripts/update-blocklists.sh
[Install]
WantedBy=default.target
The main parts here give some basic dependencies – execute only after the network is up, do the work in my homedir, and the location of the script to execute. I’m not going to post the contents of the script because you can go find it yourself here.
Once you have the unit files in place (and the script you want to execute, too) you can enable this thing. Trigger a daemon-reload first, then make sure you enter BOTH the service and the timer units on the line or your timer will not work. I know because I tried with one and then the other before using both. When I came back to the machine this morning nothing had updated since I manually triggered the service.
systemctl --user daemon-reload
systemctl --user enable --now update-blocklists.service update-blocklists.timer
Now you can list your user timers:
systemctl --user list-timers --all
NEXT LEFT LAST PASSED UNIT ACTIVATES
Wed 2024-01-17 11:53:51 EST 2h 59min Wed 2024-01-17 08:53:51 EST 25s ago update-blocklists.timer update-blocklists.service
1 timers listed.
Tada. Easy, right? Lastly, if you need to peep at the logs for your timer, journalctl can filter those! Check it out:
journalctl --user-unit update-blocklists
Happy Hump Day!