Attendez qu'une fenêtre X apparaisse / disparaisse (d'une manière saine)

11

Dans un script shell, j'ai besoin d'attendre qu'une fenêtre qui a une chaîne sur son titre apparaisse, faire une action, puis attendre qu'elle disparaisse et faire une autre action.

Jusqu'à hier, j'avais ce code simple. Le problème est que le disque ne peut pas être mis dans un état d'économie d'énergie pendant que le script est en cours d'exécution, et cela peut durer plusieurs heures:

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

Depuis que j'ai décidé que le code mentionné réveillait follement le disque, j'ai parcouru la documentation de quelques outils de ligne de commande, et j'ai décidé xdotoold'attendre que la fenêtre apparaisse et xpropde savoir quand la fenêtre a disparu:

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

Maintenant, j'ai deux nouveaux problèmes avec le code ci-dessus:

  • xdotoolnon seulement se bloque et donne des résultats étranges, comme je l'ai déjà contourné, mais il aspire également environ 15% du processeur en attendant que la fenêtre apparaisse. Cela signifie donc que je me suis débarrassé du code simple qui réveille le disque, pour écrire du code qui laisse le CPU gaspiller pendant des heures, et mon intention était d'économiser de l'énergie en premier lieu.
  • xprop -spym'informera chaque fois que je changerai de focus (que j'ai contourné $_line) ou créer et détruire des fenêtres. Cela réveille le disque plus fréquemment que xdotool.

Je recherche un programme simple qui n'attend que la fenêtre avec le titre $stringpour apparaître ou disparaître. Cela peut être un outil de ligne de commande existant, un script python, du code C compilable ..., mais je devrais être capable de l'intégrer d'une manière ou d'une autre à mon script (même s'il écrit juste des informations dans un fifo)!

Teresa e Junior
la source
1
Ne serait-il pas logique de savoir pourquoi votre ancien code réveille le disque et de rechercher une solution? Quelque chose comme chroot et ramdisk. Je suppose que cela strace -f -e trace=file wmctrl -ldevrait être informatif.
Hauke ​​Laging
J'utilise fatracepour vérifier les réveils de disque, et cela m'indique les bashlectures /bin/sleepet /usr/bin/wmctrltoutes les demi-secondes, c'est pourquoi je recherche un programme qui attendra réellement les événements de fenêtre. Suis-je en train de manquer quelque chose?
Teresa e Junior
1
la lecture de ceux-ci ne réveillerait pas le disque car ils seraient probablement mis en cache s'ils étaient exécutés deux fois par seconde. Avez-vous monté vos systèmes de fichiers avec noatime? Voir aussi btracede blktracepour rechercher les sources d'activité du disque.
Stéphane Chazelas
1
Si vous ne l'avez pas encore regardé, cela xwininfopourrait être utile, il charge certainement beaucoup moins de bibliothèques partagées que wmctrl et fonctionne à un niveau plus proche de X.
msw
1
@msw J'essaie de corriger l'impossible, qui est une fonctionnalité d'enregistrement automatique pour Google Earth (les sources fermées et les rapports de bogues sont une perte de temps)
Teresa e Junior

Réponses:

4

Cela devrait vous donner toutes les activités du système de fichiers (OK: la plupart. Qu'est-ce que j'ai oublié? Sockets?) Qui incluent les écritures:

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

Avec ces informations, un environnement de travail chroot peut être créé dans tmpfs (comme une action de dernier recours; peut-être que les liens symboliques vers tmpfs suffisent). Si le programme est démarré dans un chroot RAM, il n'a pas la possibilité de réveiller directement le disque. Aucune écriture dans sa hiérarchie de système de fichiers n'est jamais écrite sur le disque.

Hauke ​​Laging
la source
Je crois qu'il y a des moments où la lecture d'un fichier, au moins pour la première fois, réveillera également le disque, n'est-ce pas? Je me demande si ce blktraceserait le bon outil pour cela, mais cela nécessiterait une compilation du noyau # CONFIG_BLK_DEV_IO_TRACE is not set:( Cela dépasse cependant la portée de cette question. Merci!
Teresa e Junior
1
@TeresaeJunior Bien sûr, mais qui considérerait cela comme un problème? Il s'agit de garder le script en cours d'exécution tout le temps, pas de le démarrer. Et vous pouvez créer les tmpfs à partir de boot.local/ rc.localafin que vous n'ayez pas accès au disque même si vous démarrez le script plus tard. J'ai juste regardé blktrace(je ne le savais pas avant). C'est tellement terrible que je me demande si je vais pouvoir dormir ce soir ...
Hauke ​​Laging
Oui, je ne devrais plus vraiment m'inquiéter pour celui-ci, tu as encore raison. Mais je pense que je vais également perdre cette nuit de sommeil en compilant le noyau, car je veux vérifier tout ce qui pourrait réveiller constamment le disque, pas seulement ce hack de Google Earth particulier :)
Teresa e Junior
6

Il pourrait être plus simple et plus fiable de compter sur votre gestionnaire de fenêtres ou X11 pour gérer cela en écrivant une "vraie" application X11.

Ce que vous voulez du shell est quelque chose qui s'enregistre auprès du gestionnaire de fenêtres et attend le type d'événement souhaité avant de retourner au shell ... c'est beaucoup plus convivial si vous pouvez éviter de boucler à l'intérieur du shell. (Votre until xdotool...cause la charge car il n'y a pas de retard (sommeil) à l'intérieur de la boucle.)

Ah ... apparemment, xdotoolcette fonctionnalité a été ajoutée il y a plus d'un an --sync. Ce n'est pas disponible dans ma distribution Linux actuelle (Debian Squeeze), donc je ne l'ai pas essayé.

Le développeur xdotool répondant à une question similaire à la vôtre: https://groups.google.com/d/msg/xdotool-users/7zfKTtyWm0Q/DM6TSOBUWZMJ

Carl Cravens
la source
Oui, exactement, -syncétait censé faire ce que je veux, mais il en a besoin whilecar il finira par planter avant que la fenêtre n'apparaisse et gaspille trop de CPU. J'ai en fait compilé à xdotoolpartir des sources car celui de Debian était incroyablement lent à taper. Écrire une application qui interagit directement avec X me dépasse en fait. Merci quand même!
Teresa e Junior