Exécutez une commande si Linux est inactif pendant 5 minutes

16

Je voudrais exécuter une commande telle que

 notify-send 'a'

si ma machine Linux est inactive depuis 5 minutes.

Par inactif, je veux dire la même chose qu'un économiseur d'écran qui s'active utiliserait pour définir "inactif".

slhck
la source
OK, qu'as-tu essayé? Qu'est-ce que Google a dit? Avez-vous tenté de savoir comment l'économiseur d'écran détecte cela? Veuillez prendre le temps de rechercher avant de poster des questions ici et de lire Comment poser une bonne question .
terdon
Je n'ai trouvé qu'un programme xautolockmais il n'y a pas d'exemples

Réponses:

20

J'utilise un programme appelé xprintidlepour connaître le temps d'inactivité X, qui, je suppose, utilise la même source de données que les économiseurs d'écran. xprintidlene semble plus vraiment avoir d'amont, mais le paquet Debian est bel et bien vivant.

C'est une application très simple: elle retourne le nombre de millisecondes depuis la dernière interaction X:

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

(Remarque: en raison du système sous-jacent, il donnera systématiquement une valeur en ms légèrement inférieure au temps d'inactivité "réel").

Vous pouvez l'utiliser pour créer un script qui exécute une certaine séquence après cinq minutes d'inactivité via par exemple:

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

Le décalage de 100 ms est dû à la bizarrerie notée précédemment qui xprintidleretournera toujours un temps légèrement inférieur au temps d'inactivité "réel" lorsqu'il est exécuté comme ceci. Il fonctionnera sans ce décalage, et sera alors plus précis au dixième de seconde, mais il déclenchera le xprintidlecontrôle frénétiquement pendant les dernières millisecondes avant la fin d'un intervalle. Pas un porc de performance en aucune façon, mais je trouverais cela inélégant.

J'ai utilisé une approche similaire dans un script Perl (un plugin irssi) pendant un certain temps, mais ce qui précède vient d'être écrit et n'a pas vraiment été testé, à l'exception de quelques essais pendant l'écriture.

Essayez-le en l'exécutant dans un terminal au sein de X. Je recommande de définir le délai d'expiration à par exemple 5000 ms pour les tests, et en ajoutant set -xdirectement ci-dessous #!/bin/shpour obtenir une sortie informative pour voir comment cela fonctionne.

Daniel Andersson
la source
5

J'utilise xssstateà de telles fins. Il est disponible en suckless-toolspackage dans Debian ou Ubuntu , ou en amont .

Ensuite, vous pouvez utiliser le script shell suivant:

#!/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
la source
1

Voici une application C que j'ai trouvée que vous pouvez compiler.

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

Il a besoin de quelques bibliothèques pour se construire. Sur mon système Fedora 19, j'avais besoin des bibliothèques suivantes:

$ 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

Une fois ceux-ci installés, j'ai compilé ce qui précède comme suit:

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

Vous pouvez voir qu'il est capable de signaler le nombre de secondes que X détecte comme temps d'inactivité en l'exécutant comme suit:

$ 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

En utilisant cet exécutable, vous pouvez créer un script qui peut faire quelque chose comme ça, en surveillant le temps d'inactivité signalé par 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

Ce qui précède montre still < 5jusqu'à ce que 5 secondes d'inactivité se soient écoulées, moment auquel il commence à dire now > 5, ce qui signifie que plus de 5 secondes se sont écoulées.

REMARQUE: vous pouvez intégrer votre notify-send 'a'dans l'exemple ci-dessus.

Les références

slm
la source
-1

les ports bsd (collection de packages) ont un programme qui peut le faire:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
il est disponible par exemple ici:
http://distcache.freebsd.org/local- distfiles / novel / xidle-26052015.tar.bz2

construire comme:

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

notez que -program doit contenir le chemin complet du binaire, car il est passé à execv ().

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