J'ai écrit l'utilitaire idlexec de façon à pouvoir arrêter temporairement et automatiquement des processus de calcul tournant sur nos machines de bureau, lorsque quelqu'un utilise une machine. En effet, certaines machines font énormément de bruit lorsque leur processeur est actif. Cet utilitaire est capable de prendre en compte le fait qu'il peut y avoir plusieurs machines par bureau.
Il s'agit d'un script Perl qui ne dépend que du module Perl POSIX.
D'abord, vous devez définir une variable d'environnement IDLEXECDIR pointant sur un répertoire qui devra contenir les données pour idlexec. Ce répertoire doit être accessible à toutes les machines de la pièce; il est typiquement sous NFS, sauf si une seule machine est concernée. Dans ce répertoire, vous devez créer un fichier hosts contenant les machines qui sont bruyantes lorsqu'elles sont chargées: un nom de machine par ligne. Pour chaque pièce, vous devez également créer un fichier vide (le nom du fichier est typiquement le nom de la pièce), par exemple avec la commande touch, et avec les droits d'écriture pour le groupe d'utilisateurs pouvant utiliser la machine (pour des calculs); en fait, le contenu de ces fichiers n'est pas important: seule leur date de modification (mtime) sera utilisée.
La commande idlexec s'utilise de trois manières:
Avant toute autre utilisation, il faut faire un idlexec -g pièce, où pièce est le nom du fichier associé à la pièce (cf ci-dessus). Cela met en place un lien symbolique /tmp/.idlegroup pointant sur le fichier associé à la pièce. Cette étape doit être faite sur toutes les machines de la pièce (pas seulement celles qui sont bruyantes), et à chaque fois que ce lien symbolique disparaît (par exemple, après un redémarrage de la machine, si le répertoire /tmp est nettoyé par le système).
Un processus idlexec sans argument doit tourner en arrière-plan sur chaque machine, au moins quand quelqu'un utilise physiquement la machine; par exemple, il peut être lancé au démarrage (boot) de la machine (éventuellement avec un sudo) ou par un fichier d'initialisation du shell de l'utilisateur. Si le processus tourne déjà, une erreur est simplement renvoyée; elle peut être ignorée. Ce processus va mettre à jour régulièrement la date de modification du fichier pièce (via le lien symbolique /tmp/.idlegroup) lorsque le clavier de la machine est utilisé (il serait bien de prendre en compte la souris également, mais je ne sais pas faire).
Pour lancer un processus de calcul qui doit être contrôlé par idlexec, utilisez simplement la commande idlexec avec comme arguments la valeur de nice, suivie de la commande de calcul avec ses propres arguments. En gros, idlexec remplace plus ou moins la commande nice (il accepte une valeur positive ou négative, mais prend la valeur absolue, comme ça vous n'aurez pas à vous demander quelle syntaxe utiliser).
Le processus idlexec va regarder l'activité de la machine via le fichier pièce, avec un polling de 10 secondes. Si le clavier a été utilisé dans les 10 minutes, un signal STOP sera envoyé au process group de la commande. Un signal CONT sera envoyé après 10 minutes de non utilisation du clavier. Note: ces temps sont configurables avec des variables d'environnement (pour de plus amples informations, voir le source d'idlexec).
L'option -n peut être donnée comme premier argument afin de rediriger les trois flux standard sur /dev/null. Cette option peut être utile si la commande est lancée via ssh et que le processus ne fait pas lui-même les redirections nécessaires pour se détacher du terminal; sinon la commande ssh va être bloquée jusqu'à ce que le processus se termine.
Pour lancer la commande, idlexec
fait d'abord un fork
, puis dans le fils: un
nice
, un setsid
et un exec
de la commande. Si la commande
lance d'autres processus, alors les signaux seront envoyés à tous ces
processus, et pas seulement au père, à condition que ceux-ci ne fassent
pas un setsid
, évidemment.
Le script idlexec trappe les
signaux INT (envoyé en temps
normal suite à un Ctrl+C)
et TERM, et les propage au
process group du fils. Cela permet notamment
d'avoir le comportement normal d'un
Ctrl+C, malgré
le setsid
effectué dans le processus
fils.
Lorsque le processus fils (commande de calcul) se termine (normalement, par un crash, etc.), l'état de retour est récupéré par idlexec, et le code de retour de idlexec est celui du processus fils. Si le processus fils a été tué par un signal, alors idlexec écrit une ligne du style:
Process pid killed by signal number
sur le flux d'erreur standard; cette ligne n'est obtenue que si l'option -n n'a pas été utilisée (car cette option redirige les trois flux standard sur /dev/null).