Führen Sie einen Befehl aus, wenn das System inaktiv ist und wieder aktiv ist

15

Ich möchte einen Befehl ausführen, wenn der Benutzer inaktiv wird (das System ist inaktiv). Beispielsweise:

echo "You started to be inactive."

Wenn der Benutzer wieder aktiv wird (das System ist nicht mehr im Leerlauf):

echo "You started to be active, again."

Ich benötige ein Shell-Skript, das dies erledigt. Ist das ohne Timer / Intervall möglich? Vielleicht einige Systemereignisse?

Ionică Bizău
quelle
2
Können Sie etwas detaillierter auf das eingehen, was Sie tatsächlich erreichen möchten?
Nils
3
Wie messen Sie Müßiggang? Schaut sich ein Benutzer einen Film im Leerlauf an (weil er nicht mit dem Computer interagiert)? Ist ein Benutzer, der remote angemeldet ist, aktiv?
Gilles 'SO - hör auf böse zu sein'
Soweit ich weiß, hat das System dieses eingebaute Konzept: Leerlauf , Aktiv usw. Stimmt das?
Ionică Bizău
@ IonicăBizău: Nicht wirklich. Leerlauf im Kontext des Systems würde nur bedeuten, dass alle Prozesse schlafen, das heißt, auf etwas warten. Obwohl dies auf einem modernen System häufig vorkommt und die meiste Zeit sogar der Fall ist, bleibt es nicht so, solange immer etwas zu tun ist und die Uhr aktualisiert wird. Das Nichtstun , insbesondere im Zusammenhang mit Ihrer Frage, ist eher eine Funktion des Benutzers als des Systems und in der Regel sogar an eine bestimmte Sitzung gebunden.
Adaephon
@Adaephon Ok. In meinem Konzept ist ein System inaktiv, wenn der Benutzer x Minuten lang keine Aktion (Mausbewegung, Klicken, Tastendruck) am Computer ausführt. Das System wird aktiv, wenn der Benutzer die erste Aktion ausführt: Klicken mit der Maus, Bewegen mit der Maus, Drücken einer Taste usw. Ist es möglich, diese * / * aktiven Leerlaufzustände mithilfe eines Shell-Skripts zu erkennen?
Ionică Bizău

Antworten:

17

Dieser Thread in den ArchLinux-Foren enthält ein kurzes C-Programm, das den xscreensaver abfragt, um zu erfahren, wie lange der Benutzer inaktiv war. Dies scheint Ihren Anforderungen ziemlich nahe zu kommen:

#include <X11/extensions/scrnsaver.h>
#include <stdio.h>

int main(void) {
    Display *dpy = XOpenDisplay(NULL);

    if (!dpy) {
        return(1);
    }

    XScreenSaverInfo *info = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
    printf("%u\n", info->idle);

      return(0);
}

Speichern Sie diese als getIdle.cund kompilieren Sie mit

gcc -o getIdle getIdle.c -lXss -lX11

um eine ausführbare Datei zu erhalten getIdle. Dieses Programm gibt die "Leerlaufzeit" (Benutzer bewegt / klickt nicht mit der Maus, verwendet keine Tastatur) in Millisekunden aus, sodass ein darauf aufbauendes Bash-Skript folgendermaßen aussehen könnte:

#!/bin/bash

idle=false
idleAfter=3000     # consider idle after 3000 ms

while true; do
  idleTimeMillis=$(./getIdle)
  echo $idleTimeMillis  # just for debug purposes.
  if [[ $idle = false && $idleTimeMillis -gt $idleAfter ]] ; then
    echo "start idle"   # or whatever command(s) you want to run...
    idle=true
  fi

  if [[ $idle = true && $idleTimeMillis -lt $idleAfter ]] ; then
    echo "end idle"     # same here.
    idle=false
  fi
  sleep 1      # polling interval

done

Dies erfordert noch regelmäßige Abfragen, aber es tut alles, was Sie brauchen ...

Jaspis
quelle
Funktioniert wie vermutet! +1
Ionică Bizău
Sie sind mehr Punkte wert!
Ionică Bizău
2
Sie könnten es sich sparen, Ihr eigenes Programm zu kompilieren und einfach verwenden xprintidle, was in den meisten Distributionen verfügbar ist und genau dasselbe tut.
Aufstand
3

TMOUT in bash beendet eine interaktive Sitzung nach der festgelegten Anzahl von Sekunden. Sie können diesen Mechanismus verwenden.

Sie können die Abmeldung erfassen, indem Sie einen entsprechenden Trap setzen (das habe ich nicht getestet) oder indem Sie die Bash-Logout-Skripte (~ / .bash_logout) verwenden.

Hier ist eine gute Superuser-Antwort in diese Richtung.

Nils
quelle
Hier wird nicht angesprochen, wie der Benutzer einen Befehl ausführen würde, anstatt sich nach Ablauf von $TMOUTSekunden abzumelden.
Chepner
Können Sie Ihrer Antwort weitere Informationen hinzufügen? Es ist immer noch unklar für mich ...
Ionică Bizău
@chepner Ich habe meiner Antwort ein paar Details hinzugefügt.
Nils
In beiden Fällen wird der Benutzer nach Ablauf der Zeit einfach abgemeldet. Ich glaube, es gibt keine Möglichkeit, das Abmelden abzubrechen, weder von einer EXITFalle noch von .bash_logout.
Chepner
3

