在systemctl服务开始后执行udev的RUN语句

时间:2015-10-12 00:26:50

标签: udev systemd

我编写了一个守护程序,通过一个或多个RS232设备(通常为FT232R usb2serial)管理多种通信协议。 一旦出现/ dev / ttyUSB *设备,如果检测到某些属性, systemd被告知通过udev启动该守护进程:

ENV{SYSTEMD_WANTS}="%s{manufacturer}.service"

守护进程启动后,需要告知要打开哪个设备,我通过udev进行操作:

RUN="/usr/bin/sercomc open %E{sd_name} %E{sd_proto} %N"

所以完整的udev规则如下:

ACTION=="add", SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{manufacturer}=="sercomd", ENV{SYSTEMD_WANTS}="%s{manufacturer}.service", ENV{sd_proto}="%s{product}", ENV{sd_name}="%s{serial}", RUN="/usr/bin/sercomc open %E{sd_name} %E{sd_proto} %N"

现在问题是在守护进程启动之前执行了RUN 这个命令显然没有效果:

systemd-udevd[1638]: starting '/usr/bin/sercomc open ctl-vk1 ctserial /dev/ttyUSB0'
systemd-udevd[1632]: '/usr/bin/sercomc open ctl-vk1 ctserial /dev/ttyUSB0'(err) 'Couldn't connect to server: Connect failed: Connection refused'
[...]
sercomctl[1639]: [2015-10-12 03:05:39:291634] Serial communication daemon ver. 0.5 starting up

是否有推荐的解决方法,即在systemd完成启动服务后触发运行命令?

1 个答案:

答案 0 :(得分:0)

如果你偶然发现了类似的问题并阅读了这个问题,请不要让我们对使用中的软件名称感到困惑。让我们快速说“sercomd”是管理串行连接的守护进程的名称,“sercomc”是一个客户端程序,告诉sercomd使用某种协议打开该设备。 此外,我操纵了FTDI usb2serial芯片的EEPROM,使产品,制造商和串行字符串显示用户定义的值,我可以用它来“即插即用”自动识别串口适配器。

我正在做的是现在使用带有单元文件的instanciated服务 /lib/systemd/system/sercomd@.service 对于出现的每个设备。

udev规则现在为:

    SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{manufacturer}=="sercomd", ACTION=="add", SYMLINK="tty%s{serial}", PROGRAM="/bin/systemd-escape %s{serial}", ENV{SYSTEMD_WANTS}="sercomd@%c.service", ENV{sd_proto}="%s{product}", ENV{sd_dev}="%N"

此规则设置了一些环境变量sd_proto和sd_dev,以及第三个参数sd_dev,然后可以从sercomd @ .service文件中提取它:

    ExecStart=/bin/bash -c "eval $$( udevadm info --query=env --export /dev/tty%I ); sercomc open %I $$sd_proto $$sd_dev"
    ExecStop=/usr/bin/sercomc -l %I close

因此,每次从USB集线器添加或删除设备时,都会从systemd运行相应的客户端命令。 添加

    Requires=sercomd.service
    After=sercomd.service

到单元文件,它还将确保在客户端运行之前启动实际管理这些接口的守护进程。

相关问题