Espere a que aparezca / desaparezca una ventana X (de una manera sensata)

11

Dentro de un script de shell, necesito esperar a que aparezca una ventana que tenga una cadena en su título, realizar alguna acción, y luego esperar a que desaparezca, y realizar alguna otra acción.

Hasta ayer, tenía este código simple. El problema con esto es que el disco no se puede poner en un estado de ahorro de energía mientras el script se deja en ejecución, y puede durar muchas horas:

while :; do
    until wmctrl -l | grep -q "$string"; do   # until
        sleep 0.5
    done
    : do action 1

    while wmctrl -l | grep -q "$string"; do   # while
        sleep 0.5
    done
    : do action 2
done

Como decidí que el código mencionado estaba volviendo loco el disco, revisé la documentación de algunas herramientas de línea de comandos y decidí xdotoolesperar a que apareciera la ventana y xpropaveriguar cuándo desapareció la ventana:

while :; do
    # we use `until' because sometimes xdotool just crashes
    until xdotool search -sync -all -onlyvisible -pid $pid -name "$string"; do
        :
    done

    # xdotool isn't trustworthy either, so check again
    wmctrl -l | grep -q "$string" ||
        continue

    : do action 1

    xprop -spy -root _NET_CLIENT_LIST_STACKING | while read line; do
        if [[ ! ${_line:-} || $_line = $line ]]; then
            _line=$line
            continue
        else
            _line=$line
            if wmctrl -l | grep -q "$string"; then
                continue
            else
                : do action 2
                break
            fi
        fi
    done
done

Ahora tengo dos nuevos problemas con el código anterior:

  • xdotoolno solo se bloquea y da resultados extraños, como ya lo he solucionado anteriormente, sino que también absorbe aproximadamente el 15% de la CPU mientras se espera que aparezca la ventana. Eso significa que me deshice del código simple que activa el disco, para escribir el código que queda desperdiciando la CPU durante horas, y mi intención era ahorrar energía en primer lugar.
  • xprop -spyme notificará cada vez que cambie el foco (que he solucionado $_line) o crear y destruir ventanas. Eso activa el disco con más frecuencia que xdotool.

Estoy buscando un programa simple que solo espere $stringa que aparezca o desaparezca la ventana con el título . Puede ser una herramienta de línea de comandos existente, un script de Python, un código C compilable ... ¡pero debería poder integrarlo de alguna manera en mi script (incluso si solo escribe alguna información en un quince)!

Teresa e Junior
fuente
1
¿No tendría sentido averiguar por qué su antiguo código activa el disco y buscar una solución? Algo como chroot y ramdisk. Supongo que strace -f -e trace=file wmctrl -ldebería ser informativo.
Hauke ​​Laging
Estoy usando fatracepara verificar las reactivaciones del disco, y me dice bashlecturas /bin/sleepy /usr/bin/wmctrlcada medio segundo, es por eso que estoy buscando algún programa que realmente espere los eventos de la ventana. ¿Me estoy perdiendo de algo?
Teresa e Junior
1
leerlos no despertaría el disco, ya que probablemente se almacenarían en caché si se ejecutaran dos veces por segundo. ¿Montó sus sistemas de archivos con noatime? Consulte también btracedesde blktracepara investigar las fuentes de actividad del disco.
Stéphane Chazelas
1
Si aún no lo ha mirado, xwininfopodría ser útil, ciertamente carga muchas menos bibliotecas compartidas que wmctrl y opera en un nivel más cercano a la X.
msw
1
@msw Estoy tratando de arreglar lo que no se puede arreglar, que es una función de autoguardado para Google Earth (el origen cerrado y la notificación de errores es una pérdida de tiempo)
Teresa e Junior

Respuestas:

4

Esto debería darle a todos (OK: la mayoría. ¿Qué he olvidado? ¿Sockets?) Actividades del sistema de archivos que incluyen escrituras:

strace -f command 2>&1 | 
  grep -e '^open.*O_CREAT' \
    -e ^write   \
    -e ^mkdir   \
    -e ^rmdir   \
    -e ^unlink  \
    -e ^rename  \
    -e ^chmod   \
    -e ^link    \
    -e ^symlink \
    -e ^mknod

Con esta información, se puede crear un entorno chroot de trabajo en tmpfs (como acción de último recurso; tal vez los enlaces simbólicos a tmpfs sean suficientes). Si el programa se inicia en un chroot RAM, entonces no tiene la posibilidad de activar el disco directamente. Nunca se escribe en el disco la jerarquía de su sistema de archivos.

Hauke ​​Laging
fuente
Creo que hay momentos en que leer un archivo, al menos por primera vez, también activará el disco, ¿no? Me pregunto si blktracesería la herramienta adecuada para eso, pero requeriría una compilación del núcleo # CONFIG_BLK_DEV_IO_TRACE is not set:( Sin embargo, eso está fuera del alcance de esta pregunta. ¡Gracias!
Teresa e Junior
1
@TeresaeJunior Claro, pero ¿quién lo consideraría un problema? Se trata de mantener el script ejecutándose todo el tiempo, no de iniciarlo. Y puede crear los tmpfs desde boot.local/ rc.localpara que no tenga acceso al disco, incluso si inicia el script más tarde. Acabo de echar un vistazo blktrace(no lo sabía antes). Eso es tan terrible que me pregunto si voy a dormir esta noche ...
Hauke ​​Laging
Sí, ya no debería preocuparme más por esto, tienes razón otra vez. Pero creo que también perderé esta noche de sueño compilando el núcleo, ya que quiero verificar todo lo que podría estar despertando constantemente el disco, no solo este truco en particular de Google Earth :)
Teresa e Junior
6

Puede ser más simple y más confiable confiar en su administrador de ventanas o X11 para manejar esto escribiendo una aplicación X11 "real".

Lo que desea del shell es algo que se registra con el administrador de ventanas y espera el tipo de evento deseado antes de regresar al shell ... es mucho más fácil de cargar si puede evitar bucles dentro del shell. (Sus until xdotool...causas se cargan porque no hay retraso (suspensión) dentro del bucle).

Ah ... aparentemente xdotoolesa característica se agregó hace más de un año --sync. Eso no está disponible en mi distribución actual de Linux (Debian Squeeze), por lo que no lo he probado.

El desarrollador de xdotool responde una pregunta similar a la suya: https://groups.google.com/d/msg/xdotool-users/7zfKTtyWm0Q/DM6TSOBUWZMJ

Carl Cravens
fuente
Sí, exactamente, -syncse suponía que debía hacer lo que quiero, pero lo necesita whileporque eventualmente se bloqueará antes de que aparezca la ventana y desperdicie demasiada CPU. Realmente compilé xdotooldesde el código fuente porque el de Debian fue increíblemente lento para escribir. Escribir una aplicación que interactúa directamente con X realmente está más allá de mí. Gracias, sin embargo!
Teresa e Junior