問題 1: 環境変数。

問題 1: 環境変数。

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.

答え1

xsetwacom本質的には、これは競合状態と、環境変数の違いなどにより、udev ルールから実行した場合と使い慣れたグラフィカル端末から実行した場合の動作の違いの組み合わせです。

問題 1: 環境変数。

まず2番目の問題に取り組みましょう。これは、シェルスクリプトは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使用していることがわかります。DISPLAYXAUTHORITY

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 では次のように動作させることができました:

スクリプトに と の 2 つの変数エクスポートを追加する必要がありますDISPLAY。 これらは、正しい X セッションを識別してアクセスするために使用されます。通常のユーザーとしてログインしてXAUTHORITY実行すると、適切な値を取得できます。env

問題 2: 競合状態。

さて、競合状態についてですが、このxsetwacomコマンドはXサーバがハードウェアを認識することに依存しているため、準備が整う前に実行すると失敗します。はsleep 1かつては十分だったようですが、今はそうではありません。(時々、sleep 2sleep 3、 またはsleep 4、特に理由はありません。大まかに言えば、 が必要なこと自体が問題ですsleep 1

デバイスを接続すると:

  1. Linux はデバイスを検出し、udev ルールに基づいてデバイス エントリを作成します。
  2. X サーバーがデバイスを検出します。

ステージ 2 より前に実行することはできませんxsetwacom。X がデバイスをまだ認識していないステージ 1 でスクリプトを実行しているため、スクリプトは失敗します。

ジル「だから、悪事はやめなさい」https://unix.stackexchange.com/a/65792/30049

これはすべてうまくいっていますが、人々がこれを試すと、もう機能しません。

詳細についてあなたの回答に賛成しましたが、次の理由でこれが正しいかどうかわかりません。sleep数秒間使用してみました。接続すると、タブレットは 1 秒も経たないうちに動作するので、コマンドが実行される頃には、デバイスはすでに検出され、 によって使用されていますX。それでも動作しないのですか?

コメントによるレッドサンドロ

私はあなたと同じハードウェアや OS を持っていないので、問題を再現することはできません。しかし、他のスレッドから私が収集した情報は次のとおりです。遅延sleepだけでは不十分です。次のような回避策を講じている人もいます。

おそらく私が見た中で最も徹底した解決策はリンクされたスレッド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 サービス (システムまたはユーザー) がデバイスに依存できるようにします (デバイス ユニットとして登録します。man を参照 systemd.device)。

スペルフォhttps://unix.stackexchange.com/a/290940/30049

関連情報