Mardi 31 janvier 2006 |
#!/bin/bash set -o noclobber NAME=tictac LOCK=/tmp/$NAME.lock error () { echo "$1" 1>&2 exit 1 } once () { if [ -f "$LOCK" ] then xterm -g 50x2 -e bash -c \ "echo -n 'Daemon '$NAME' running pid='; cat $LOCK; sleep 5" fi } launch () { while true do if sleep 60 then once else exit 1 fi done } usage () { error "Usage: $0 [ -launch | -kill ] " } if [ $# != 1 ] then usage fi case "$1" in -launch) if [ -f "$LOCK" ] then error "Daemon already running (not launched)!" else echo -n '' > "$LOCK" || error "Cannot write $LOCK" echo -n "Launching $NAME... " launch & echo $! >> "$LOCK" echo "done (pid=$!)" fi ;; -kill) if [ -f "$LOCK" ] then PID=$(cat "$LOCK") case "$PID" in [1-9][0-9]*) ;; *) error "$LOCK does not contain a pid";; esac echo -n "Killing daemon $PID... " if kill -KILL "$PID" then echo "Done" rm "$LOCK" else echo "Process $PID not running (cleaning $LOCK)!" 1>&2 rm "$LOCK" exit 1 fi else error "Daemon not running" fi ;; *) usage esac |
bash, dans lequel il est possible de rechercher un mot
avec la touche / .name et lock correspondant aux
constantes NAME et LOCK du script shell précédent, puis écrire
une fonction error équivalente à la fonction error du script
(1>&2 indique que l'affichage doit être effectué sur la sortie d'erreur).
mon_execvp telle que mon_execvp cmd argv
exécute la
commande cmd (Unix.excevp) dans un processus différent (Unix.fork) avec les arguments présents dans le tableau de chaînes
de caractères argv. La fonction attend la fin de la
commande cmd (Unix.waitpid) avant de se terminer.
La fonction retourne la valeur de retour
de la commande ou lève une exception. Attention, l'attente peut être intérompue par l'arrivée d'un signal
(levée de l'exception Unix_error(EINTR,_,_), il faut alors relancer
l'attente.
mon_execvp ne prend pas en compte tous les cas où des
signaux peuvent arriver. Modifier votre fonction pour que le signal SIGCHLD
soit bloqué (Unix.sigprocmask) et les signaux SIGINT et SIGQUIT soient
ignorés (Sys.signal avec Sys.Signal_ignore). Pensez également à remettre
en place le comportement initial des signaux avant la fin de la commande
quelle que soit la façon dont elle se termine.
mon_execvp, écrire une fonction
mon_system qui exécute une commande passée en argument sous la
forme d'une chaîne de caractères en passant cette dernière en argument
de la commande /bin/sh -c.
succeed telle que succeed f x appelle f x et
retourne true si f x se termine normalement, false si l'appel
a levé une exception de type Unix_error (l'exception est alors
ignorée) et propage les exceptions différentes de Unix_error.
succeed précédente, écrire une fonction
file_exists (correspondant à test -f) qui retourne true si le
fichier dont le nom est passé en argument existe. Pour cela, on pourra
utiliser la fonction Unix.access. mon_execvp et file_exists écrire une
fonction once équivalente à celle du shell-script précédent.
mon_excevp une fonction launch qui a le même
comportement que celle du shell-script.
background telle que background lock f x
appelle f x après avoir effectué un fork, et qui utilise un
fichier de nom lock pour s'assurer qu'il n'y ait qu'une exécution de
f x à la fois. Pour cela, on ouvrira le fichier avec les attributs
O_EXCL et O_CREAT. Le fichier lock devra contenir le numéro de
processus exécutant f x.
read_pid_from_file qui retourne le numéro du
processus stocké dans le fichier dont le nom est passé en argument. On
pourra utiliser la fonction input_line de Ocaml.
kill_daemon telle que kill_daemon lock termine
le processus dont le numéro est présent dans le fichier de nom lock.
Comme dans le shell-script on fera attention à traiter tous les cas
d'erreurs possibles.
kill
a échoué parce que l'on n'avait pas les droits nécessaires pour arrêter le
processus. Modifier la fonction kill_daemon en conséquence (il est
plus compliqué de le faire avec shell-script).
This document was translated from LATEX by HEVEA and HACHA.