14

On my Linux (Angstrom distro on BeagleBone Black) I have a USB dongle which presents as a serial port and per default is available as /dev/ttyUSB0

I want to start a daemon, which will connect to the serial port and make it available as a socket. I have the code for this USB-to-socket bridge and it works when started by hand.

I want it to start automatically whenever the system boots, supposing the USB dongle is plugged in. How should I do this?

Attempts so far:

  1. systemd: I created a systemd service with conditions After: remote-fs.target and After:syslog.target , but (it seems) the USB dongle is not ready at that point and the startup of the daemon fails.

    Are there other systemd targets or services to condition to, so that the daemon is started only when the udev has finished installing devices and the network is ready?

  2. udev: I created a udev rule like

    KERNEL=="ttyUSB?", RUN+="/path/to/daemon.sh"

    which executes successfully. But the daemon (which is started as a background process with a "&" within that script) seems not to execute. Also it seems to be frowned upon, to fork long running processes from udev rules.

What is the correct way to do it?

Philipp
  • 4,659
  • 9
  • 48
  • 69
  • I had a similar problem a while ago, this blog article helps me a lot (since it's almost exactly what you are trying to do). [Proper(-ish) way to start long-running systemd service on udev event (device hotplug)](http://blog.fraggod.net/2012/06/16/proper-ish-way-to-start-long-running-systemd-service-on-udev-event-device-hotplug.html) – morten.c Aug 27 '13 at 11:17
  • Thanks for the reference, it now works! – Philipp Aug 27 '13 at 12:03

2 Answers2

20

Create a udev rule like

# cat /etc/udev/rules.d/95-serialdaemon.rules
KERNEL=="ttyUSB0", TAG+="systemd", ENV{SYSTEMD_WANTS}="serialdaemon.service"

Create a systemd service like

# cat /lib/systemd/system/serialdaemon.service
[Unit]
Description=USB serial to socket bridge
After=remote-fs.target
After=syslog.target

[Service]
ExecStart=/mnt/serialdaemon.sh

Create the executable file

# cat /mnt/serialdaemon.sh
#!/bin/sh
date +%F-%T >> /var/log/serialdaemon.log
/usr/local/serialdaemon/serialdaemon -serial /dev/ttyUSB0 -port 15789 -baud 38400 >> /var/log/serialdaemon.log 2>&1
date +%F-%T >> /var/log/serialdaemon.log
ftl
  • 3,014
  • 1
  • 24
  • 25
Philipp
  • 4,659
  • 9
  • 48
  • 69
  • 1
    You can just mark your own anwser as "accepted", since it's the right solution for your problem. Nothing wrong about it... – morten.c Aug 27 '13 at 12:26
  • The file locations could be improved though: the `.service` file should be placed in `/etc/systemd/system` and the executable in `/usr/local/bin`. – Victor Klos Nov 12 '20 at 10:19
5

Since the link in my further comment seems to solve this problem, here is the solution for using udev for starting a daemon when a certain usb device is plugged in:

Proper(-ish) way to start long-running systemd service on udev event (device hotplug)

morten.c
  • 3,414
  • 5
  • 40
  • 45
  • 2
    Accepting your answer so you get the points. Mine's there just for (my own) reference. – Philipp Aug 27 '13 at 12:32
  • This link gives workable solution, but in case this link gets broken in future, please also copy-paste the gist of contents from that link in your answer. Of course, you will need to give due credit by mentioning the original link. – anishsane Dec 10 '15 at 04:29
  • @anishsane Sorry for that, you're correct. This was one of my first posts on SO, if I've written the answer today, I would have done that. I will add a summary of the solution provided in the link if I have some spare time. – morten.c Dec 14 '15 at 15:22
  • No issues. I was just saying it as a general guideline... Besides, this helped me recently :) – anishsane Dec 14 '15 at 15:25