Dies ist nicht ganz das, wonach Sie gefragt haben, aber es gibt immer den Befehl -command batch(normalerweise ein spezieller Aufruf des atBefehls und die Verwendung des atdDämons -daemon).

batchErmöglicht das Aufrufen eines Befehls, der ausgeführt wird, wenn der Lastdurchschnitt eine bestimmte Grenze unterschreitet (normalerweise 1,5, kann jedoch beim Starten festgelegt werden atd). Damit ist ates auch möglich, einen Job so anzuweisen, dass er nicht zu einer bestimmten Zeit ausgeführt wird. Der Job wird gerade zu batchdiesem Zeitpunkt geliefert und zum ersten Mal ausgeführt, wenn der Lastdurchschnitt abfällt (z. B., wenn der Lastdurchschnitt irgendwann nach 2:00 Uhr unter 1,5 abfällt).

Leider läuft ein Batch-Job dann zu Ende, er stoppt nicht, wenn der Computer nicht mehr im Leerlauf ist.

+++

Wenn Sie die Programmierroute gehen müssen (wie es aus den anderen Antworten hervorgeht), würde ich versuchen, etwas Ähnliches wie die Dämonen atdoder zu machen crond, die die angemeldeten Benutzer und / oder den Lastdurchschnitt überwachen. Dieser Daemon könnte dann Skripte / Programme aus einem bestimmten Verzeichnis ausführen und diese nach Bedarf starten / fortsetzen oder stoppen (mit Signalen).

Baard Kopperud
quelle
Wenn Sie dies tun und .lockDateien verwenden, können Sie Zeitprobleme leicht lösen.
mikeserv
2

Dieser Thread bietet eine Reihe von Lösungen, die auf der Erkennung von Tastatur- und Mausaktivitäten basieren. Ich laufe xprintidlevon einem Cron Job aus, der alle paar Minuten startet. Aber wie sie darauf hinweisen, xprintidleist dies nicht der Fall. Vielleicht möchten Sie das Perl-Modul installieren und dieses stattdessen verwenden:

$ cpanm X11::IdleTime
...
$ sleep 10; perl -MX11::IdleTime -le 'print GetIdleTime()'
9

Ich würde beide Lösungen durch Abfragen von cron in einem Skript verwenden, das oben beendet wird, wenn die Benutzeroberfläche nicht ausreichend inaktiv ist. Natürlich würde das Skript eine benötigen export DISPLAY=:0.0, um mit X11 zu sprechen.

Denken Sie daran, dass Ihre Tastatur und Maus möglicherweise inaktiv sind, wenn Sie einen Film ansehen oder eine CPU-schwere Aufgabe ausführen.

Metamorph
quelle
1

Ich kenne keine Möglichkeit, dies zu tun, ohne eine Art Systemstatistik abzufragen, wie die anderen Antworten einen Bildschirmschoner oder einen Bash-Leerlauf-Timer verwenden oder von .bash_logout aus ausgeführt werden, aber hier ist eine Idee, die CPU-Auslastung zu überprüfen.

Dies würde immer noch ein Abfragen alle n Sekunden beinhalten. Wenn Ihre CPU-Auslastung unter dem von Ihnen gewählten Wert liegt, können Sie Skripte erstellen, die Sie ausführen möchten. Was auch immer Sie ausführen, kann die CPU-Auslastung erhöhen, aber Sie können Ihre "Sachen" auch gut nutzen, um sie nicht zu zählen.

Hier ist ein Testskript mit top, aber Sie könnten stattdessen mpstat verwenden oder stattdessen die Durchschnittswerte für das Laden überprüfen?

while true
do
idle=$(top -bn2 | grep "Cpu(s)"|tail -n 1|sed "s/.*, *\([0-9.]*\)%* id.*/\1/")
echo "idle is $idle"
if [[ $idle > 90 ]]
then
    echo "idle above 90%"
    echo "Do stuff now"
else
    echo "idle below 90%"
    echo "Stop doing stuff now"
fi
sleep 1
done

Das ist nur ein Skript, das ich zusammengestellt habe, um zu testen, ob ich den Leerlauf von oben gelesen habe. Sie könnten analysieren, /proc/stataber ich denke, es werden nur die Gesamtzeiten angezeigt, und Sie müssen die Ergebnisse über einen Zeitraum vergleichen. Top hat für mich ein eigenes problem (linux mint 16), auf den ersten blick scheint es cpustats nie zu ändern, als ob es warten müsste, um / proc / stat selbst zu parsen, daher sollte das top -bn2aber theoretisch top -bn1funktionieren.

Xen2050
quelle
Ugh ... wirklich? CPU-Statistiken abrufen?
Rolf
Übrigens können Sie auch den wBefehl abrufen, der die Leerlaufzeit des Benutzers anzeigt. - Übrigens, ich urteile nicht, es ist nur so, dass ich Leerlauf feststellen möchte, um die Maschine in den Ruhezustand zu versetzen, um Energie zu sparen, und Polling geht dagegen vor.
Rolf
@Rolf Klingt ziemlich nach einem Urteil ... da dieser Kommentar wirklich nicht viel hinzufügt, sollte er wahrscheinlich entfernt werden, ja? Wie auch immer, die anderen Antworten verwenden die Leerlaufzeit auf verschiedene Arten, aber wie können Sie Leerlauf erkennen, ohne das System zu betrachten oder zu fragen?
Xen2050