我的 udev 规则有什么问题?

我的 udev 规则有什么问题?

我想在连接特定键盘时执行脚本。这是我的尝试和我收集的数据。

煮完后,这是我仍然遇到的最小问题:

/etc/udev/rules.d/99-kinesis-testing-high-number.rules:

ACTION=="add", RUN+="/bin/sh -c '/bin/echo UDEV > /tmp/layout_kinesis.log'"

重新加载并触发:

 sudo udevadm control --reload-rules && sudo udevadm trigger

/tmp/layout_kinesis.log连接 USB 设备后文件中没有任何反应。

这个最低限度的规则有什么问题吗?

乌班图20.04。


这是来自/var/log/syslog

Mar 30 08:24:25 ionian mtp-probe: checking bus 2, device 96: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2"
Mar 30 08:24:25 ionian mtp-probe: bus: 2, device: 96 was not an MTP device
Mar 30 08:24:25 ionian systemd-udevd[59515]: 2-1.1.2: /etc/udev/rules.d/99-kinesis-testing-high-number.rules:1 Failed to write ATTR{/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2/idProduct}, ignoring: Permission denied
Mar 30 08:24:25 ionian systemd-udevd[59515]: 2-1.1.2: Process '/bin/sh -c '/bin/echo UDEV > /tmp/layout_kinesis.log'' failed with exit code 2.
Mar 30 08:24:25 ionian systemd-udevd[59515]: 2-1.1.2:1.0: /etc/udev/rules.d/99-kinesis-testing-high-number.rules:1 Failed to write ATTR{/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2/2-1.1.2:1.0/idProduct}, ignoring: No such file or directory
Mar 30 08:24:25 ionian systemd-udevd[59513]: 2-1.1.2:1.1: /etc/udev/rules.d/99-kinesis-testing-high-number.rules:1 Failed to write ATTR{/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2/2-1.1.2:1.1/idProduct}, ignoring: No such file or directory
Mar 30 08:24:25 ionian systemd-udevd[59515]: 2-1.1.2:1.0: Process '/bin/sh -c '/bin/echo UDEV > /tmp/layout_kinesis.log'' failed with exit code 2.
Mar 30 08:24:25 ionian systemd-udevd[59513]: 2-1.1.2:1.1: Process '/bin/sh -c '/bin/echo UDEV > /tmp/layout_kinesis.log'' failed with exit code 2.

该规则似乎会触发(尽管我不确定为什么它会弹出三次)。我找到了一个数字问题 在线的关于只读 文件udev 系统。

所有这些链接似乎都在以只读方式挂载 udev 的文件系统时出现问题。但我不确定我是否也是这样:

$ ps aux|grep udev
root       61004  0.0  0.0  23816  7416 ?        Ss   09:00   0:00 /lib/systemd/systemd-udevd
$ less /proc/61004/mounts
/dev/sda1 / ext4 rw,relatime,errors=remount-ro 0 0

它说rw,但它也说errors=remount-ro......


以下是我如何到达那里的详细信息:


lsusb给我总线和设备(002 和 048):

$ lsusb
Bus 002 Device 008: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 002 Device 007: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
Bus 002 Device 010: ID 045e:0b12 Microsoft Corp. 
Bus 002 Device 048: ID 05f3:0007 PI Engineering, Inc. Kinesis Advantage PRO MPC/USB Keyboard
Bus 002 Device 047: ID 05f3:0081 PI Engineering, Inc. Kinesis Integrated Hub

从那里,udevadm给了我属性:

