Wykonaj polecenie, jeśli Linux jest bezczynny przez 5 minut

16

Chciałbym wykonać polecenie takie jak

 notify-send 'a'

jeśli mój komputer z systemem Linux był bezczynny przez 5 minut.

Przez bezczynny mam na myśli to samo, co aktywowany wygaszacz ekranu użyłby do zdefiniowania „bezczynności”.

slhck
źródło
OK, co próbowałeś? Co powiedział Google? Czy próbowałeś dowiedzieć się, w jaki sposób wygaszacz ekranu to wykrywa? Poświęć trochę czasu na wyszukiwanie przed zamieszczeniem tutaj pytań i przeczytaj Jak zadać dobre pytanie .
terdon
Znalazłem tylko program, xautolockale nie ma przykładów

Odpowiedzi:

20

Korzystam z programu wywoływanego w xprintidlecelu sprawdzenia czasu bezczynności X, który, jak przypuszczam, używa tego samego źródła danych co wygaszacze ekranu. xprintidlewydaje się, że nie ma już dodatkowej wersji, ale pakiet Debiana jest żywy i ma się dobrze.

Jest to bardzo prosta aplikacja: zwraca liczbę milisekund od ostatniej interakcji X:

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

(uwaga: ze względu na podstawowy system będzie konsekwentnie dawać wartość w ms nieco niższą niż „rzeczywisty” czas bezczynności).

Możesz użyć tego do stworzenia skryptu, który uruchamia określoną sekwencję po pięciu minutach bezczynności, np .:

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

Przesunięcie 100 ms wynika z wcześniej zauważonego dziwactwa, xprintidlektóre zawsze wykona czas nieco mniejszy niż „rzeczywisty” czas bezczynności, gdy zostanie wykonany w ten sposób. Będzie działał bez tego przesunięcia, a następnie będzie dokładniejszy do jednej dziesiątej sekundy, ale spowoduje xprintidlegorączkowe sprawdzenie w ciągu ostatnich milisekund przed końcem interwału. W żadnym wypadku nie świnia wydajnościowa, ale uważałbym to za nieeleganckie.

Podobne podejście zastosowałem w skrypcie Perla (wtyczka irssi) od dłuższego czasu, ale powyższe zostało właśnie napisane i tak naprawdę nie zostało przetestowane, z wyjątkiem kilku próbnych przebiegów podczas pisania.

Spróbuj, uruchamiając go w terminalu w X. Polecam ustawienie limitu czasu np. 5000 ms na testowanie i dodanie set -xbezpośrednio poniżej, #!/bin/shaby uzyskać informacje wyjściowe, aby zobaczyć, jak to działa.

Daniel Andersson
źródło
5

Używam xssstatedo takich celów. Jest dostępny w suckless-toolspakiecie w Debianie lub Ubuntu lub powyżej .

Następnie możesz użyć następującego skryptu powłoki:

#!/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 Szewcow
źródło
1

Oto aplikacja C, którą znalazłem, którą możesz skompilować.

$ 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);
    }
}

Do zbudowania potrzebuje kilku bibliotek. W moim systemie Fedora 19 potrzebowałem następujących bibliotek:

$ 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

Po ich zainstalowaniu skompilowałem powyższe w następujący sposób:

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

Możesz zobaczyć, że jest w stanie zgłosić liczbę sekund, które X wykrywa jako czas bezczynności, uruchamiając go w następujący sposób:

$ 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

Korzystając z tego pliku wykonywalnego, możesz stworzyć skrypt, który może zrobić coś takiego, monitorując zgłaszany czas bezczynności 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

Powyższe pokazuje, still < 5aż upłynie 5 sekund bezczynności, w którym to momencie zaczyna mówić now > 5, co oznacza, że ​​minęło ponad 5 sekund.

UWAGA: Możesz włączyć swój notify-send 'a'do powyższego przykładu.

Bibliografia

slm
źródło
-1

Porty bsd (kolekcja pakietów) ma program, który może to zrobić:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
jest dostępny np. tutaj:
http://distcache.freebsd.org/local- distfiles / novel / xidle-26052015.tar.bz2

buduj jak:

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

zauważ, że -program musi zawierać pełną ścieżkę do pliku binarnego, ponieważ jest przekazywany do execv ().

$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"  
r00t
źródło