3

I want to bind a user systemd timer (or service) to network events. For example consider this service:

[Unit]
Description=shows if connection changed

[Service] Type=oneshot Environment=DISPLAY=:0 ExecStart=notify-send "Network" "Status changed!"

How can I force this user service to run on network up/down events? I asked a similar question before. It seems I should use the PartOf= directive but what target should I use for this?

1- Note that I've defined this service in ~/.config/systemd/user/ so its scope is user-level. That means it can't depend on system targets.

2- If we define it as a system-level service, what is the proper hook (.target) that causes this service to trigger? I've monitored system service when I toggle the WiFi switch. Only NetworkManager-dispatcher.service gets triggered on such event and after doing its task, it gets de-activated. So it seems I can't depend on it. network.target, network-online.target, NetworkManager.service, network-manager.service are all loaded and active even when I turn off system's WiFi.

  • 1
    Don't hardcode DISPLAY. (notify-send doesn't even need DISPLAY, but still, don't hardcode DISPLAY.) Have startx or your desktop systemctl --user import-environment it instead. – u1686_grawity Sep 19 '21 at 16:02
  • @user1686 can you elaborate please? I thought by specifying DISPLAY=0 we can force notify-send use first monitor to render the notification. I didn't understand your solution also – Zeta.Investigator Sep 19 '21 at 16:21
  • 1
    No, that's wrong on several levels. 1) All your monitors are on the same X display. 2) Your X display isn't guaranteed to be ":0" (e.g. the login screen may be :0 and your desktop may be :1 instead). 3) notify-send doesn't render any notifications; it only sends a request to an already running "notification daemon". 4) The request isn't sent according to DISPLAY; it is sent according to DBUS_SESSION_BUS_ADDRESS. – u1686_grawity Sep 19 '21 at 17:34
  • @user1686 wow! thanks! I just copied that line from a post I saw in some website...That's the price of copying without research I guess – Zeta.Investigator Sep 19 '21 at 18:08
  • Relevant blog: https://andreas.scherbaum.la/blog/archives/963-if-up-and-if-down-scripts- with-systemd.html

    Seems to be impossible with systemd

    – Zeta.Investigator Sep 21 '21 at 08:09

1 Answers1

3

Run systemctl --user without any other parameters to see a listing of all units the user-level services can interact with. You will probably find something like sys-subsystem-net-devices-eno1.device.

But note that this might not be the optimal way to react on network status changes: instead, you could drop a script into /etc/NetworkManager/dispatcher.d/ or any of its sub-directories to be executed any time there is a network event. Read the DISPATCHER SCRIPTS chapter on man NetworkManager for details.

Or if it needs to be an user-level thing with no root access at all, you could connect into system D-Bus and monitor NetworkManager events. You might start with:

gdbus monitor --system --dest org.freedesktop.NetworkManager

and refine from there according to your specific needs. You might be looking for org.freedesktop.NetworkManager.StateChanged events, or some specific variety of org.freedesktop.NetworkManager.Connection.Active.PropertiesChanged events, for example.

Connecting into D-Bus might be the appropriate solution if you use more advanced scripting languages like Perl or Python, instead of just shell scripting; those languages have modules that can more easily interface with D-Bus.

telcoM
  • 96,466
  • Thanks. I'm already using the /etc/NetworkManager/dispatcher.d/ method for something else. So with only user level or even system level systemd, it is not possible to react to such events, right? – Zeta.Investigator Sep 19 '21 at 10:35
  • sys-subsystem-net-devices-*.device does not become inactive when I turn-off my WiFi – Zeta.Investigator Sep 19 '21 at 10:37
  • 1
    Yeah, that's what I was afraid of: systemd device units tend to concern only things like physically unplugging the device from the system. For things like network connection status, NetworkManager is the right point of contact if you have it. If you were using systemd-networkd for network configuration instead of NetworkManager, then you perhaps would have an applicable unit. – telcoM Sep 19 '21 at 10:54