Systemd sleep.target for user level
At one point, I got carried away making a bunch of user level services for Systemd. It’s a neat way to run scripts during user sessions providing cool functionality like handling dependencies and automatic restarts. One issue I ran into was that I couldn’t create units depending on system level targets. I wanted to have some user level units that depended on the sleep.target, but I was blocked for a while. At some point I was introduced to dbus-monitor, which I immediately realized this could be used to build out monitor services to watch for system level events. I was able to create my own sleep.target using the following scripts and services. I’m sure this could be simplified, but this works fine for my purposes :)
~/.local/share/systemd/user/sleep.target
[Unit]
Description=User level sleep target
StopWhenUnneeded=yes
~/.local/bin/watch_sleep
#!/bin/bashdbus-monitor --system "type='signal',interface='org.freedesktop.login1.Manager',member=PrepareForSleep" | while read x; do
case "$x" in
*"boolean false"*) systemctl --user --no-block stop sleep.target;;
*"boolean true"*) systemctl --user --no-block start sleep.target;;
esac
done
~/.local/share/systemd/user/watch_sleep.service
[Unit]
Description=watch for sleep signal to start sleep.target
After=started.target[Service]
ExecStart=/bin/bash -c watch_sleep
Restart=on-failure[Install]
WantedBy=started.target
I use a started.target
which I start in my .zprofile after setting some env variables and adding them to systemd using dbus-update-activation-environment --systemd
, but you could replace that with default.target
. I also use /bin/bash -c
to run the script since that will pick up my PATH
, so you might need to change that with the full path.
Using a similar approach you could create some usable targets such asunlocked.target
using
~/.local/bin/watch_unlock
#!/bin/bashdbus-monitor --session "type='signal',interface='org.gnome.ScreenSaver'" | while read x; do
case "$x" in
*"boolean false"*) systemctl --user --no-block start unlocked.target;;
*"boolean true"*) systemctl --user --no-block stop unlocked.target;;
esac
done
You might be able to get some inspiration from my dotfiles (https://github.com/aiguofer/dotfiles). If you got some other cool targets or units, please share in comments!