$ sudo udevadm info --attribute-walk /dev/bus/usb/002/048

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2':
    KERNEL=="2-1.1.2"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{devpath}=="1.1.2"
    ATTR{bcdDevice}=="0320"
    ATTR{devnum}=="48"
    ATTR{bMaxPower}=="64mA"
    ATTR{bMaxPacketSize0}=="8"
    ATTR{quirks}=="0x0"
    ATTR{tx_lanes}=="1"
    ATTR{bNumInterfaces}==" 2"
    ATTR{idProduct}=="0007"
    ATTR{speed}=="12"
    ATTR{bConfigurationValue}=="1"
    ATTR{configuration}==""
    ATTR{busnum}=="2"
    ATTR{bDeviceClass}=="00"
    ATTR{maxchild}=="0"
    ATTR{bNumConfigurations}=="1"
    ATTR{idVendor}=="05f3"
    ATTR{ltm_capable}=="no"
    ATTR{bDeviceSubClass}=="00"
    ATTR{avoid_reset_quirk}=="0"
    ATTR{bmAttributes}=="a0"
    ATTR{urbnum}=="427"
    ATTR{bDeviceProtocol}=="00"
    ATTR{removable}=="fixed"
    ATTR{version}==" 1.10"
    ATTR{rx_lanes}=="1"
    ATTR{authorized}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1':
    KERNELS=="2-1.1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{devnum}=="77"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bcdDevice}=="0320"
    ATTRS{idVendor}=="05f3"
    ATTRS{urbnum}=="31"
    ATTRS{manufacturer}=="PI Engineering"
    ATTRS{devpath}=="1.1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bMaxPower}=="50mA"
    ATTRS{idProduct}=="0081"
    ATTRS{ltm_capable}=="no"
    ATTRS{configuration}==""
    ATTRS{bConfigurationValue}=="1"
    ATTRS{maxchild}=="4"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{tx_lanes}=="1"
    ATTRS{version}==" 1.10"
    ATTRS{busnum}=="2"
    ATTRS{rx_lanes}=="1"
    ATTRS{speed}=="12"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{removable}=="unknown"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{product}=="Kinesis Keyboard Hub"
    ATTRS{quirks}=="0x0"
...

因此,我得到的 udev 规则如下/etc/udev/rules.c/90-kinesis-advantage.rules

SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="05f3", ATTR{idProduct}=="0007", RUN+="/bin/echo aaa >> /tmp/layout_kinesis.log"

然后重新加载规则:

$ sudo udevadm control --reload-rules && sudo udevadm trigger

并监控输出文件:

$ tail -f /tmp/layout_kinesis.log

但断开并重新连接键盘没有任何反应。


我也尝试过匹配父母,但没有运气:

SUBSYSTEMS=="usb", ACTION=="add", ATTRS{idVendor}=="05f3", RUN+="/bin/sh -c 'echo aaa >> /tmp/layout_kinesis.log'"

还尝试删除sh并尝试此操作,但不行:RUN+="/bin/echo aaa >> /tmp/layout_kinesis.log"


最后一个add条目udevadm monitor -e是:

UDEV  [51347.305368] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2/2-1.1.2:1.1/0003:05F3:0007.003C/input/input112/event6 (input)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2/2-1.1.2:1.1/0003:05F3:0007.003C/input/input112/event6
SUBSYSTEM=input
DEVNAME=/dev/input/event6
SEQNUM=26402
USEC_INITIALIZED=51347305171
ID_INPUT=1
ID_INPUT_KEY=1
ID_VENDOR=05f3
ID_VENDOR_ENC=05f3
ID_VENDOR_ID=05f3
ID_MODEL=0007
ID_MODEL_ENC=0007
ID_MODEL_ID=0007
ID_REVISION=0320
ID_SERIAL=05f3_0007
ID_TYPE=hid
ID_BUS=usb
ID_USB_INTERFACES=:030101:030000:
ID_USB_INTERFACE_NUM=01
ID_USB_DRIVER=usbhid
ID_PATH=pci-0000:00:1d.0-usb-0:1.1.2:1.1
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_1_2_1_1
XKBMODEL=pc105
XKBLAYOUT=us
XKBVARIANT=
XKBOPTIONS=
BACKSPACE=guess
LIBINPUT_DEVICE_GROUP=3/5f3/7:usb-0000:00:1d.0-1.1
MAJOR=13
MINOR=70
DEVLINKS=/dev/input/by-path/pci-0000:00:1d.0-usb-0:1.1.2:1.1-event /dev/input/by-id/usb-05f3_0007-event-if01
TAGS=:power-switch:

所以我尝试了这个,因为我有一些回忆:

ACTION=="add", ENV{ID_SERIAL}=="05f3_0007", RUN+="/bin/echo aaa >> /tmp/layout_kinesis.log"

依然没有。


udevadm 测试显示run至少已填充(此输出与ENV{ID_SERIAL}上面的版本相同):

