Skip to main content

Helpful custom Systemd Timers and services

Intro

I thought I'd share some useful scripts for systemd that replace a cron daemon, and that I use on many of my Gentoo machines.  Since moving away from openrc, I had to relearn a bit, especially the daily cron jobs that I was so used to.  But I will trade crontab -e for journalctl functionality any day-- so useful.  Anyways, I no longer have any crons installed.  What to do?  I have 1 Gentoo headless file server that needs to run all of these services, 1 desktop (the "bulldozer") and a couple laptops that need to run a subset of these services.

1. Eix-sync Service and Timer

I have the excellent eix program installed, and use the wrapper eix-sync for portage and overlay syncing and eix database updating in one shot.  Naturally, I want to run this daily for all my machines, and I have my server as a local portage mirror (just a matter of changing the make.conf SYNC setting on the clients: SYNC="rsync://jwilly/gentoo-portage").  Thus, the service need for systemd.  Putting this is crontab was super easy.  Here's how to do it for systemd.  Soon you'll see it's almost as easy, just a few things to understand and watch out for.

I give credit to solpeth for the idea and simple howto.  It's basically a copy of his/hers.

The idea is that a timer file is running (started and enabled by user), which will trigger a service file (not enabled by user) to run at a specific time of day, or week, or whatever, and repeat.  Hence why it's called a timer.  The service file that's triggered will run whatever script or program you want once, repeating as dictated by the timer file.  I have my timer setup to trigger once a day, everyday.

My /etc/systemd/system/eix-sync-daily.service, which is not enabled nor started, but is triggered by the timer file:

[Unit]
Description=eix-sync

[Service]
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/usr/bin/eix-sync

The timer file, /etc/systemd/system/eix-sync-daily.timer, is what triggers the service.  The timer is enabled and started, and you can see that it is setup to run daily:

[Unit]
Description=Run eix-sync daily

[Timer]
OnCalendar=daily
Persistent=true
Unit=eix-sync-daily.service

[Install]
WantedBy=timers.target

OnCalendar=daily will run at about midnight every night.  It isn't exact timing, but it's usually within a minute or two.  More timing info can be found on freedesktop.org's man pages: systemd.timer and systemd.time.

I think you can see how to modify these two simple files to run almost any program, script you want.  In fact, that's exactly what I've done in the next section.

2. Blogger Post Daily Service and Timer

I help manage a blog which needs to post everyday.  I also didn't want to do this everyday, manually, so of course I figured out a way to let a script do this!  The script was written in python, of which I am no expert.  I expanded the systemd service+timer duo to make the script run everyday at midnight.  Actually, I post at 11pm so I can verify it before I sleep.  It's very similar to the eix-sync service+timer.

Here's the service file, /etc/systemd/system/post-tomorrows-daily-bible.service:  (Again, this is neither enabled nor started).

[Unit]
Description=post-tomorrows-daily-bible.service

[Service]
Type=simple
ExecStart=/usr/local/bin/post-tomorrows-daily-bible.sh
WorkingDirectory=/mnt/huge/share/Podcasts/RochDailyBible

