Exécutez une commande lorsque le système est inactif et lorsqu'il est à nouveau actif

15

Je veux exécuter une commande lorsque l'utilisateur devient inactif (le système est inactif). Par exemple:

echo "You started to be inactive."

Aussi, lorsque l'utilisateur redevient actif (le système n'est plus inactif):

echo "You started to be active, again."

J'ai besoin d'un script shell qui fera cela. Est-ce possible sans minuterie / intervalle? Peut-être certains événements système?

Ionică Bizău
la source
2
Pouvez-vous entrer un peu plus dans les détails sur ce que vous voulez réellement réaliser?
Nils
3
Comment mesurez-vous l'oisiveté? Un utilisateur regarde-t-il un film inactif (car il n'interagit pas avec l'ordinateur)? Un utilisateur connecté à distance est-il actif?
Gilles 'SO- arrête d'être méchant'
D'après ce que je sais, le système a ce concept intégré: inactif , actif, etc. Est-ce vrai?
Ionică Bizău
@ IonicăBizău: Pas vraiment. Inactif dans le contexte du système signifierait seulement que tous les processus sont en sommeil, c'est-à-dire «en attente de quelque chose». Bien que cela puisse se produire assez souvent sur un système moderne et peut même être le cas la plupart du temps, cela ne reste pas ainsi tant qu'il y a toujours quelque chose à faire et s'il met à jour l'horloge. L'oisiveté , en particulier dans le contexte de votre question, est plus une fonction de l'utilisateur que du système et même qu'elle est généralement liée à une session spécifique.
Adaephon
@Adaephon Ok. Dans mon concept, un système est inactif lorsque l'utilisateur n'effectue aucune action (déplacement de la souris, clic, pression de touche) sur l'ordinateur pendant x minutes. Le système devient actif lorsque l'utilisateur effectue la première action: clique sur un bouton de la souris, le déplace, appuie sur une touche, etc. Est-il possible de détecter ces états actifs * / * inactifs à l' aide d'un script shell?
Ionică Bizău

Réponses:

17

Ce fil sur les forums ArchLinux contient un court programme C qui interroge xscreensaver pour savoir depuis combien de temps l'utilisateur est inactif, cela semble assez proche de vos besoins:

#include <X11/extensions/scrnsaver.h>
#include <stdio.h>

int main(void) {
    Display *dpy = XOpenDisplay(NULL);

    if (!dpy) {
        return(1);
    }

    XScreenSaverInfo *info = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
    printf("%u\n", info->idle);

      return(0);
}

Enregistrez-le sous getIdle.cet compilez avec

gcc -o getIdle getIdle.c -lXss -lX11

pour obtenir un fichier exécutable getIdle. Ce programme imprime le "temps d'inactivité" (l'utilisateur ne bouge pas / ne clique pas avec la souris, n'utilise pas le clavier) en millisecondes, donc un script bash qui s'appuie sur cela pourrait ressembler à ceci:

#!/bin/bash

idle=false
idleAfter=3000     # consider idle after 3000 ms

while true; do
  idleTimeMillis=$(./getIdle)
  echo $idleTimeMillis  # just for debug purposes.
  if [[ $idle = false && $idleTimeMillis -gt $idleAfter ]] ; then
    echo "start idle"   # or whatever command(s) you want to run...
    idle=true
  fi

  if [[ $idle = true && $idleTimeMillis -lt $idleAfter ]] ; then
    echo "end idle"     # same here.
    idle=false
  fi
  sleep 1      # polling interval

done

Cela nécessite toujours un sondage régulier, mais il fait tout ce dont vous avez besoin ...

Jaspe
la source
Fonctionne comme supposé! +1
Ionică Bizău
Vous valez plus de points!
Ionică Bizău
2
Vous pourriez vous sauver en compilant votre propre programme et en utiliser simplement xprintidle, qui est disponible dans la plupart des distributions et fait exactement la même chose.
Riot
3

TMOUT en bash mettra fin à une session interactive après le nombre de secondes défini. Vous pouvez utiliser ce mécanisme.

Vous migrez capturer la déconnexion en définissant un piège correspondant (je n'ai pas testé cela), ou en utilisant les scripts bash-logout (~ / .bash_logout).

Voici une bonne réponse de superutilisateur dans cette direction.

Nils
la source
Cela ne traite pas de la manière dont l'utilisateur exécuterait une commande, plutôt que de se déconnecter, une fois les $TMOUTsecondes écoulées.
chepner
Pouvez-vous ajouter plus d'informations à votre réponse? Ce n'est toujours pas clair pour moi ...
Ionică Bizău
@chepner J'ai ajouté plus de détails à ma réponse.
Nils
Dans les deux cas, cela déconnecte simplement l'utilisateur une fois le temps écoulé. Je ne pense pas qu'il existe un moyen d'annuler la déconnexion, que ce soit à partir d'un EXITpiège ou à partir de .bash_logout.
chepner
3

Ce n'est pas tout à fait ce que vous avez demandé, mais il y a toujours la batchcommande-(généralement une invocation spéciale de la atcommande-et l'utilisation du atd-daemon).

