Linux Fu: Stupid Systemd Tricks

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-RPI\x2dRP2.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.

15 thoughts on “Linux Fu: Stupid Systemd Tricks

    1. Yes, although I like it running on occasion. I have an overwrought system that uses cgroups to severely restrict it during the day and let it run full bore at night. My older system just cron jobbed it off in the morning, started it at night, and started/stopped it when the screen locker was active. But sometimes the indexer goes insane without cgroup limitations.

  1. hahahaha i was looking forward to find out how you interacted with the numerous ways to trigger off of network status changing. surely, you have to figure out how to wait for dhcp to stabilize before you can tell your ip to the dns server.

    using a timer instead. my god. article lives up to the headline :)

  2. I wanted to ask last article, is the systemd under discussion, the one folks on both sides kvetch about the same or largely the same as the systemd MacOs has or had?

    1. on macos i think startup / service management is “launchd”, which is unrelated to systemd. though i imagine they do similar tasks in a similar way but with every detail different.

      1. Are the details all different? Not sarcastic, I’m not THAT familiar with OSX and am really asking.

        I thought the RedHat/Poettering people that made SystemD were the “we want Linux to be OSX” crowd and that’s why they were always trying to change everything.

        1. i haven’t used systemd in 5 years, and OSX in 15, so take it with a grain of salt…but my understanding is that every detail is completely different. for example, launchd uses XML but systemd uses what looks like “ini file format” (if you remember it was introduced around MSDOS 5.0), so even just the way the config files encode structured key/value content is already different. systemd is very tightly coupled to the linux kernel (cgroups etc) and to linux gui/display systems. systemd is closely connected to linux udevd, which i guess doesn’t really have a macosx equivalent. and logind and dbus and so on, which aren’t the same on macosx either.

          honestly my impression is that launchd is more generic…i think you’d have an easier time running launchd on linux than systemd on macosx.

          they really do solve a lot of the same problems but they’re both pretty overarching, trying to integrate all of the quirks of the OS into one location so that the user can have a coherent experience. i mean really systemd has a huge overlap with android zygote as well, but again it’s totally different in every detail. these things are basically the center of all of the petty differences between OSes.

  3. “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.”

    Seriously? Is that the state of things now?
    I’ve been using dyndns.org for a lot of years now. I switched when the dynamic dns I used before that went belly up.. I want to say… ods.org? Anyway, when dyndns first started charging for certain services… they offered a lifetime purchase. So I haven’t been shopping.

    But.. I have noticed that when I set up my router to update it, there is a dropdown of dynamic dns providers and it is a LONG list. None of those are free? That’s sad.

    Speaking of that.. yah. That first “trick” is pretty cool. But… probably kind of niche since routers will do that for you. I like keeping my router in charge of updating the dynamic dns because the router is the device leasing the ip from my isp. It is the first device to know when an update needs to occur!

      1. I wanted to do that! But all the free ones are blacklisted by Netflix. And I don’t want to mess around with trying to route only ipv4 for Netflix and ipv6 for everything else.

  4. Generative Intelligence: Amend stupid trick #3, automount Raspberry Pi Pico, so that it is possible that user alw can write in /media/alw/RPI-RP2 without sudo or other escapes to root privilege.

  5. Restrict the resources that a program can allocate/demand:

    systemd-run –scope -p MemoryLimit=400M -p CPUQuota=67% firefox-esr

    I found it necessary to do this on a RPi 3B – Firefox was causing the whole thing to be very slow to respond. Now, it’s only Firefox that’s slow to respond! Lucky only need it rarely.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.