Linux Fu: Stupid Systemd Tricks [Hackaday]

View Article on Hackaday

Last time, I gave a whirlwind introduction to a very small slice of systemd. If you aren’t comfortable with systemd services, timers, and mounts, you might want to read that now. Otherwise, press on to see a few interesting uses for custom systemd units, including running a few things on a schedule and automatically mounting a Raspberry Pi Zero.

Can you do every one of these things in a different way? Of course you can. I’m not debating the relative merits of using or not using systemd. However, unless you totally control your own environment, good chance you are going to have to interact with systemd at some point.

Stupid Trick #1: Update Your IP Address

A few years ago, I talked about updating your remote DNS server with your public IP address. This lets you refer to a hostname like snoopy.hackaday.com and get back to your computer that often changes IP addresses. Sure, you can get services to do that for you, but you must either pay or agree to read ads on their site to keep your hostname going. This is all under your control. In the original post, I suggested using cron or NetworkManager to run the update script. I also hinted you could do it with systemd, but I didn’t tell you how. Let’s fix that.

Step one is simple: create a “one shot service” that executes the command required:

[Unit] 
Description=Update IP via SSH (called by timer) 

[Service] 
Type=oneshot 
ExecStart=/usr/bin/ssh awce ./updateip - wd5gnr.com dyn E
WorkingDirectory=/home/alw/bin

You can read about why that works in the original post. This is an easy-to-understand unit. A one-shot service runs once and then it is done The rest is the program to run and the working directory. Piece of cake.

Next, you need a timer. The timer’s name is the same as the service except for the extension. That is, updateip.service and updateip.timer go together.


[Unit] 
Description=Timer to update public IP via SSH 

[Timer] 
OnCalendar=*-*-* *:01,16,31,46:00 
Persistent=true 

[Install] 
WantedBy=timers.target


Here, we ask the system to run the code every hour of every day at minutes :01, :16, :31, and :46. It is persistent, so if a timer misses, it will run as soon as possible. In theory, we should make this all dependent on the network being up, but it doesn’t hurt to try and fail since if the network is down, this doesn’t matter.

Stupid Trick #2: Shut Up Baloo!

Recent versions of KDE love Baloo, the file indexer. While it is nice to instantly find files in your home directories, and it handles a few other tasks, it also is known to eat up system resources. I’ve used cgroups and other tricks to limit Baloo’s insatiable desire for CPU and I/O time. But what works best is to shut it down in the morning and let it start again late at night.

This is not quite the same as updating the IP address. For one thing, it happens at an absolute time. It would be easy, too, to have it do different times on the weekend, for example. The other thing to note is that this timer, as it is now, should probably not be persistent. It might be smarter to make it persistent and have one script that decides what to do based on the time, but I didn’t elect to go that way.

However, I did want to stop the timer from running if there was no GUI session. This is, it turns out, tricky. You’d think you could set the timer to be “WantedBy” the GUI target, but that’s not the case. Here’s how I turn off Baloo:


[Unit]
Description=Stop KDE's Baloo File Indexing Service
# Ensure this only runs in a graphical session by checking for the DISPLAY variable
ConditionEnvironment=DISPLAY

[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user stop kde-baloo

Note that the service actually calls systemd again to stop the predefined kde-baloo service. The ConditionEnvironment line means it only does this if there is a DISPLAY variable set. That’s not foolproof, but it should work for most caes.

You still need a timer:

[Unit]
Description=Timer to Stop KDE's Baloo File Indexing Service Daily at 06:45

[Timer]
OnCalendar=*-*-* 06:45:00
Persistent=true
Unit=baloo-off.service

[Install]
WantedBy=timers.target

Of course, the baloo-on pair looks just the same, with obvious changes to the service names and time specifications.

Stupid Trick #3: Automount your Raspberry Pi Pico

Another item systemd handles is mounting filesystems. What happened to fstab? Nothing. A special program reads fstab and creates systemd mount units for you automatically. The unit files wind up somewhere like /run/systemd/generator, at least on my system.

If you use the Raspberry Pi Pico, you’ve probably noticed that when it is in boot mode, it presents a different ID to the system each time. That makes it hard to tell the system to mount it automatically. However, it should have a constant label. Making systemd automount your Pi requires two files (in /etc/systemd/system). First, there is the .mount file:


[Unit]
Description=Mount Raspberry Pi Pico at startup

[Mount]
What=/dev/disk/by-label/RPI-RP2
Where=/media/alw/RPI-RP2
Type=vfat
Options=defaults

[Install]
WantedBy=multi-user.target

Then there is a .automount file with the same base name:


[Unit]
Description=Automount Raspberry Pi Pico

[Automount]
Where=/media/alw/RPI-RP2
TimeoutIdleSec=0

[Install]
WantedBy=multi-user.target

Speaking of the name, systemd expects a file that mounts at path /x/y/z to be named x-y-z.mount. That’s fine until you want to mount something at path /x/y-z. That’s because the name x-y-z.mount should go to /x/y/z, not /x/y-z. To solve this, the file name needs to have an escaped hyphen in it like this: media-alw-RPIx2dRP2.mount. That backslash needs to actually be in the file name, so you’ll have to quote or escape it in the shell, too.

Now, when you boot the Pi into bootloader mode, the system will mount it at the designated location.

That’s a Wrap!

Actually, that’s not a wrap. This shows nearly the bare minimum of what you can do with systemd. There is a question if it is desirable for one thing to do so much, but I’m trying to ignore that elephant. For today, systemd is here, and we might as well use it. If you work with others or deliver software to other users, it is a good bet you’ll have no choice.