Me gustaría ejecutar un comando como
notify-send 'a'
si mi máquina Linux ha estado inactiva durante 5 minutos.
Por inactivo, quiero decir lo mismo que un protector de pantalla que se activa usaría para definir "inactivo".
Me gustaría ejecutar un comando como
notify-send 'a'
si mi máquina Linux ha estado inactiva durante 5 minutos.
Por inactivo, quiero decir lo mismo que un protector de pantalla que se activa usaría para definir "inactivo".
Respuestas:
Utilizo un programa llamado xprintidle
para averiguar el tiempo de inactividad X, que supongo que utiliza la misma fuente de datos que los protectores de pantalla. xprintidle
ya no parece tener un flujo ascendente, pero el paquete Debian está vivo y bien.
Es una aplicación muy simple: devuelve la cantidad de milisegundos desde la última interacción X:
$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932
(nota: debido al sistema subyacente, siempre dará un valor en ms ligeramente inferior al tiempo de inactividad "real").
Puede usar esto para crear una secuencia de comandos que ejecute una secuencia determinada después de cinco minutos de inactividad mediante, por ejemplo:
#!/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
El desplazamiento de 100 ms se debe a la peculiaridad observada anteriormente que xprintidle
siempre devolverá un tiempo ligeramente inferior al tiempo de inactividad "real" cuando se ejecuta de esta manera. Funcionará sin este desplazamiento, y luego será más preciso a una décima de segundo, pero activará la xprintidle
verificación frenéticamente durante los últimos milisegundos antes de que finalice un intervalo. No es un cerdo de rendimiento de ninguna manera, pero me parece poco elegante.
He usado un enfoque similar en un script de Perl (un complemento irssi) durante bastante tiempo, pero lo anterior se acaba de escribir y no se ha probado realmente, excepto por algunas ejecuciones de prueba durante la escritura.
Pruébelo ejecutándolo en un terminal dentro de X. Recomiendo configurar el tiempo de espera en, por ejemplo, 5000 ms para pruebas, y agregarlo set -x
directamente a continuación #!/bin/sh
para obtener una salida informativa para ver cómo funciona.
Yo uso xssstate
para tales fines. Está disponible en suckless-tools
paquete en Debian o Ubuntu , o en sentido ascendente .
Luego puede usar el siguiente script de 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
Aquí hay una aplicación C que encontré que puedes compilar.
$ 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);
}
}
Necesita un par de bibliotecas para construir. En mi sistema Fedora 19 necesitaba las siguientes bibliotecas:
$ 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 vez que se instalaron, compilé lo anterior así:
$ gcc xidle.c -o xidle -lX11 -lXext -lXss
Puede ver que es capaz de informar la cantidad de segundos que X está detectando como tiempo inactivo ejecutándolo así:
$ 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 este ejecutable, podría crear un script que pueda hacer algo como esto, monitoreando el tiempo de inactividad informado por 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
Lo anterior muestra still < 5
hasta que hayan transcurrido 5 segundos de inactividad, momento en el que comienza a decir now > 5
, lo que significa que han pasado más de 5 segundos.
NOTA: Puede incorporar su notify-send 'a'
en el ejemplo anterior.
bsd ports (paquetes de colección) tiene un programa que puede hacer esto:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
está disponible, por ejemplo, aquí:
http://distcache.freebsd.org/local- distfiles / novel / xidle-26052015.tar.bz2
construir como:
# apt-get install libxss-dev # for include/X11/extensions/scrnsaver.h
# gcc -o /usr/local/bin/xidle xidle.c -lX11 -lXss
tenga en cuenta que el programa necesita contener la ruta completa al binario, ya que se pasa a execv ().
$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"