Systemd user unit that depends on system unit (sleep.target)
六月 15, 2024 [C/C++] #Linux #obsidian #编译链接Systemd user unit that depends on system unit (sleep.target)
You can do the following to achieve sleep.target (and a complementary awake.target) in userspace:
Create the following service template in /etc/systemd/system/sleep@.service
[Unit]
Description=%I sleep hook
PartOf=sleep.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemctl --user --machine=%i@ start sleep.target
ExecStop=/usr/bin/systemctl --user --machine=%i@ start awake.target
[Install]
WantedBy=sleep.target
Create an instance of it for your user (don't start it):
sudo systemctl enable sleep@$(whoami)
Now for the equivalent sleep.target for users:
[Unit]
Description=User-level Sleep Target
Conflicts=awake.target
And awake.target:
[Unit]
Description=User-level Awake Target
Conflicts=sleep.target
[Install]
WantedBy=default.target
Enable with systemctl --user enable awake.target so that it starts at login
When either of these targets are reached, they stop the other target, thanks to the Conflicts directive, which makes them mutually exclusive targets.
For my use-case, I actually found the awake.target to be more useful than the sleep.target because I could make some user services use the PartOf directive to start and stop with it.
The only use-case I could think of that would benefit from the sleep target is if someone was trying to make use systemd-inhibit to do some last minute cleanup before the system goes to sleep. This would also mean delaying the actual sleep target until after the work is done.
may deal with
systemd --userruns as a separate process from thesystemd --systemprocess. User units can not reference or depend on system units.
You can also create a "proxy" for all your sleep/suspend targets between service and user instances.
Create this file on /etc/systemd/system/suspend@.service:
[Unit]
Description=Call user's suspend target after system suspend
After=suspend.target
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl --user --machine=%i@ start --wait suspend.target
[Install]
WantedBy=suspend.target
And enable it by running sudo systemctl daemon-reload && sudo systemctl enable suspend@youruser.
Now create your user suspend.target at ~/.config/systemd/user/suspend.target:
[Unit]
Description=User level suspend target
StopWhenUnneeded=yes
Wants=my-etc-service.service
Then add your services on the Wants list and make sure to run systemctl --user daemon-reload
or using this solution
Adding to the response from @kyrias, here's a way to create your own user level sleep.target:
~/.local/share/systemd/user/sleep.target
[Unit]
Description=User level sleep target
StopWhenUnneeded=yes
~/.local/bin/watch_sleep
#!/bin/bash
dbus-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
[Service]
ExecStart=%h/.local/bin/watch_sleep
Restart=on-failure
[Install]
WantedBy=default.target