Ejecute un comando si Linux está inactivo durante 5 minutos

16

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".

slhck
fuente
OK, que has intentado? ¿Qué dijo google? ¿Has intentado descubrir cómo el protector de pantalla detecta esto? Tómese el tiempo de buscar antes de publicar preguntas aquí y lea Cómo hacer una buena pregunta .
terdon
Solo encontré un programa xautolockpero no hay ejemplos

Respuestas:

20

Utilizo un programa llamado xprintidlepara averiguar el tiempo de inactividad X, que supongo que utiliza la misma fuente de datos que los protectores de pantalla. xprintidleya 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 xprintidlesiempre 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 xprintidleverificació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 -xdirectamente a continuación #!/bin/shpara obtener una salida informativa para ver cómo funciona.

Daniel Andersson
fuente
5

Yo uso xssstatepara tales fines. Está disponible en suckless-toolspaquete 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
Petr Shevtsov
fuente
1

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 < 5hasta 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.

Referencias

slm
fuente
-1

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"  
r00t
fuente