I'm running a daemon that needs a path to a device when it starts. This device is connected to the USB bus but sometimes drops off the USB and reconnects again (either a loose connector or crashing hardware, have not found the problem yet), and but then the device gets another name, say, /dev/ttyACM0 becomes /dev/ttyACM1.

It's a virtual serial port that spits out NMEA data from an AIS receiver (Quark-elec QK-A022 for the interested).

I'm pretty sure only one device will ever be connected at the same time to the USB.

Is there a way to start/restart a service with systemd when a specific kind of device is inserted in the system? I noticed systemctl list-units --type=device which lists the device so I'm hopeful, but every example I've found thus far is based on explicitly starting servicename@device.

root@ais:/home/pi# systemctl list-units --type=device | fgrep STM
sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.2-1\x2d1.2:1.0-tty-ttyACM1.device                      loaded active plugged STM32F407

I'm pretty sure only one device will ever be connected at the same time to the USB.

  • While I do not have a precise answer, I would recommend to check man systemd.service or any other systemd.* man pages. Other than that, I would possibly have a script run periodically (or through inotifywait) to check on the status and then have that script restart the systemd item. – Phoenix May 26 '18 at 23:04

These days the canonical way to run a daemon when a device is plugged in seems to be to create a systemd Unit for the daemon, and add a udev entry for the device referring to this Unit. For example, create a file /etc/udev/rules.d/90-my.rules with the line

ACTION=="add", KERNEL=="ttyACM*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="myacm@%k.service"

and a file /etc/systemd/system/myacm@.service with

Description=my serial daemon for ttyACM0
ExecStart=/bin/myscript %i

You may need sudo udevadm control --reload and sudo systemctl daemon-reload. When you plug in your device your script should be run with the parameter ttyACM0 if that is its name. Check the log files for errors.

See man 7 daemon section New-Style Daemons and Device-Based Activation, as well as man systemd.device.

  • I had to reboot but to get it working but other then that this works. What is the difference between a file in /etc/systemd and /lib/systemd? And, another question perhaps, how do you stop the script if the device is ejected again? I've found ACTION='remove', RUN+='pkill...' but that seems rather unelegant. – Mrten May 28 '18 at 15:12
  • See man file-hierarchy. /etc/ is for the local administrator to use. – meuh May 28 '18 at 15:16

I don't know whether you can do that within systemd but you could use udev for restarting / reloading the service if it detects a device change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.