Wacom 墊的 udev 規則不起作用
我有以下腳本來定義我的 Wacom Intuos S 2 的按鈕映射:
/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh
#!/bin/bash export DISPLAY=:0 export XAUTHORITY=/home/scriptim/.Xauthority /usr/bin/sleep 1 # wait for device to be ready /usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -' /usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 3 'key +' /usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 8 'key +Ctrl z -Ctrl' /usr/bin/xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 9 'key +Ctrl +Shift z -Ctrl -Shift'
如果我手動執行此腳本,它可以正常工作。
我的目標是在插入墊時自動執行此腳本。我使用以下
udev
規則進行了嘗試:
/etc/udev/rules.d/10-wacom_intuos_s_2_pad.rules
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="056a", ATTRS{idProduct}=="033b", RUN+="/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh"
但是,如果我插入墊,腳本不會映射按鈕。
我正在執行 Arch Linux (
5.5.10-arch1-1
)$ lsusb ... Bus 004 Device 015: ID 056a:033b Wacom Co., Ltd CTL-490 [Intuos Draw (S)] ...
$ udevadm info -a -n hidraw0 ... looking at parent device '/devices/pci0000:00/0000:00:10.0/usb4/4-2': KERNELS=="4-2" SUBSYSTEMS=="usb" DRIVERS=="usb" ATTRS{authorized}=="1" ATTRS{bcdDevice}=="0100" ATTRS{bmAttributes}=="80" ATTRS{bMaxPower}=="498mA" ATTRS{manufacturer}=="Wacom Co.,Ltd." ATTRS{quirks}=="0x0" ATTRS{maxchild}=="0" ATTRS{bNumInterfaces}==" 3" ATTRS{bMaxPacketSize0}=="64" ATTRS{devpath}=="2" ATTRS{ltm_capable}=="no" ATTRS{busnum}=="4" ATTRS{devnum}=="15" ATTRS{tx_lanes}=="1" ATTRS{bDeviceSubClass}=="00" ATTRS{bDeviceClass}=="00" ATTRS{bDeviceProtocol}=="00" ATTRS{bNumConfigurations}=="1" ATTRS{speed}=="12" ATTRS{version}==" 2.00" ATTRS{product}=="Intuos PS" ATTRS{avoid_reset_quirk}=="0" ATTRS{idVendor}=="056a" ATTRS{configuration}=="" ATTRS{devspec}=="(null)" ATTRS{urbnum}=="174" ATTRS{bConfigurationValue}=="1" ATTRS{removable}=="unknown" ATTRS{rx_lanes}=="1" ATTRS{idProduct}=="033b" ...
$ udevadm test --action="add" /devices/pci0000:00/0000:00:10.0/usb4/4-2 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. Load module index Parsed configuration file /usr/lib/systemd/network/99-default.link Created link configuration context. Reading rules file: /usr/lib/udev/rules.d/10-dm.rules Reading rules file: /etc/udev/rules.d/10-wacom_intuos_s_2_pad.rules ... Reading rules file: /usr/lib/udev/rules.d/65-libwacom.rules ... Reading rules file: /usr/lib/udev/rules.d/wacom.rules Invalid inotify descriptor. DEVPATH=/devices/pci0000:00/0000:00:10.0/usb4/4-2 DEVNAME=/dev/bus/usb/004/015 DEVTYPE=usb_device DRIVER=usb PRODUCT=56a/33b/100 TYPE=0/0/0 BUSNUM=004 DEVNUM=015 MAJOR=189 MINOR=398 ACTION=add SUBSYSTEM=usb ID_VENDOR=Wacom_Co._Ltd. ID_VENDOR_ENC=Wacom\x20Co.\x2cLtd. ID_VENDOR_ID=056a ID_MODEL=Intuos_PS ID_MODEL_ENC=Intuos\x20PS ID_MODEL_ID=033b ID_REVISION=0100 ID_SERIAL=Wacom_Co._Ltd._Intuos_PS ID_BUS=usb ID_USB_INTERFACES=:030000:030102: ID_VENDOR_FROM_DATABASE=Wacom Co., Ltd ID_MODEL_FROM_DATABASE=CTL-490 [Intuos Draw (S)] ID_PATH=pci-0000:00:10.0-usb-0:2 ID_PATH_TAG=pci-0000_00_10_0-usb-0_2 USEC_INITIALIZED=4102997566 run: '/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh' Unload module index Unloaded link configuration context.
$ journalctl -xe Mar 22 17:38:55 scriptim systemd-udevd[5927]: 1-1: Process '/usr/local/bin/wacom_intuos_s_2_pad_button_mapping.sh' failed with exit code 255.
本質上,這是競爭條件和
xsetwacom
從 udev 規則執行時與從熟悉的圖形終端執行時的行為差異的組合,例如由於環境變數的差異。問題1:環境變數。
首先解決第二個問題:這類似於shell 腳本在從 cronjob 執行時表現不同的情況。
要將您的環境與 udev 環境進行比較,請執行或 :
env``printenv
printenv > my-env.txt
從圖形終端,然後添加這個 udev 腳本:
/usr/bin/printenv > /tmp/udev-env.txt
然後你可以比較
my-env.txt
和udev-env.txt
。要推斷
xsetwacom
正在使用的環境變數,請安裝ltrace
並執行如下命令:ltrace -f -e getenv -o my-ltrace-01.log xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'
由於我沒有 Wacom 設備,因此無法執行完整的命令。
$ xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -' Cannot find device 'Wacom Intuos S 2 Pad pad'.
但是,僅根據
xsetwacom
它退出之前的距離,我可以告訴它使用DISPLAY
andXAUTHORITY
。15447 libX11.so.6->getenv("DISPLAY") = ":0" 15447 libxcb.so.1->getenv("DISPLAY") = ":0" 15447 libxcb.so.1->getenv("DISPLAY") = ":0" 15447 libXau.so.6->getenv("XAUTHORITY") = "/home/nathaniel/.Xauthority" 15447 libX11.so.6->getenv("XLIBBUFFERSIZE") = nil 15447 libX11.so.6->getenv("XLIB_SKIP_ARGB_VISUALS") = nil 15447 libX11.so.6->getenv("XKB_DEBUG") = nil 15447 libX11.so.6->getenv("_XKB_OPTIONS_ENABLE") = nil 15447 libX11.so.6->getenv("XKB_DISABLE") = nil 15447 +++ exited (status 0) +++
您可以通過列印這些值來找到它們。
$ printf 'DISPLAY=%q\n' "$DISPLAY" DISPLAY=:0 $ printf 'XAUTHORITY=%q\n' "$XAUTHORITY" XAUTHORITY=/home/nathaniel/.Xauthority
然後在腳本頂部定義它們。
#!/bin/bash # Just an example, yours will be different. export DISPLAY=:0 export XAUTHORITY=/home/nathaniel/.Xauthority sleep 1 # The rest of the script.
由於其他原因,該腳本仍然可能無法工作,但消除環境變數的差異對其他人來說似乎已經足夠了。相關問題中的另一位使用者能夠以這種方式使其在 Ubuntu 18.04 上執行:
您需要在腳本中添加兩個變數導出,一個 for
DISPLAY
和XAUTHORITY
. 這些用於辨識和訪問正確的 X 會話。env
您可以通過在以普通使用者身份登錄時執行來獲取適當的值。問題 2:競爭條件。
現在是競爭條件:該
xsetwacom
命令依賴於 X 伺服器辨識硬體,因此在它準備好之前執行它會導致它失敗。一次顯然是足夠的sleep 1
,但不再是。(有時人們使用sleep 2
,sleep 3
, orsleep 4
,沒有特別的原因。廣義地說,它sleep 1
甚至是必要的,這讓我很困擾。)插入設備時:
- Linux 檢測設備並根據 udev 規則創建設備條目。
- X 伺服器檢測到設備。
您不能
xsetwacom
在第 2 階段之前執行。您的腳本失敗是因為您在第 1 階段執行它,此時 X 還不知道設備。— Gilles ‘停止作惡’,https://unix.stackexchange.com/a/65792/30049
這一切都很好,但是當人們嘗試這個時,它就不再起作用了:
我贊成您對詳細資訊的回答,但由於以下原因,我不確定這是否正確:我嘗試使用
sleep
幾秒鐘。插入電源後,平板電腦會在不到一秒的時間內工作,因此在執行命令時,設備已經被檢測到並被X
. 但是還是不行?由於我沒有您的硬體或作業系統,我無法複製您的問題。但這是我從其他執行緒中收集到的:
sleep
延遲本身是不夠的。有些人有解決方法,例如:
- 使用 subshell 並循環,直到設備在
xsetwacom --list devices
.- 使用
at
命令,認為不清楚為什麼會這樣。也許我見過的最徹底的解決方案是在使用 systemd 服務文件的連結執行緒中:
我最終不得不使用由 udev 規則觸發的 systemd 服務啟動腳本:
$ cat /etc/udev/rules.d/99-wacom.rules SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="056a", ENV{ID_MODEL_ID}=="0302", TAG+="systemd"
$$ … $$ 這
TAG+="systemd"
使其他 systemd 服務(系統或使用者)能夠依賴於設備(將其註冊為設備單元,請參閱 mansystemd.device
)。