背景:我想在 USB-UART 设备连接时启动日志脚本。
我的/etc/udev/rules.d/10-local.rules
:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", ATTRS{serial}=="000621000000", SYMLINK+="ttymkw", TAG+="systemd", ENV{SYSTEMD_USER_WANTS}+="offnet-uart-log@$env{ID_SERIAL_SHORT}.service"
我的:~/.config/systemd/user/[email protected]
[Unit]
Description=Start log of UART
[Service]
ExecStart=sh -c "echo %I >> /tmp/systemd.test"
这并没有给我预期的价值ID_SERIAL_SHORT
。相反,我得到了很长的系统路径:
sys/devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1/3-1.7/3-1.7.2/3-1.7.2:1.0/tty/ttyACM0
当我尝试获取此路径的属性时(我需要删除前导sys
),我可以看到ID_SERIAL_SHORT
:
$ udevadm info --query=property --path /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1/3-1.7/3-1.7.2/3-1.7.2:1.0/tty/ttyACM0DEVPATH=//devices/pci0000:00/0000:00:1c.0/0000:01:00.0/0000:02:02.0/0000:39:00.0/usb3/3-1/3-1.7/3-1.7.2/3-1.7.2:1.0/tty/ttyACM0
DEVNAME=/dev/ttyACM0
MAJOR=166
MINOR=0
SUBSYSTEM=tty
USEC_INITIALIZED=1633350773062
[email protected]
ID_BUS=usb
ID_VENDOR_ID=1366
ID_MODEL_ID=1015
ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
ID_PCI_INTERFACE_FROM_DATABASE=XHCI
ID_VENDOR_FROM_DATABASE=SEGGER
ID_MODEL_FROM_DATABASE=DSL6340 USB 3.1 Controller [Alpine Ridge]
ID_VENDOR=SEGGER
ID_VENDOR_ENC=SEGGER
ID_MODEL=J-Link
ID_MODEL_ENC=J-Link
ID_REVISION=0100
ID_SERIAL=SEGGER_J-Link_000621000000
ID_SERIAL_SHORT=000621000000 ### <--- here
ID_TYPE=generic
ID_USB_INTERFACES=:020201:0a0000:ffffff:080650:
ID_USB_INTERFACE_NUM=00
ID_USB_DRIVER=cdc_acm
ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device
ID_USB_PROTOCOL_FROM_DATABASE=Interface Association
ID_PATH=pci-0000:39:00.0-usb-0:1.7.2:1.0
ID_PATH_TAG=pci-0000_39_00_0-usb-0_1_7_2_1_0
ID_MM_CANDIDATE=1
DEVLINKS=/dev/ttymkw /dev/serial/by-id/usb-SEGGER_J-Link_000621000000-if00 /dev/serial/by-path/pci-0000:39:00.0-usb-0:1.7.2:1.0
TAGS=:systemd:
$env{ID_SERIAL_SHORT}
在我的 udev 规则中似乎没有被属性的值替换。
udev 的手册页指出,$env{key}
替换仅适用于 NAME、SYMLINK、PROGRAM、OWNER、GROUP、MODE、SECLABEL 和 RUN 字段。
然而,我见过人们使用它的例子在ENV{SYSTEMD_USER_WANTS}
。显然这对我不起作用。
如何将设备的序列号传递给 systemd 模板?
编辑:我也尝试过这,但是不:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", ATTRS{serial}=="000621000000", SYMLINK+="ttymkw", PROGRAM="/bin/systemd-escape -p [email protected] $env{ID_SERIAL_SHORT}", ENV{SYSTEMD_WANTS}+="%c"
答案1
我正在寻找的参数是$attr{serial}
.我不确定为什么其他解决方案在适用于其他解决方案时不起作用,我猜它们已经过时了(编辑:这可能是因为我的规则文件(以 10- 开头)在创建环境变量 ID_SERIAL 的规则文件之前被读取,从 60- 开始)。这是工作:
udev规则:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1366", SYMLINK+="ttymkw", ENV{SYSTEMD_WANTS}+="offnet-uart-log@$attr{serial}"
系统模板:
[Unit]
Description=Start log of UART for a Offnet unit
[Service]
ExecStart=/bin/sh -c "/bin/echo %i >> /tmp/asdf.log"
显然我不需要TAG
,我需要$attr
使用$env
。
systemd 版本是 241。
这问答这对我有帮助。
编辑:不工作的一个原因$env
可能是ID_SERIAL_SHORT
在 60 级的规则上创建的,而我的文件是10-local.rules
.谢谢@yuwata。 (未经审核的。)
答案2
作为另一个解决方法,如果系统服务正在调用其中的脚本执行启动udevadm
声明中,问题中显示的相同调用可以包含在该脚本中以提取ID_SERIAL_SHORT
via grep
。
答案3
作为解决方法,我可以在 udev 规则中创建自己的环境变量:
SUBSYSTEM=="tty", ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", \
ATTRS{serial}=="000621000000", SYMLINK+="ttymkw", TAG+="systemd", \
ENV{MY_ID}="000621000000", \
ENV{SYSTEMD_USER_WANTS}+="offnet-uart-log@$env{MY_ID}.service"
(为了可读性,反斜杠应该在一行上。)
或者实际上,只需将字符串直接写在 后面即可@
。
但这些应该不是必需的。