Problem 1: Umgebungsvariable.

Problem 1: Umgebungsvariable.

Ich habe das folgende Skript, um die Tastenzuordnungen meines Wacom Intuos S 2 zu definieren:

/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'

Dieses Skript funktioniert einwandfrei, wenn ich es manuell ausführe.

Mein Ziel ist es, dieses Skript automatisch auszuführen, wenn das Pad angeschlossen wird. Ich habe das mit der folgenden udevRegel versucht:

/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"

Allerdings ordnet das Skript die Tasten nicht zu, wenn ich das Pad anschließe.


Ich verwende 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.

Antwort1

Im Wesentlichen handelt es sich dabei um eine Kombination aus einem Race Condition und dem unterschiedlichen Verhalten beim xsetwacomAusführen über eine Udev-Regel im Vergleich zum Ausführen über ein bekanntes grafisches Terminal, was beispielsweise auf Unterschiede bei den Umgebungsvariablen zurückzuführen ist.

Problem 1: Umgebungsvariable.

Kommen wir zunächst zum zweiten Problem: Dies ist vergleichbar mit der Situation, in derShell-Skripte verhalten sich anders, wenn sie von einem Cronjob ausgeführt werden.

Um Ihre Umgebung mit der udev-Umgebung zu vergleichen, führen Sie ausentweder envoder printenv:

printenv > my-env.txt

von einem grafischen Terminal aus und fügen Sie dann das folgende Udev-Skript hinzu:

/usr/bin/printenv > /tmp/udev-env.txt

Dann können Sie vergleichen my-env.txtund udev-env.txt.

Um abzuleiten, welche Umgebungsvariablen xsetwacomverwendet werden,InstallierenltraceUndFühren Sie einen Befehl wie diesen aus:

ltrace -f -e getenv -o my-ltrace-01.log xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'

Da ich kein Wacom-Gerät habe, kann ich den vollständigen Befehl nicht ausführen.

$ xsetwacom set 'Wacom Intuos S 2 Pad pad' Button 1 'key -'
Cannot find device 'Wacom Intuos S 2 Pad pad'.

Allein anhand der xsetwacomzurückgelegten Strecke bis zum Beenden kann ich jedoch erkennen, dass es DISPLAYund verwendet XAUTHORITY.

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) +++

Diese Werte können Sie durch Ausdrucken ermitteln.

$ printf 'DISPLAY=%q\n' "$DISPLAY"
DISPLAY=:0
$ printf 'XAUTHORITY=%q\n' "$XAUTHORITY"
XAUTHORITY=/home/nathaniel/.Xauthority

Definieren Sie sie dann oben im Skript.

#!/bin/bash

# Just an example, yours will be different.
export DISPLAY=:0
export XAUTHORITY=/home/nathaniel/.Xauthority
sleep 1
# The rest of the script.

Das Skript könnte aus anderen Gründen immer noch nicht funktionieren, aber für manche Leute scheint es ausreichend gewesen zu sein, die Unterschiede in den Umgebungsvariablen zu beseitigen. Ein anderer Benutzer in einemVerwandte Fragekonnte es unter Ubuntu 18.04 folgendermaßen zum Laufen bringen:

Sie müssen Ihrem Skript zwei Variablenexporte hinzufügen, einen für DISPLAYund XAUTHORITY. Diese werden zum Identifizieren und Zugreifen auf die richtige X-Sitzung verwendet. Sie können die entsprechenden Werte abrufen, indem Sie es ausführen, envwährend Sie als normaler Benutzer angemeldet sind.

Problem 2: Race Condition.

Nun zum Race Condition: Der xsetwacomBefehl verlässt sich darauf, dass der X-Server die Hardware erkennt. Wenn er also ausgeführt wird, bevor er bereit ist, schlägt er fehl. Das sleep 1war anscheinend einmal ausreichend, ist es aber nicht mehr. (Manchmal verwenden die Leutesleep 2,sleep 3, odersleep 4, ohne besonderen Grund. Generell beunruhigt es mich, dass das sleep 1überhaupt notwendig ist.)

Wenn Sie das Gerät anschließen:

  1. Linux erkennt das Gerät und erstellt einen Geräteeintrag basierend auf Udev-Regeln.
  2. Der X-Server erkennt das Gerät.

Sie können nicht xsetwacomvor Phase 2 ausführen. Ihr Skript schlägt fehl, weil Sie es in Phase 1 ausführen, wenn X das Gerät noch nicht kennt.

Gilles: „Also, hör auf, böse zu sein“,https://unix.stackexchange.com/a/65792/30049

Das ist ja alles schön und gut, aber wenn man das hier probiert, funktioniert es nicht mehr:

Ich habe Ihre Antwort wegen der Details positiv bewertet, bin mir aber aus folgendem Grund nicht sicher, ob sie richtig ist: Ich habe versucht, es sleepmit einigen Sekunden zu verwenden. Beim Anschließen funktioniert das Tablet nach weniger als einer Sekunde. Wenn die Befehle ausgeführt werden, wird das Gerät also bereits erkannt und verwendet X. Aber es funktioniert immer noch nicht?

KommentarvonRedsandro

Da ich weder Ihre Hardware noch Ihr Betriebssystem habe, kann ich Ihr Problem nicht reproduzieren. Aber Folgendes habe ich aus anderen Threads herausgelesen: Die sleepVerzögerung allein reicht nicht aus. Manche Leute haben Workarounds wie:

Die vielleicht gründlichste Lösung, die ich gesehen habe, ist dieVerlinkter ThreadVerwenden von systemd-Dienstdateien:

Letztendlich musste ich das Skript mit einem systemd-Dienst starten, der durch eine Udev-Regel ausgelöst wurde:

$ cat /etc/udev/rules.d/99-wacom.rules
SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="056a", ENV{ID_MODEL_ID}=="0302", TAG+="systemd"

[...]

Dadurch TAG+="systemd"werden andere systemd-Dienste (System oder Benutzer) vom Gerät abhängig (registriert es als Geräteeinheit, siehe man systemd.device).

Spelufo,https://unix.stackexchange.com/a/290940/30049

verwandte Informationen