$ udevadm test $(udevadm info -q path -n /dev/bus/usb/002/062)
# ... the end here:
Reading rules file: /etc/udev/rules.d/90-kinesis-advantage.rules
Reading rules file: /lib/udev/rules.d/90-libgpod.rules
Reading rules file: /lib/udev/rules.d/90-libinput-fuzz-override.rules
Reading rules file: /lib/udev/rules.d/90-nm-thunderbolt.rules
Reading rules file: /lib/udev/rules.d/90-pulseaudio.rules
Reading rules file: /lib/udev/rules.d/95-cd-devices.rules
Reading rules file: /lib/udev/rules.d/95-dm-notify.rules
Reading rules file: /lib/udev/rules.d/95-upower-csr.rules
Reading rules file: /lib/udev/rules.d/95-upower-hid.rules
Reading rules file: /lib/udev/rules.d/95-upower-hidpp.rules
Reading rules file: /lib/udev/rules.d/95-upower-wup.rules
Reading rules file: /lib/udev/rules.d/96-e2scrub.rules
Reading rules file: /lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Invalid inotify descriptor.
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.1/2-1.1.2
DEVNAME=/dev/bus/usb/002/062
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=5f3/7/320
TYPE=0/0/0
BUSNUM=002
DEVNUM=062
MAJOR=189
MINOR=189
ACTION=add
SUBSYSTEM=usb
ID_VENDOR=05f3
ID_VENDOR_ENC=05f3
ID_VENDOR_ID=05f3
ID_MODEL=0007
ID_MODEL_ENC=0007
ID_MODEL_ID=0007
ID_REVISION=0320
ID_SERIAL=05f3_0007
ID_BUS=usb
ID_USB_INTERFACES=:030101:030000:
ID_VENDOR_FROM_DATABASE=PI Engineering, Inc.
ID_MODEL_FROM_DATABASE=Kinesis Advantage PRO MPC/USB Keyboard
ID_PATH=pci-0000:00:1d.0-usb-0:1.1.2
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_1_2
USEC_INITIALIZED=51523126321
run: '/bin/echo aaa >> /tmp/layout_kinesis.log'
Unload module index
Unloaded link configuration context.

我还尝试将设备的属性和一位家长的属性结合起来:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="05f3", ATTR{idProduct}="0007", ACTION=="add", RUN+="/bin/sh -c '/bin/echo UDEV > tmp/layout_kinesis.log'"

这仍然不起作用。


关于沙箱:

$ systemctl cat systemd-udevd.service
# /lib/systemd/system/systemd-udevd.service
#  SPDX-License-Identifier: LGPL-2.1+
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=udev Kernel Device Manager
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
After=systemd-sysusers.service systemd-hwdb-update.service
Before=sysinit.target
ConditionPathIsReadWrite=/sys

[Service]
Type=notify
# Note that udev also adjusts the OOM score internally and will reset the value internally for its workers
OOMScoreAdjust=-1000
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
Restart=always
RestartSec=0
ExecStart=/lib/systemd/systemd-udevd
ExecReload=udevadm control --reload --timeout 0
KillMode=mixed
TasksMax=infinity
PrivateMounts=yes
ProtectHostname=yes
MemoryDenyWriteExecute=yes
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
IPAddressDeny=any
WatchdogSec=3min

答案1

在现代系统上,udevRUN密钥有一些与之相关的注意事项。

首先,您不应该使用它来启动任何长时间运行的进程,因为它可能会阻止同一设备或依赖于该设备的任何设备处理其他 udev 事件。

systemd-udevd.service第二个警告是沙盒化的默认情况下,在现代发行版上:请参阅systemctl cat systemd-udevd.serviceSANDBOXING章节man 5 systemd.exec以查看您的发行版中应用的确切沙箱选项。但最终结果是 udev 的临时文件可能隐藏在它自己的命名空间中,这可能解释了为什么您看不到它们。

答案2

我仍然无法在规则本身中echo写入,但启动 oneshot systemd 服务是有效的。/tmp/

/etc/udev/rules.d/99-kinesis.rules:

SUBSYSTEM=="usb", ATTRS{idVendor}=="05f3", ATTR{idProduct}=="0007", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="kinesis_custom.service"

/etc/sytemd/system/kinesis_custom.service:

[Unit]
Description=Autorun actions for Kinesis keyboard

[Service]
Type=oneshot
ExecStart=sh -c "/bin/echo UDEVSYSTEMD >> /tmp/layout_kinesis.log"
RemainAfterExit=true
StandardOutput=journal

根据 @telcoM 提到的沙箱,我不确定这是否是设计使然,但我想我可以使用它。

相关内容