13

I'm running Arch Linux, and I have a udev rule which starts a service when a device is inserted. In this case, it dials a connection when a 3G modem is plugged in.

KERNEL=="ttyUSB*", SYMLINK=="gsmmodem", TAG+="systemd", ENV{SYSTEMD_WANTS}="netcfg@wvdial.service"

However, if the device is removed, systemd won't stop the service, and hence when it is plugged in again, it won't start the service, since it's already running.

What I need is a matching udev rule which runs when the device is removed to stop the service.

Update

Using the answer below, what I now have is the following udev rule

KERNEL=="ttyUSB*", SYMLINK=="gsmmodem", TAG+="systemd", ENV{SYSTEMD_WANTS}="vodafone.service"

with the following service file (which was basically copied and pasted from the netcfg service file:

[Unit]
Description=Netcfg networking service for Vodafone Dongle
Before=network.target
Wants=network.target
BindsTo=dev-gsmmodem.device
After=dev-gsmmodem.device

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/netcfg check-iface wvdial
ExecStop=-/usr/bin/netcfg down wvdial
KillMode=none

[Install]
WantedBy=multi-user.target

I'm using netcfg-wvdial from the AUR to do the dialing.

1 Answers1

13

Your problem may be solved using systemd solely, by simply specifying that your service Requires or, even better, BindsTo the given device.

Quoting:

"If one of the other [required/bound to] units gets deactivated or its activation fails, this unit [service] will be deactivated"

You just need to edit your service file like the following.

[Unit]
<...>
BindsTo=<DEVICE UNIT HERE>.device
<...>
After=<DEVICE UNIT HERE>.device

Note: to get a list of all available device unit files use systemctl list-units --all --full | grep ".device"

  • Does this mean that I don't need the udev rule? I tried to do as you suggested, by creating a new service file to replace the netcfg @wvdial.service and including those two lines. It does seem to stop the service now, but it doesn't start it when the device is plugged in again. – crazystick Sep 19 '13 at 11:25
  • @crazystick you still need the udev rule for starting the service, what I meant is you won't need to use udev to stop it. – brunocodutra Sep 19 '13 at 12:47
  • Got it. Works very nicely with both the udev rule and the modified service file. – crazystick Sep 19 '13 at 12:54
  • 2
    You can use StopWhenUnneeded=true instead BindsTo and After – SergA May 19 '16 at 09:32
  • @SergA by the time I answered this there was a bug preventing StopWhenUnneeded=true from working, but I believe it's been fixed for quite a while now. – brunocodutra May 19 '16 at 11:39
  • @brunocoduta just saw this bug. StopWhenUnneeded=true works well on systemd 215. – SergA May 19 '16 at 13:40