I actually have a bash script that then runs the python script (I couldn't get the python script to run from the service file, not sure why).  

The bash script is simple:

#!/bin/bash
# Run Python script
(cd /mnt/huge/share/Podcasts/RochDailyBible && python blogger_setup_daily2.py)


The timer file, /etc/systemd/system/post-tomorrows-daily-bible.timer: (This one is enabled and started, of course)

[Unit]
Description=post-tomorrows-daily-bible.timer

[Timer]
OnCalendar=23:00
Unit=post-tomorrows-daily-bible.service

[Install]
WantedBy=timers.target

Notice the OnCalendar is literal, at 11pm.  It can take much more complicated, powerful timing parameters, but this works for what I need.

The scripts in order, in summary: timer triggers at 11pm calls the service, which then calls the bash.sh, which then calls the python.py.  

3. Delete Old Distfiles Daily Service and Timer

I was starting to fill up my harddrive with old distribution source files, and with Gentoo they reside in /usr/portage/distfiles.  There's only so much room for old libreoffice, ibm-jdk, and kernel sources!  Those are yesterday's duckies.  Ha, I think I had at one time 8 or 9 gigs and I needed storage for a few audiobooks.  Weeding those out looks like deleting anything that hasn't been accessed in 180 days. I figure that's plenty of time to keep things around.  Herein lies my service+timer and the cleaning script I run.

The service file, /etc/systemd/system/delete-old-distfiles.service:

[Unit]
Description=delete-old-distfiles-180

[Service]
#Type=simple
Nice=19
IOSchedulingClass=2
IOSchedulingPriority=7
ExecStart=/usr/local/bin/delete-old-distfiles.sh
WorkingDirectory=/usr/portage/distfiles

The bash script, /usr/local/bin/delete-old-distfiles.sh, to clean my distfiles not accessed in 180 days:

#!/bin/bash
echo ""
echo "Current Root filesystem usage:"
df -h | grep Filesystem
df -h | grep /dev/sda3
echo ""
echo ""
echo "Deleting distfiles older than 180 days..."
find /usr/portage/distfiles -maxdepth 1 -type f -atime +180 -delete
echo ""
echo "New Root filesystem usage:"
df -h | grep Filesystem
df -h | grep /dev/sda3
echo ""

 
The interesting part of the clean script is the "find" line, where I only go 1 level deep in the directory, look for only files that have an access time older than 180 days and delete them.

The timer file, /etc/systemd/system/delete-old-distfiles.timer:

[Unit]
Description=Run delete-old-distfiles daily

[Timer]
OnCalendar=daily
Persistent=true
Unit=delete-old-distfiles.service

[Install]
WantedBy=timers.target

Again, this one runs at midnight, like my first one.  


That's it for now.  Hope these examples help anyone who's trying to schedule tasks in systemd!

~JWilly

Comments

Popular posts from this blog

Update to USBmicroISP: 6pin and 10pin headers

Actually using my USBmicroISP with microcontrollers other than Arduino Uno's led me to fix a udev rule issue with my Gentoo Linux laptop.  I was getting Permission Denied when I was trying to use avrdude as a normal user.  Yes, my user is part of the 'uucp' group... Background Some background on the Arduino ISP connector.  It is much different than the 10-pin AVR connector... 6-pin ICSP cable pinout.  NOTE: Numbers refer to ATtiny45/85 pins, not ICSP! Arduino ISP pinout. Notice the vertical line next to pin 1, which appears in silkscreen on the PCBs. Redboard ISP pinout.  Obviously the same as UNO.  Notice pin 1 location on upper-left, with horizontal white silk. My USBmicroISP has the cables coming off the IDC differently, but the key is in the correct orientation to the pinout in the top picture! (Please disregard numbering on first picture for ICSP purposes)  Usually the key and wires are facing inward (left side on 2nd and 3rd ...

Harvey Barnstead SterileMax Retrofit

I recently did up a replacement controller PCB for a customer who was having runtime issues.  The replacement PCB and firmware exactly replaces the old 68k controller system.  It is a drop-in replacement with exactly compatible connectors, power supply, and input and output signalling. The SterileMax was a prolific autoclave, and can economically fulfill your needs. If you have this version or similar, you can use my replacement. The replacement PCB is MUCH smaller than the OEM. Replacement controller for the PC1277X1, top-side. The PCB is about 1/3 the size of the original.  It helps to not use any DIP parts. Schematic for the controller. If you're interested in this design or a slightly modified version for your sterilizer, comment below and I can hook you up. The main issue this solved was over-pressure in the chamber during a run.  The NVSRAM's battery died and it lost all the configuration data.  Once this happened the system w...

squashmount and aufs: Small footprint and high performance

Squashmount and aufs: Gentoo on tiny 4GB root! I came across a post about "squashing" certain directories on a Gentoo install (portage tree, portage db, /usr/src/, etc) much like those minimal-install-cd's use!  AuFS is an improved "union" filesystem.  I don't understand it all, but as a hardware engineer it's kinda like having a dual-port memory (I think).  Given that many of the directories I want to squash also contain many, many tiny files, mashing them all together increases performance on disk reads (supposedly). My Eee PC 901 still functioning... I was intrigued as my little netbook has its SDcard slot occupied for quite some time with a 32GB card for the /usr directory (2GB swap space as well!).  I wanted to change that.  I wanted to see if I could actually use my netbook as an " ultra-portable internet-connected enduring-battery system..." and happen to run a really snappy source distro!   The technique requires a very...