Führen Sie einen Befehl aus, wenn Linux 5 Minuten inaktiv ist

16

Ich möchte einen Befehl ausführen wie

 notify-send 'a'

wenn mein Linux-Rechner 5 Minuten im Leerlauf war.

Mit Leerlauf meine ich dasselbe, was ein aktivierter Bildschirmschoner verwenden würde, um "Leerlauf" zu definieren.

slhck
quelle
OK, was hast du versucht? Was hat Google gesagt? Haben Sie versucht herauszufinden, wie der Bildschirmschoner dies erkennt? Bitte nehmen Sie sich die Zeit für die Suche, bevor Sie Fragen hier posten und lesen Sie, wie Sie eine gute Frage stellen .
Terdon
Ich habe nur ein Programm gefunden, xautolockaber es gibt keine Beispiele

Antworten:

20

Ich benutze ein Programm, das aufgerufen wird xprintidle, um die X-Leerlaufzeit herauszufinden. Ich gehe davon aus, dass es dieselbe Datenquelle wie Bildschirmschoner verwendet. xprintidleScheint keinen Upstream mehr zu haben, aber das Debian-Paket ist am Leben und in Ordnung.

Es ist eine sehr einfache Anwendung: Sie gibt die Anzahl der Millisekunden seit der letzten X-Interaktion zurück:

$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932

(Hinweis: Aufgrund des zugrunde liegenden Systems wird durchgehend ein Wert in ms angegeben, der geringfügig unter der "tatsächlichen" Leerlaufzeit liegt.)

Hiermit können Sie ein Skript erstellen, das nach fünf Minuten Leerlaufzeit eine bestimmte Sequenz ausführt, z. B .:

#!/bin/sh

# Wanted trigger timeout in milliseconds.
IDLE_TIME=$((5*60*1000))

# Sequence to execute when timeout triggers.
trigger_cmd() {
    echo "Triggered action $(date)"
}

sleep_time=$IDLE_TIME
triggered=false

# ceil() instead of floor()
while sleep $(((sleep_time+999)/1000)); do
    idle=$(xprintidle)
    if [ $idle -ge $IDLE_TIME ]; then
        if ! $triggered; then
            trigger_cmd
            triggered=true
            sleep_time=$IDLE_TIME
        fi
    else
        triggered=false
        # Give 100 ms buffer to avoid frantic loops shortly before triggers.
        sleep_time=$((IDLE_TIME-idle+100))
    fi
done

Der Versatz von 100 ms ist auf die früher festgestellte Eigenart zurückzuführen, xprintidledie bei dieser Ausführung immer eine Zeit zurückgibt, die geringfügig unter der "tatsächlichen" Leerlaufzeit liegt. Es funktioniert ohne diesen Versatz und ist dann auf eine Zehntelsekunde genau, aber es löst die xprintidlePrüfung in den letzten Millisekunden vor dem Ende eines Intervalls rasend schnell aus . In keinster Weise ein Leistungsschwein, aber ich würde das für unelegant halten.

Ich habe in einem Perl-Skript (einem Irssi-Plugin) schon seit einiger Zeit einen ähnlichen Ansatz verwendet, aber der obige Ansatz wurde nur geschrieben und bis auf einige Testläufe während des Schreibens nicht wirklich getestet.

Probieren Sie es aus, indem Sie es in einem Terminal innerhalb von X ausführen. Ich empfehle, das Timeout zum Testen auf z. B. 5000 ms einzustellen und es set -xdirekt unten hinzuzufügen #!/bin/sh, um eine informative Ausgabe zu erhalten, um zu sehen, wie es funktioniert.

Daniel Andersson
quelle
5

Ich benutze xssstatefür solche Zwecke. Es ist verfügbar in suckless-toolsPaket in Debian oder Ubuntu , oder stromaufwärts .

Dann können Sie das folgende Shell-Skript verwenden:

#!/bin/sh

if [ $# -lt 2 ];
then
    printf "usage: %s minutes command\n" "$(basename $0)" 2>&1
    exit 1
fi

timeout=$(($1*60*1000))
shift
cmd="$@"
triggered=false

while true
do
    tosleep=$(((timeout - $(xssstate -i)) / 1000))
    if [ $tosleep -le 0 ];
    then
        $triggered || $cmd
        triggered=true
    else
        triggered=false
        sleep $tosleep
    fi
done
Petr Shevtsov
quelle
1

Hier ist eine C-Anwendung, die ich gefunden habe und die Sie kompilieren können.

$ more xidle.c 
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/scrnsaver.h>

/* Report amount of X server idle time. */
/* Build with- */
/* cc xidle.c -o xidle -lX11 -lXext -lXss */


int main(int argc, char *argv[])
{
    Display *display;
    int event_base, error_base;
    XScreenSaverInfo info;
    float seconds;

    display = XOpenDisplay("");

    if (XScreenSaverQueryExtension(display, &event_base, &error_base)) {
    XScreenSaverQueryInfo(display, DefaultRootWindow(display), &info);

    seconds = (float)info.idle/1000.0f;
    printf("%f\n",seconds);
    return(0);
    }
    else {
    fprintf(stderr,"Error: XScreenSaver Extension not present\n");
    return(1);
    }
}

Es braucht ein paar Bibliotheken, um zu bauen. Auf meinem Fedora 19-System benötigte ich folgende Bibliotheken:

$ rpm -qf /lib64/libX11.so.6 /lib64/libXext.so.6 /lib64/libXss.so.1
libX11-1.6.0-1.fc19.x86_64
libXext-1.3.2-1.fc19.x86_64
libXScrnSaver-1.2.2-5.fc19.x86_64

Sobald diese installiert waren, habe ich das oben genannte wie folgt kompiliert:

$ gcc xidle.c -o xidle -lX11 -lXext -lXss

Sie können sehen, dass es in der Lage ist, die Anzahl der Sekunden, die X als Leerlaufzeit erkennt, zu melden, indem Sie es wie folgt ausführen:

$ while [ 1 ]; do ./xidle ; sleep 2;done
0.005000
1.948000
3.954000
5.959000
7.965000
0.073000   <--- moved the mouse here which resets it
0.035000

Mit dieser ausführbaren Datei könnten Sie ein Skript zusammenstellen, das so etwas tun kann und die von gemeldete Leerlaufzeit überwacht xidle.

$ while [ 1 ]; do idle=$(./xidle); 
    [ $( echo "$idle > 5" | bc ) -eq 0 ] && echo "still < 5" || echo "now > 5"; 
    sleep 2;
done
still < 5
still < 5
still < 5
now > 5
now > 5
still < 5
still < 5
still < 5

Das obige zeigt an, still < 5bis 5 Sekunden Leerlaufzeit verstrichen sind. An diesem Punkt wird angezeigt now > 5, was bedeutet, dass mehr als 5 Sekunden vergangen sind.

ANMERKUNG: Sie könnten Ihr notify-send 'a'in das obige Beispiel integrieren.

Verweise

slm
quelle
-1

bsd ports (packages collection) hat ein Programm, das das kann:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
es ist zB hier verfügbar:
http://distcache.freebsd.org/local- distfiles / novel / xidle-26052015.tar.bz2

bauen wie:

 # apt-get install libxss-dev # for include/X11/extensions/scrnsaver.h
 # gcc -o /usr/local/bin/xidle xidle.c -lX11 -lXss

Beachten Sie, dass das -Programm den vollständigen Pfad zur Binärdatei enthalten muss, da er an execv () übergeben wird.

$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"  
r00t
quelle