我有这个 UDEV 规则,当我插入键盘时它会被激活:
ACTION=="add", DEVPATH=="/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/0003:046A:0011.00??/input/input??/event[0-9][0-9]*", ATTRS{name}=="HID 046a:0011", ATTRS{phys}=="usb-0000:00:14.0-1/input0", RUN+="/home/*user*/.udev_rule_scripts/cherry_keyboard.sh", SYMLINK+="cherrysymlink"
它应该
- 创建一个 symlink
/dev/cherrysymlink
,它确实这样做了,并且 - 执行 shell 脚本,但它不执行。
这是调试输出udevadm test /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/0003:046A:0011.0003/input/input18/event17
:
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.
.INPUT_CLASS=kbd
ACTION=add
DEVLINKS=/dev/input/by-id/usb-046a_0011-event-kbd /dev/cherrysymlink /dev/input/by-path/pci-0000:00:14.0-usb-0:1:1.0-event-kbd
DEVNAME=/dev/input/event17
DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/0003:046A:0011.0003/input/input18/event17
ID_BUS=usb
ID_INPUT=1
ID_INPUT_KEY=1
ID_INPUT_KEYBOARD=1
ID_MODEL=0011
ID_MODEL_ENC=0011
ID_MODEL_ID=0011
ID_PATH=pci-0000:00:14.0-usb-0:1:1.0
ID_PATH_TAG=pci-0000_00_14_0-usb-0_1_1_0
ID_REVISION=0100
ID_SERIAL=046a_0011
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030101:
ID_USB_INTERFACE_NUM=00
ID_VENDOR=046a
ID_VENDOR_ENC=046a
ID_VENDOR_ID=046a
LIBINPUT_DEVICE_GROUP=3/46a/11/111:usb-0000:00:14.0-1
MAJOR=13
MINOR=81
SUBSYSTEM=input
USEC_INITIALIZED=31155231
run: '/usr/local/bin/cherry.sh'
当插入键盘时,/dev/cherrysymlink
将创建。此外,调试输出在最后一行表明脚本/usr/local/bin/cherry.sh
确实运行了。
问题是,该脚本并未实际执行。
cherry_keyboard.sh
:
#!/bin/bash
xset r rate 150 60
它应该改变键盘按键的自动重复,但它保持不变。
我也尝试过:
#!/bin/bash
slock
什么都没发生。当我在 shell 中手动执行脚本时,它们都可以工作。我究竟做错了什么?
编辑:
像这样修改我的脚本后,我可以将echo
输出通过管道dzen2
传输到屏幕上:
#!/bin/bash
export DISPLAY=:0
export XAUTHORITY=/home/*user*/.Xauthority
echo 'test' > /home/*user*/.udev_rule_scripts/test
echo 'test' | dzen2 -p 4
xset r rate 150 60
slock
到目前为止,前两echo
行工作正常。和xset
命令slock
仍然不起作用。
编辑2:
经过一番阅读后,我非常确定它与 DBUS 和环境变量“DBUS_SESSION_BUS_ADDRESS”有关。另外,当我以用户身份运行 printenv 时,就会DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
设置。当我以 root 身份运行 printenv 时,未设置此变量。
因此我对我的脚本做了另一个修改:
#!/bin/bash
export DISPLAY=:0
export XAUTHORITY=/home/*user*/.Xauthority
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
echo 'test' > /home/*user*/.udev_rule_scripts/test
echo 'test' | dzen2 -p 4
xset r rate 150 60
slock
不幸的是,它仍然不起作用。
编辑3:
根据吉尔斯的建议,我在脚本中添加了一行:
#!/bin/bash
exec >>/home/*user*/.udev_rule_scripts/test.log 2>&1; echo; date
export DISPLAY=:0
export XAUTHORITY=/home/*user*/.Xauthority
echo 'test' | dzen2 -p 4
xset r rate 150 60
slock
这会产生以下错误消息test.log
Tue Feb 23 10:14:17 UTC 2016
/home/*user*/.udev_rule_scripts/cherry_keyboard: line 11: 858 Segmentation fault (core dumped) slock
这(某种程度上)解释了为什么slock
无法执行。遗憾的是,什么都没有xset
。
编辑4:
这次,我结合了 Gilles 和 ojs 的建议。现在错误消息更有趣:
cherry_keyboard.sh
:
#!/bin/bash
exec >>/home/*user*/.udev_rule_scripts/test.log 2>&1; echo; date
export DISPLAY=:0
export XAUTHORITY=/home/*user*/.Xauthority
echo 'test' | dzen2 -p 4
su *user* -c "DISPLAY=:0 xset r rate 150 60"
su *user* -c "DISPLAY=:0 slock"
test.log:
Tue Feb 23 10:37:22 UTC 2016
XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 43 requests (37 known processed) with 0 events remaining.
Tue Feb 23 10:38:37 UTC 2016
dzen: cannot open display
xset: unable to open display ":0"
slock: cannot open display
Tue Feb 23 10:40:54 UTC 2016
现在事情是这样的:当我插入键盘时,dzen2
屏幕上会弹出 ,然后屏幕变黑。但不是因为slock
,它有点崩溃,当我在键盘上打字时,屏幕保持黑色(当 slock 在它后面时,它不应该是这样)。其他应用程序(如)moc
仍在运行。
现在奇怪的部分是:
当我按下笔记本电脑上的电源按钮重新启动系统时(我认为这是这种情况下唯一的选择),在关机之前,黑屏消失了半秒,而是出现了红屏(slock的红屏)您输入了错误的密码)。所以 slock 实际上正在运行。但是为什么错误消息指出两者都dzen
“slock
无法打开显示”,而实际上它们都在运行?为什么屏幕会崩溃?xset
的错误消息有何不同?
替代cherry_keyboard.sh
:
#!/bin/bash
exec >>/home/*user*/.udev_rule_scripts/test.log 2>&1; echo; date
export DISPLAY=:0
export XAUTHORITY=/home/*user*/.Xauthority
echo 'test' | dzen2 -p 4
su *user* -c "DISPLAY=:0 xset r rate 150 60"
#su *user* -c "DISPLAY=:0 slock"
test.log
:
Tue Feb 23 10:43:36 UTC 2016
所以这次根本没有错误消息。
但是,在两个版本中xset
都不会修改自动重复...
答案1
首先,您的匹配指令是严重错误的:更好的规则应该仅在 SUBSYSTEM 以及 USB VID 和 PID 上匹配。
不管怎样,你不能只让 root 运行命令来控制你的活动 X 会话。如果您确实必须这样做,那么您至少必须导入 $DISPLAY 和 $XAUTHORITY,但正确的解决方案是在适当的时候使用桌面环境的本机工具来运行这些命令。
答案2
从 udev 执行的脚本在几乎空的环境中运行。它们不附加到任何特定会话或终端。
您需要做的第一件事是阅读错误消息。添加exec >>/var/log/my-udev-script.log 2>&1; echo; date
到脚本开头的行下方,并在脚本触发后#!
查看。/var/log/my-udev-script.log
该xset
命令是一个X窗口系统客户端,因此它需要与 X 服务器通信。它根据环境变量的值知道要与哪个 X 服务器(可能有很多)通信DISPLAY
。如果DISPLAY
未设置,xset
则无法与任何 X 服务器通信,因此它所做的只是打印一条错误消息并退出。
要了解如何设置DISPLAY
,XAUTHORITY
如有必要,请参阅我可以以 root 身份在另一个用户的桌面上启动图形程序吗?和在远程 X 显示器上打开窗口(为什么“无法打开显示器”)?请注意,如果有多个 X 服务器,可能很难弄清楚该怎么做。
xset 和 slock 都不需要也不关心 D-Bus。如果你真的需要D-Bus,如何用固定地址启动dbus?是最简单的方法。