Execute um comando se o Linux estiver ocioso por 5 minutos

16

Gostaria de executar um comando como

 notify-send 'a'

se a minha máquina Linux estiver inativa por 5 minutos.

Por inativo, quero dizer a mesma coisa que uma proteção de tela que é ativada usaria para definir "ocioso".

    
por slhck 29.08.2013 / 19:53

4 respostas

18

Eu uso um programa chamado xprintidle para descobrir o tempo ocioso do X, que estou achando que usa a mesma fonte de dados que os protetores de tela. xprintidle realmente não parece ter mais um upstream, mas o pacote Debian está vivo e bem.

É uma aplicação muito simples: devolve a quantidade de milissegundos desde a última interação X:

$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932

(nota: devido ao sistema subjacente, ele fornecerá consistentemente um valor em ms um pouco menor que o tempo ocioso "real").

Você pode usar isso para criar um script que execute uma determinada sequência depois de cinco minutos de tempo ocioso, por exemplo:

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

O deslocamento de 100 ms é devido à peculiaridade observada anteriormente de que xprintidle sempre retornará um tempo um pouco menor que o tempo ocioso "real" quando executado assim. Ele funcionará sem esse deslocamento e será mais preciso até um décimo de segundo, mas acionará a verificação xprintidle freneticamente durante os últimos milésimos de segundo antes de um término do intervalo. Não é um especialista em performance, mas eu acharia isso deselegante.

Eu usei uma abordagem semelhante em um script Perl (um plugin irssi) por algum tempo, mas o acima foi escrito e não foi realmente testado, exceto por algumas tentativas durante a escrita.

Experimente, executando-o em um terminal no X. Recomendo definir o tempo limite para, por exemplo, 5000 ms para teste e adicionando set -x diretamente abaixo de #!/bin/sh para obter saída informativa para ver como funciona.

    
por 30.08.2013 / 00:40
5

Eu uso xssstate para esses fins. Está disponível em suckless-tools package em Debian ou Ubuntu , ou upstream .

Então você pode usar o seguinte 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
    
por 28.06.2016 / 06:39
1

Aqui está uma aplicação C que encontrei e que você pode 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);
    }
}

Precisa de algumas bibliotecas para construir. No meu sistema Fedora 19 eu precisava das seguintes 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

Uma vez que estas foram instaladas eu compilei o acima da seguinte forma:

$ gcc xidle.c -o xidle -lX11 -lXext -lXss

Você pode ver que é capaz de relatar o número de segundos que o X está detectando como tempo ocioso executando da seguinte forma:

$ 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 esse executável, você pode criar um script que possa fazer algo assim, monitorando o tempo ocioso relatado 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

O texto acima mostra still < 5 até que 5 segundos de tempo inativo tenham decorrido, quando começa a dizer now > 5 , o que significa que 5+ segundos se passaram.

OBSERVAÇÃO: você pode incorporar seu notify-send 'a' no exemplo acima.

Referências

por 11.05.2014 / 07:05
-1

O bsd ports (coleção de pacotes) tem um programa que pode fazer isso: link
está disponível, por exemplo aqui: link

construir como:

 # apt-get install libxss-dev # for include/X11/extensions/scrnsaver.h
 # gcc -o /usr/local/bin/xidle xidle.c -lX11 -lXss

observe que o -program precisa conter o caminho completo para o binário, pois é passado para execv ().

$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"  
    
por 28.06.2016 / 01:43