Warten Sie, bis ein X-Fenster angezeigt / ausgeblendet wurde (auf vernünftige Weise).

11

In einem Shell-Skript muss ich warten, bis ein Fenster mit einem String im Titel angezeigt wird, eine Aktion ausführen und dann warten, bis es verschwindet, und eine andere Aktion ausführen.

Bis gestern hatte ich diesen einfachen Code. Das Problem dabei ist, dass die Festplatte nicht in einen Energiesparmodus versetzt werden kann, während das Skript ausgeführt wird, und dies kann viele Stunden dauern:

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

Da ich feststellte, dass der erwähnte Code die Festplatte wahnsinnig weckte, ging ich die Dokumentation einiger Befehlszeilentools durch und beschloss xdotool, auf das Erscheinen des Fensters zu warten und xpropherauszufinden, wann das Fenster verschwunden ist:

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

Jetzt habe ich zwei neue Probleme mit dem obigen Code:

  • xdotoolEs stürzt nicht nur ab und liefert seltsame Ergebnisse, wie ich bereits zuvor umgangen habe, sondern es saugt auch etwa 15% der CPU an, während es darauf wartet, dass das Fenster angezeigt wird. Das bedeutet, dass ich einfachen Code losgeworden bin, der die Festplatte aufweckt, um Code zu schreiben, der die CPU stundenlang verschwendet, und ich wollte in erster Linie Strom sparen.
  • xprop -spybenachrichtigt mich jedes Mal, wenn ich den Fokus ändere (den ich umgangen habe $_line) oder Fenster erstelle und zerstöre. Dadurch wird die Festplatte häufiger geweckt als bei xdotool.

Ich suche ein einfaches Programm, das nur darauf wartet, dass das Fenster mit dem Titel $stringerscheint oder verschwindet. Es kann ein vorhandenes Befehlszeilentool, ein Python-Skript, kompilierbarer C-Code sein ..., aber ich sollte es irgendwie in mein Skript integrieren können (selbst wenn es nur einige Informationen in ein Fifo schreibt)!

Teresa e Junior
quelle
1
Wäre es nicht sinnvoll herauszufinden, warum Ihr alter Code die Festplatte aufweckt, und nach einer Lösung zu suchen? So etwas wie Chroot und Ramdisk. Ich denke, strace -f -e trace=file wmctrl -lsollte informativ sein.
Hauke ​​Laging
Ich verwende fatracefür Disk Wakeups zu überprüfen, und es sagt mir , bashliest /bin/sleepund /usr/bin/wmctrljede halbe Sekunde, deshalb habe ich für einige Programm bin auf der Suche , die tatsächlich für Fenster Ereignisse warten werde. Vermisse ich etwas
Teresa e Junior
1
Das Lesen dieser Daten würde die Festplatte nicht aufwecken, da sie wahrscheinlich zwischengespeichert würden, wenn sie zweimal pro Sekunde ausgeführt würden. Haben Sie Ihre Dateisysteme mit noatime gemountet? Siehe auch btracevon blktrace, um die Quellen der Festplattenaktivität zu untersuchen.
Stéphane Chazelas
1
Wenn Sie es sich noch nicht angesehen haben, xwininfokönnte es sicherlich weit weniger gemeinsam genutzte Bibliotheken als wmctrl laden und auf einer Ebene arbeiten, die näher an Bare X liegt.
msw
1
@msw Ich versuche, das Unfixable zu beheben, das eine automatische Speicherfunktion für Google Earth ist (geschlossene Quellen und das Melden von Fehlern ist Zeitverschwendung)
Teresa e Junior

Antworten:

4

Dies sollte Ihnen alle (OK: die meisten. Was habe ich vergessen? Sockets?) Dateisystemaktivitäten geben, die Schreibvorgänge umfassen:

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

Mit diesen Informationen kann eine funktionierende Chroot-Umgebung in tmpfs erstellt werden (als letzte Möglichkeit; möglicherweise reichen Symlinks zu tmpfs aus). Wenn das Programm in einem RAM-Chroot gestartet wird, hat es keine Chance, die Festplatte direkt zu aktivieren. Kein Schreiben in die Dateisystemhierarchie wird jemals auf die Festplatte geschrieben.

Hauke ​​Laging
quelle
Ich glaube, es gibt Zeiten, in denen das Lesen einer Datei zumindest zum ersten Mal auch die Festplatte aufweckt, nicht wahr? Ich frage mich, ob blktracedas das richtige Werkzeug dafür wäre, aber es würde eine Kernel-Kompilierung erfordern # CONFIG_BLK_DEV_IO_TRACE is not set:( Das geht jedoch über den Rahmen dieser Frage hinaus. Danke!
Teresa e Junior
1
@TeresaeJunior Sicher, aber wer würde das als Problem betrachten? Hier geht es darum, das Skript ständig laufen zu lassen und nicht darum, es zu starten. Und Sie können die tmpfs aus boot.local/ erstellen, rc.localsodass Sie keinen Festplattenzugriff haben, selbst wenn Sie das Skript später starten. Ich habe es mir nur angesehen blktrace(wusste das vorher nicht). Das ist so schrecklich, dass ich mich frage, ob ich heute Nacht einschlafen werde ...
Hauke ​​Laging
Ja, ich sollte mir darüber keine Sorgen mehr machen, du hast wieder Recht. Aber ich denke, ich werde auch diese Nacht des Schlafes verlieren, wenn ich den Kernel kompiliere, da ich alles überprüfen möchte, was die Festplatte ständig weckt, nicht nur diesen speziellen Google Earth-Hack :)
Teresa e Junior
6

Es ist möglicherweise einfacher und zuverlässiger, sich darauf zu verlassen, dass Ihr Fenstermanager oder X11 dies erledigt, indem Sie eine "echte" X11-Anwendung schreiben.

Was Sie von der Shell erwarten, ist etwas, das sich beim Fenstermanager registriert und auf einen gewünschten Ereignistyp wartet, bevor Sie zur Shell zurückkehren. Es ist viel lastfreundlicher, wenn Sie eine Schleife innerhalb der Shell vermeiden können. (Ihre until xdotool...Ursachen laden, weil es keine Verzögerung (Schlaf) innerhalb der Schleife gibt.)

Ah ... hatte anscheinend xdotooldiese Funktion vor über einem Jahr hinzugefügt --sync. Das ist in meiner aktuellen Linux-Distribution (Debian Squeeze) nicht verfügbar, daher habe ich es nicht ausprobiert.

Der xdotool-Entwickler beantwortet eine ähnliche Frage wie Sie: https://groups.google.com/d/msg/xdotool-users/7zfKTtyWm0Q/DM6TSOBUWZMJ

Carl Cravens
quelle
Ja, genau, -syncsollte tun, was ich will, aber es braucht das, whileweil es irgendwann abstürzt, bevor das Fenster erscheint, und zu viel CPU verschwendet. Ich habe tatsächlich xdotoolaus dem Quellcode kompiliert, weil der von Debian unglaublich langsam zu tippen war. Das Schreiben einer Anwendung, die direkt mit X interagiert, ist mir eigentlich ein Rätsel. Trotzdem danke!
Teresa e Junior