Execute um comando se o Linux estiver ocioso por 5 minutos

16

Eu gostaria de executar um comando como

 notify-send 'a'

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

Por ocioso, quero dizer a mesma coisa que um protetor de tela que é ativado usaria para definir "ocioso".

slhck
fonte
OK, o que você tentou? O que o google disse? Você já tentou descobrir como o protetor de tela detecta isso? Reserve um tempo para pesquisar antes de postar perguntas aqui e leia Como fazer uma boa pergunta .
terdon
Eu só encontrei um programa xautolock, mas não há exemplos

Respostas:

20

Eu uso um programa chamado xprintidlepara descobrir o tempo ocioso do X, que eu acho fortemente que usa a mesma fonte de dados que os protetores de tela. xprintidlerealmente não parece mais ter um upstream, mas o pacote Debian está vivo e bem.

É uma aplicação muito simples: retorna a quantidade de milissegundos desde a última interação do 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 ligeiramente inferior ao tempo ocioso "real").

Você pode usar isso para criar um script que execute uma determinada sequência após cinco minutos de tempo ocioso via, 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 deve-se à peculiaridade observada anteriormente, que xprintidlesempre retornará um tempo um pouco menor que o tempo ocioso "real" quando executado dessa maneira. Ele funcionará sem esse deslocamento e será mais preciso até um décimo de segundo, mas disparará a xprintidleverificação freneticamente durante os últimos milissegundos antes do final do intervalo. Não é um porco da performance, mas acho isso deselegante.

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

Tente executá-lo em um terminal no X. Eu recomendo definir o tempo limite para, por exemplo, 5000 ms para testes e adicionar set -xdiretamente abaixo #!/bin/shpara obter uma saída informativa e ver como funciona.

Daniel Andersson
fonte
5

Eu uso xssstatepara esses fins. Está disponível no suckless-toolspacote no 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
Petr Shevtsov
fonte
1

Aqui está um aplicativo C que eu achei 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);
    }
}

Ele 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 estes foram instalados, eu compilei o acima descrito assim:

$ 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-o da seguinte maneira:

$ 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 montar um script que pode 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 exemplo acima mostra still < 5até 5 segundos de tempo ocioso, ponto em que ele começa a dizer now > 5, o que significa que mais de 5 segundos se passaram.

NOTA: Você pode incorporar o seu notify-send 'a'no exemplo acima.

Referências

slm
fonte
-1

As portas bsd (coleção de pacotes) têm um programa que pode fazer isso:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
está disponível, por exemplo, aqui:
http://distcache.freebsd.org/local- distfiles / romance / 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

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

$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"  
r00t
fonte