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.