How do I use ENV{SYSTEMD_USER_WANTS}= in udev rule?

5,721

Solution 1

You can try replacing SYSTEMD_USER_WANTS with MANAGER_USER_WANTS. I'm not 100% sure about this name change, but at least in systemd-226 there is no mention of SYSTEMD_USER_WANTS in the sources any more and it seems to be replaced by MANAGER_USER_WANTS. At least it worked for me for the similar case.

Solution 2

Although I still don't know how ENV{SYSTEMD_USER_WANTS} works, I managed to get my specific problem solved after reading this blog.

It turns out that I can install targets as a dependency on devices. I changed my unit file ~/.config/systemd/user/docked.target to:

[Unit]
Description=Docked to ThinkPad Mini Dock
BindsTo=dev-tp_mini_dock.device
After=dev-tp_mini_dock.device

[Install]
WantedBy=dev-tp_mini_dock.device

and my udev rule to:

SUBSYSTEM=="usb", ACTION=="add", ENV{ID_VENDOR}=="17ef", ENV{ID_MODEL}=="100a", SYMLINK+="tp_mini_dock", TAG+="systemd"

and then enable it with systemctl --user enable docked.target.

Now, when I dock it, the udev rule creates the systemd device, which in turn starts up the target. Then the BindsTo option makes sure that when the device disappears (gets unplugged) the target gets stopped.

I had to do some nonsensical magic to get this to work when I login with the dock already plugged in. One would imagine that simply adding default.target to WantedBy and After would be enough... I'll add a link to a blog after I write it.

Solution 3

Man... That problem made me sick as well, what a bug!

In my case, I wanted to listen to HDMI (monitor hotplug) events, and I found a trick how to work around this problem. I thought to myself, well, if this udev somehow knows that it started a service with this or that name and refuses to do it again, then let's make it believe that it starts a new service each time. All eyes on the corresponding udev event:

UDEV  [19214.534185] change   /devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0 (drm)
ACTION=change
DEVLINKS=/dev/dri/by-path/pci-0000:01:00.0-card
DEVNAME=/dev/dri/card0
DEVPATH=/devices/pci0000:00/0000:00:01.0/0000:01:00.0/drm/card0
DEVTYPE=drm_minor
HOTPLUG=1
ID_FOR_SEAT=drm-pci-0000_01_00_0
ID_PATH=pci-0000:01:00.0
ID_PATH_TAG=pci-0000_01_00_0
MAJOR=226
MINOR=0
SEQNUM=3364
SUBSYSTEM=drm
USEC_INITIALIZED=3280572

and notice the SEQNUM. It's changing on every new event and that's exactly what we want:

ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", ENV{SYSTEMD_USER_WANTS}+="monitor-hotplug@$env{SEQNUM}.service", TAG+="systemd"

Works like a charm even for ~/.config/systemd/user/[email protected]. Hopefully, your events also have SEQNUM or something similar.

Share:
5,721

Related videos on Youtube

aiguofer
Author by

aiguofer

Working as a freelance data engineer looking to leverage open source tooling while contributing back to the projects I use. I have experience working with a variety of databases including MariaDB, Postgres, Reshift, TEIID, Oracle, and MongoDB. Most data manipulation, exploration, analysis, automation, and reporting I do in Python, leveraging tools and libraries such as Pandas, Jupyter, Airflow, Bokeh/Plot.ly/Matplotlib, and SQLAlchemy. I've also authored a couple open source python libraries, gspread-pandas and sql_connectors.

Updated on September 18, 2022

Comments

  • aiguofer
    aiguofer over 1 year

    I want to set up a docked.target in my user level systemd. The idea is to run some services to configure my external displays.

    I currently have this as my rule:

    SUBSYSTEM=="usb", ACTION=="add", ENV{ID_VENDOR}=="17ef", ENV{ID_MODEL}=="100a", SYMLINK+="tp_mini_dock", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}="docked.target"
    

    The rule gets detected just fine (I can see dev-tp_mini_dock.device when I'm docked).

    I then have this in ~/.config/systemd/user/docked.target (also tried /etc/systemd/user with no luck):

    [Unit]
    Description=Docked to ThinkPad Mini Dock
    BindTo=dev-tp_mini_dock.device
    

    But this does not start when I dock. However, if I manually start docked.target while docked, it stops as expected when I undock.

    However, if I use ENV{SYSTEMD_WANTS}="docked.target" and put the file in /etc/systemd/system/docked.target, the target starts as expected when I dock. The problem then, is that my user level instance doesn't know about system-level services/targets.

    Any thoughts? I've seen a few other questions around the net, and one almost exactly like mine: https://bbs.archlinux.org/viewtopic.php?pid=1600019

    • Dawid Grzesiak
      Dawid Grzesiak almost 3 years
      The problem might be that you used ENV{SYSTEMD_USER_WANTS}="docked.target" instead of ENV{SYSTEMD_USER_WANTS}+="docked.target".