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”.
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”.
Odpowiedzi:
Korzystam z programu wywoływanego w xprintidle
celu sprawdzenia czasu bezczynności X, który, jak przypuszczam, używa tego samego źródła danych co wygaszacze ekranu. xprintidle
wydaje 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, xprintidle
któ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 xprintidle
gorą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 -x
bezpośrednio poniżej, #!/bin/sh
aby uzyskać informacje wyjściowe, aby zobaczyć, jak to działa.
Używam xssstate
do takich celów. Jest dostępny w suckless-tools
pakiecie 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
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 < 5
aż 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.
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"