Problema 1: variable de entorno.

Problema 1: variable de entorno.

Tengo el siguiente script para definir las asignaciones de botones de mi 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'

Este script funciona bien si lo ejecuto manualmente.

Mi objetivo es ejecutar este script automáticamente cada vez que el pad esté conectado. Lo intenté con la siguiente udevregla:

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

Sin embargo, el script no asigna los botones si conecto el pad.


Estoy ejecutando 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.

Respuesta1

Esencialmente, se trata de una combinación de una condición de carrera y la diferencia en el comportamiento xsetwacomcuando se ejecuta desde una regla udev en comparación con cuando se ejecuta desde una terminal gráfica familiar, debido, por ejemplo, a diferencias en las variables de entorno.

Problema 1: variable de entorno.

Abordando primero la segunda cuestión: esto es similar a la situación en la queLos scripts de Shell se comportan de manera diferente cuando se ejecutan desde un cronjob..

Para comparar su entorno con el entorno udev, ejecutecualquiera envo printenv:

printenv > my-env.txt

desde una terminal gráfica, y luego agregue este script udev:

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

Entonces puedes comparar my-env.txty udev-env.txt.

Para inferir qué variables de entorno xsetwacomse están utilizando,instalarltraceyejecutar un comando como este:

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

Como no tengo un dispositivo Wacom, no puedo ejecutar el comando completo.

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

Sin embargo, basándome únicamente en qué tan lejos xsetwacomllega antes de salir, puedo decir que usa DISPLAYy 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) +++

Puede encontrar estos valores imprimiéndolos.

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

Luego defínelos en la parte superior del guión.

#!/bin/bash

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

El script aún podría no funcionar por otras razones, pero eliminar las diferencias en las variables de entorno parece haber sido suficiente para otras personas. Otro usuario en unpregunta relacionadaPude hacerlo funcionar en Ubuntu 18.04 de esta manera:

Debe agregar dos exportaciones de variables a su secuencia de comandos, una para DISPLAYy XAUTHORITY. Se utilizan para identificar y acceder a la sesión X correcta. Puede obtener los valores adecuados ejecutándolo envmientras está conectado como usuario habitual.

Problema 2: condición de carrera.

Ahora, para la condición de carrera: el xsetwacomcomando depende de que el servidor X reconozca el hardware, por lo que ejecutarlo antes de que esté listo provocará que falle. sleep 1Al parecer, en algún momento fue suficiente, pero ya no lo es . (A veces la gente usasleep 2,sleep 3, osleep 4, sin ningún motivo concreto. En términos generales, me preocupa que sleep 1sea incluso necesario.)

Cuando conectas el dispositivo:

  1. Linux detecta el dispositivo y crea una entrada de dispositivo basada en las reglas de udev.
  2. El servidor X detecta el dispositivo.

No puedes ejecutarlo xsetwacomantes de la etapa 2. Tu script falla porque lo estás ejecutando en la etapa 1, cuando X aún no conoce el dispositivo.

Gilles 'SO- deja de ser malvado',https://unix.stackexchange.com/a/65792/30049

Todo esto está muy bien, pero cuando la gente intenta esto, ya no funciona:

Voté a favor de su respuesta para conocer los detalles, pero no estoy seguro de que sea correcta por el siguiente motivo: intenté usarla sleepcon unos segundos. Cuando se conecta, la tableta funciona en menos de un segundo, por lo que cuando se ejecutan los comandos, el dispositivo ya está detectado y en uso X. ¿Pero todavía no funciona?

comentarioporrojosandro

Como no tengo su hardware ni su sistema operativo, no puedo replicar su problema. Pero esto es lo que he deducido de otros hilos: el sleepretraso por sí solo no es suficiente. Algunas personas tienen soluciones como:

Quizás la solución más completa que he visto esté en elhilo vinculadousando archivos de servicio systemd:

Terminé teniendo que iniciar el script con un servicio systemd activado por una regla udev:

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

[...]

Permite TAG+="systemd"que otros servicios systemd (sistema o usuario) dependan del dispositivo (lo registra como una unidad de dispositivo, consulte man systemd.device).

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

información relacionada