batchvous permet d'indiquer une commande à exécuter lorsque la charge moyenne chute en dessous d'une certaine limite (généralement 1,5, mais cela peut être défini au démarrage atd). Avec, atil est également possible d'indiquer un travail de telle manière qu'au lieu d'être exécuté à un certain moment; le travail est simplement livré batchà ce moment-là et est d'abord exécuté lorsque la moyenne de charge chute (par exemple, il est exécuté dès que la moyenne de charge tombe en dessous de 1,5 quelque temps après 2h00 du matin).

Malheureusement, un travail par lots s'exécutera alors jusqu'à sa fin, il ne s'arrêtera pas si l'ordinateur n'est plus inactif.

+++

Si vous devez emprunter la voie de programmation (à laquelle elle ressemble à partir des autres réponses), je pense que j'essaierais de créer quelque chose de similaire au atdou aux cronddémons, qui surveillaient les utilisateurs connectés et / ou la charge moyenne. Ce démon pourrait alors exécuter des scripts / programmes à partir d'un certain répertoire, et les démarrer / continuer ou les arrêter (avec des signaux) selon les besoins.

Baard Kopperud
la source
Si vous avez fait cela et utilisé des .lockfichiers, vous pouvez facilement gérer les problèmes de synchronisation.
mikeserv
2

Ce fil a quelques solutions basées sur la détection de l'activité du clavier et de la souris. Je cours xprintidledepuis un travail cron qui démarre toutes les quelques minutes. Mais comme ils le soulignent xprintidlen'est pas entretenu, vous pouvez donc installer le module Perl et l'utiliser à la place:

$ cpanm X11::IdleTime
...
$ sleep 10; perl -MX11::IdleTime -le 'print GetIdleTime()'
9

J'utiliserais l'une ou l'autre solution en interrogeant Cron, dans un script qui se termine en haut si l'interface utilisateur n'a pas été suffisamment inactive. Bien sûr, le script aurait besoin d'un export DISPLAY=:0.0pour parler à X11.

N'oubliez pas que votre clavier et votre souris peuvent être inactifs lorsque vous regardez un film ou exécutez une tâche gourmande en CPU.

Métamorphique
la source
1

Je ne connais pas de moyen de le faire sans interroger une sorte de statistiques système, comme les autres réponses utilisent un économiseur d'écran ou une minuterie inactive bash, ou en cours d'exécution à partir de .bash_logout, mais voici une idée pour vérifier l'utilisation du processeur.

Cela impliquerait toujours l'interrogation toutes les n secondes, et si votre utilisation du processeur est inférieure à la quantité que vous choisissez, vous pouvez alors écrire ce que vous voulez exécuter. Cependant, tout ce que vous exécutez pourrait augmenter l'utilisation du processeur, mais vous pouvez utiliser nice sur votre "truc" pour ne pas le compter.

Voici un script de test utilisant top, mais vous pouvez utiliser mpstat à la place ou vérifier les moyennes de charge à la place?

while true
do
idle=$(top -bn2 | grep "Cpu(s)"|tail -n 1|sed "s/.*, *\([0-9.]*\)%* id.*/\1/")
echo "idle is $idle"
if [[ $idle > 90 ]]
then
    echo "idle above 90%"
    echo "Do stuff now"
else
    echo "idle below 90%"
    echo "Stop doing stuff now"
fi
sleep 1
done

C'est juste un script que j'ai jeté ensemble pour tester la lecture du ralenti par le haut. Vous pouvez analyser, /proc/statmais je pense que cela ne montre que les temps totaux, et vous auriez besoin de comparer les résultats sur un intervalle. Top a son propre problème pour moi (Linux Mint 16), lors de la première exécution, il ne semble jamais changer les cpustats, comme s'il devait attendre pour analyser / proc / stat lui-même, d'où le top -bn2mais en théorie top -bn1devrait fonctionner.

Xen2050
la source
Ugh ... vraiment? Interroger les statistiques du processeur?
Rolf
Par ailleurs, vous pouvez également interroger la wcommande qui affiche le temps d'inactivité de l'utilisateur. - Au fait, je ne juge pas, c'est juste que pour moi, je veux détecter le ralenti pour mettre la machine en veille, pour économiser de l'énergie, et l'interrogation va à l'encontre de cela.
Rolf
@Rolf Sonne assez bien ... puisque ce commentaire n'ajoute vraiment pas grand-chose, il devrait probablement être supprimé, oui? Quoi qu'il en soit, les autres réponses utilisent le temps d'inactivité de différentes manières, mais comment pouvez-vous détecter l'inactivité sans regarder / demander au système?
Xen2050