196 votes

Script Bash qui tue un processus enfant après un délai d'attente donné

J'ai un script bash qui lance un processus enfant qui se bloque (en fait, il se bloque de temps en temps et sans raison apparente (à code source fermé, donc il n'y a pas beaucoup que je peux faire à ce sujet). En conséquence, je voudrais être en mesure de lancer ce processus pour un laps de temps donné, et de le tuer s'il n'a pas de retour avec succès après un laps de temps donné.

Est-il simple et robuste de manière à réaliser que l'utilisation de bash?

P. S.: dites-moi si cette question est mieux adapté à serverfault ou superutilisateur.

298voto

Ignacio Vazquez-Abrams Points 312628

(Comme on le voit dans: BASH entrée de la FAQ #68: "Comment puis-je exécuter une commande, et de l'avortement (timeout) après N secondes?")

Si vous n'avez pas l'esprit de télécharger un truc utilisation timeout (sudo apt-get install timeout) et de l'utiliser comme:

timeout 10 ping www.goooooogle.com

Si vous ne voulez pas télécharger quelque chose à faire ce délai d'attente n'en interne:

( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec ping www.goooooogle.com )

Dans le cas que vous voulez faire d'un délai d'attente pour plus d'bash code, utiliser la deuxième option en tant que tel:

( cmdpid=$BASHPID; 
    (sleep 10; kill $cmdpid) \
   & while ! ping -w 1 www.goooooogle.com 
     do 
         echo crap; 
     done )

35voto

Dan Points 1322
 # Spawn a child process:
(dosmth) & pid=$!
# in the background, sleep for 10 secs then kill that process
(sleep 10 && kill -9 $pid) &
 

ou pour obtenir les codes de sortie également:

 # Spawn a child process:
(dosmth) & pid=$!
# in the background, sleep for 10 secs then kill that process
(sleep 10 && kill -9 $pid) & waiter=$!
# wait on our worker process and return the exitcode
exitcode=$(wait $pid && echo $?)
# kill the waiter subshell, if it still runs
kill -9 $waiter 2>/dev/null
# 0 if we killed the waiter, cause that means the process finished before the waiter
finished_gracefully=$?
 

13voto

DigitalRoss Points 80400
sleep 999&
t=$!
sleep 10
kill $t

1voto

kojiro Points 24374

En supposant que vous avez (ou pouvez facilement créer) un fichier pid pour suivre le pid de l'enfant, vous pouvez ensuite créer un script qui vérifie l'heure de modification du fichier pid et tue / respawns le processus selon les besoins. Ensuite, placez le script dans crontab pour qu'il s'exécute approximativement à la période souhaitée.

Faites-moi savoir si vous avez besoin de plus de détails. Si cela ne vous convient pas, qu’en est-il de Upstart?

1voto

Gavin Smith Points 1289

Une façon est d'exécuter le programme dans un shell interne est exécuté, et communiquer avec le shell interne est exécuté par l'intermédiaire d'un canal nommé avec l' read commande. De cette façon, vous pouvez vérifier le statut de sortie du processus en cours d'exécution et de communiquer ce retour dans le tuyau.

Voici un exemple de calendrier les yes commande au bout de 3 secondes. Il obtient le PID du processus à l'aide d' pgrep (éventuellement ne fonctionne que sur Linux). Il y a également un problème avec l'aide d'un tuyau dans un processus d'ouverture d'un tuyau pour la lecture de bloquer jusqu'à ce qu'il est également ouvert pour l'écriture, et vice versa. Pour empêcher l' read commande accroché, j'ai "calé" ouvrir le tuyau pour les lire avec un fond shell interne est exécuté. (Une autre façon d'éviter un gel pour ouvrir le canal de lecture-écriture, c'est à dire read -t 5 <>finished.pipe - cependant, qui peuvent également ne pas fonctionner, sauf avec Linux.)

rm -f finished.pipe
mkfifo finished.pipe

{ yes >/dev/null; echo finished >finished.pipe ; } &
SUBSHELL=$!

# Get command PID
while : ; do
    PID=$( pgrep -P $SUBSHELL yes )
    test "$PID" = "" || break
    sleep 1
done

# Open pipe for writing
{ exec 4>finished.pipe ; while : ; do sleep 1000; done } &  

read -t 3 FINISHED <finished.pipe

if [ "$FINISHED" = finished ] ; then
  echo 'Subprocess finished'
else
  echo 'Subprocess timed out'
  kill $PID
fi

rm finished.pipe

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X