Vorrei eseguire un comando come
notify-send 'a'
se la mia macchina Linux è rimasta inattiva per 5 minuti.
Per inattivo, intendo la stessa cosa che uno screen saver che viene attivato userebbe per definire "inattivo".
Vorrei eseguire un comando come
notify-send 'a'
se la mia macchina Linux è rimasta inattiva per 5 minuti.
Per inattivo, intendo la stessa cosa che uno screen saver che viene attivato userebbe per definire "inattivo".
Risposte:
Uso un programma chiamato xprintidle
per scoprire il tempo di inattività X, che suppongo fortemente utilizzi la stessa fonte di dati degli screensaver. xprintidle
non sembra più avere un upstream, ma il pacchetto Debian è vivo e vegeto.
È un'applicazione molto semplice: restituisce la quantità di millisecondi dall'ultima interazione X:
$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932
(nota: a causa del sistema sottostante, fornirà costantemente un valore in ms leggermente inferiore al tempo di inattività "effettivo").
Puoi usarlo per creare uno script che esegue una determinata sequenza dopo cinque minuti di inattività tramite ad esempio:
#!/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
L'offset di 100 ms è dovuto alla stranezza notata in precedenza xprintidle
restituirà sempre un tempo leggermente inferiore al tempo di inattività "effettivo" quando eseguito in questo modo. Funzionerà senza questo offset e sarà quindi più preciso di un decimo di secondo, ma attiverà il xprintidle
controllo freneticamente negli ultimi millisecondi prima della fine di un intervallo. Non un maiale da prestazione in alcun modo, ma lo troverei inelegante.
Ho usato un approccio simile in uno script Perl (un plug-in irssi) per un po 'di tempo, ma quanto sopra è stato appena scritto e non è stato testato se non per alcune prove durante la scrittura.
Provalo eseguendolo in un terminale all'interno di X. Ti consiglio di impostare il timeout su ad es. 5000 ms per il test e di aggiungere set -x
direttamente sotto #!/bin/sh
per ottenere un output informativo per vedere come funziona.
Uso xssstate
per tali scopi. È disponibile in suckless-tools
pacchetto in Debian o Ubuntu o upstream .
Quindi è possibile utilizzare il seguente script shell:
#!/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
Ecco un'applicazione C che ho trovato che puoi compilare.
$ 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);
}
}
Ha bisogno di un paio di librerie da compilare. Sul mio sistema Fedora 19 avevo bisogno delle seguenti librerie:
$ 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
Una volta installati questi ho compilato quanto sopra in questo modo:
$ gcc xidle.c -o xidle -lX11 -lXext -lXss
Puoi vedere che è in grado di segnalare il numero di secondi che X sta rilevando come tempo di inattività eseguendolo in questo modo:
$ 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
Usando questo eseguibile potresti mettere insieme uno script che può fare qualcosa del genere, monitorando il tempo di inattività riportato da 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
Quanto sopra mostra still < 5
fino a quando sono trascorsi 5 secondi di inattività, a quel punto inizia a dire now > 5
, il che significa che sono trascorsi 5+ secondi.
NOTA: è possibile incorporare notify-send 'a'
l'esempio sopra riportato.
bsd porte (collezione di pacchetti) ha un programma che può fare questo:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
è disponibile ad es. qui:
http://distcache.freebsd.org/local- distfiles / romanzo / xidle-26052015.tar.bz2
costruire come:
# apt-get install libxss-dev # for include/X11/extensions/scrnsaver.h
# gcc -o /usr/local/bin/xidle xidle.c -lX11 -lXss
si noti che il programma deve contenere l'intero percorso del file binario, poiché viene passato a execv ().
$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"