Esegui un comando quando il sistema è inattivo e quando è di nuovo attivo


15

Voglio eseguire un comando quando l'utente diventa inattivo (il sistema è inattivo). Per esempio:

echo "You started to be inactive."

Inoltre, quando l'utente diventa di nuovo attivo (il sistema non è più inattivo):

echo "You started to be active, again."

Ho bisogno di uno script di shell che lo farà. È possibile senza un timer / intervallo? Forse alcuni eventi di sistema?


2
Puoi approfondire un po 'di più i dettagli su ciò che realmente vuoi ottenere?
Nils,

3
Come si misura l'ozio? Un utente sta guardando un film inattivo (perché non interagisce con il computer)? Un utente che ha effettuato l'accesso in remoto è attivo?
Gilles 'SO-smetti di essere malvagio' il

Da quello che so, il sistema ha questo concetto integrato: inattivo , attivo ecc. È giusto?
Ionică Bizău,

@ IonicăBizău: Non proprio. Inattivo nel contesto del sistema significherebbe solo che tutti i processi stanno dormendo, cioè "aspettando qualcosa". Anche se questo può accadere abbastanza spesso su un sistema moderno e può anche accadere per la maggior parte del tempo, non rimane così finché c'è sempre qualcosa da fare e se aggiorna l'orologio. L'ozio , specialmente nel contesto della tua domanda, è più una funzione dell'utente che del sistema e anche di solito è collegato a una sessione specifica.
Adaephon,

@Adaephon Ok. Nel mio concetto, un sistema è inattivo quando l'utente non esegue alcuna azione (spostamento del mouse, clic, pressione dei tasti) sul computer per x minuti. Il sistema diventa attivo quando l'utente effettua la prima azione: fa clic su un pulsante del mouse, lo sposta, preme un tasto e così via. È possibile rilevare questi stati inattivi * / * utilizzando uno script di shell?
Ionică Bizău,

Risposte:


17

Questo thread nei forum ArchLinux contiene un breve programma C che richiede a xscreensaver informazioni per quanto tempo l'utente è rimasto inattivo, questo sembra essere abbastanza vicino alle tue esigenze:

#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);
}

Salva come getIdle.ce compila con

gcc -o getIdle getIdle.c -lXss -lX11

per ottenere un file eseguibile getIdle. Questo programma stampa il "tempo di inattività" (l'utente non si sposta / fa clic con il mouse, non usa la tastiera) in millisecondi, quindi uno script bash che si basa su questo potrebbe apparire così:

#!/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

Ciò richiede ancora il polling regolare, ma fa tutto il necessario ...


Funziona come previsto! +1
Ionică Bizău,

Vale la pena di più punti!
Ionică Bizău,

2
Potresti salvarti compilando il tuo programma e semplicemente utilizzarlo xprintidle, che è disponibile nella maggior parte delle distribuzioni e fa esattamente la stessa cosa.
Riot

3

TMOUT in bash termina una sessione interattiva dopo il numero di secondi impostato. Puoi usare quel meccanismo.

Puoi catturare il logout impostando una trappola corrispondente (non l'ho testato) o usando gli script bash-logout (~ / .bash_logout).

Ecco una buona risposta da superutente in quella direzione.


Questo non risolve il modo in cui l'utente eseguirà un comando, anziché disconnettersi, dopo che $TMOUTsono trascorsi alcuni secondi.
Chepner,

Puoi aggiungere ulteriori informazioni alla tua risposta? Non è ancora chiaro per me ...
Ionică Bizău

@chepner Ho aggiunto qualche dettaglio in più alla mia risposta.
Nils,

Ad ogni modo, questo semplicemente disconnette l'utente dopo che il tempo è scaduto. Non penso che ci sia modo di interrompere il logout da una EXITtrappola o da .bash_logout.
chepner,

3

Non è esattamente quello che hai chiesto, ma c'è sempre il batchcomando (di solito una speciale atchiamata del comando e l'utilizzo del atd-daemon).

batchti consente di eseguire un comando da eseguire quando la media del carico scende al di sotto di un certo limite (in genere 1,5, ma può essere impostato all'avvio atd). Con atè anche possibile indicare un lavoro in modo tale che invece di essere eseguito in un determinato momento; il lavoro viene appena consegnato batchin quel momento e viene eseguito per la prima volta quando la media del carico diminuisce (ad es. viene eseguita non appena la media del carico scende al di sotto di 1,5 in qualche momento dopo le 2:00).

Sfortunatamente un lavoro batch verrà quindi eseguito fino alla fine, non si fermerà se il computer non è più inattivo.

+++

Se devi seguire il percorso di programmazione (che sembra dalle altre risposte), penso che proverei a fare qualcosa di simile ai demoni atdo crond, che ha monitorato gli utenti che hanno effettuato l'accesso e / o caricano la media. Questo demone potrebbe quindi eseguire script / programmi da una determinata directory e avviarli / continuare o arrestarli (con segnali) secondo necessità.


Se lo facessi e utilizzassi i .lockfile, potresti facilmente gestire i problemi di temporizzazione.
mikeserv,

2

Questo thread ha un paio di soluzioni basate sul rilevamento dell'attività della tastiera e del mouse. Corro xprintidleda un cron job che inizia ogni pochi minuti. Ma come sottolineano xprintidlenon è mantenuto, quindi potresti voler installare il modulo Perl e usarlo invece:

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

Userei entrambe le soluzioni eseguendo il polling da cron, in uno script che esce in alto se l'interfaccia utente non è stata sufficientemente inattiva. Ovviamente la sceneggiatura avrebbe bisogno di una export DISPLAY=:0.0per parlare con X11.

Ricorda che la tastiera e il mouse potrebbero essere inattivi quando si guarda un film o si esegue un'attività pesante per la CPU.


1

Non conosco un modo per farlo senza eseguire il polling di una sorta di statistiche di sistema, come le altre risposte utilizzano uno screensaver o bash inattivo o in esecuzione da .bash_logout, ma ecco un'idea per controllare l'utilizzo della CPU.

Ciò comporterebbe comunque il polling ogni n secondi e se l'utilizzo della CPU è inferiore a qualsiasi importo scelto, è possibile eseguire lo script di ciò che si desidera eseguire. Tuttavia, qualunque cosa tu esegua potrebbe aumentare l'utilizzo della CPU, ma potresti usare bene le tue "cose" per non contarle.

Ecco uno script di test che utilizza top, ma potresti invece utilizzare mpstat o verificare invece le medie di caricamento?

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

Questa è solo una sceneggiatura che ho messo insieme per provare a leggere il minimo dall'alto. Potresti analizzare /proc/statma penso che mostri solo i tempi totali e dovresti confrontare i risultati in un intervallo. Top ha il suo problema per me (Linux Mint 16), al primo avvio sembra non cambiare mai cpustats, come se dovesse aspettare per analizzare / proc / stat stesso, quindi il top -bn2teorico top -bn1dovrebbe funzionare.


Ugh ... davvero? Polling delle statistiche della CPU?
Rolf

A proposito, potresti anche weseguire il polling del comando che mostra il tempo di inattività dell'utente. - A proposito, non sto giudicando, è solo che per me, voglio rilevare il minimo per mettere la macchina in pausa, per risparmiare energia e il polling va contro questo.
Rolf

@Rolf Sembra abbastanza giudicante ... dal momento che quel commento non aggiunge molto, probabilmente dovrebbe essere rimosso, sì? Ad ogni modo, le altre risposte usano il tempo di inattività in diversi modi, ma come si può rilevare il minimo senza guardare / chiedere al sistema?
Xen2050
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.