2010-10-28 69 views
6

Je le script bash suivant:script Bash ne pas sortir immédiatement quand `exit` est appelé

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 0 
    fi 
done 

Pour une raison quelconque, il est fait l'écho launchd message, en attendant une pleine 5 secondes, et puis sortant.

Pourquoi est-ce que cela se produit et comment puis-je le faire sortir immédiatement après il echos launchd message?

Répondre

9

Étant donné que vous utilisez un canal, la boucle while est exécutée dans un sous-shell. Exécutez-le dans le shell principal à la place.

#!/bin/bash 

while ... 
do 
    ... 
done < <(tail ...) 
+0

Je reçois une erreur de syntaxe à la ligne ... – Chetan

+0

fait Ah, c'était parce que j'utilisais/bin/sh, moi stupide. – Chetan

+0

L'appel de bash comme sh désactive certaines fonctionnalités, y compris la substitution de processus. –

3

Comme indiqué par Ignacio, votre tail | while crée un sous-shell. Le retard est dû au fait que la ligne suivante doit être écrite dans le fichier journal avant que tout ne se ferme.

Vous pouvez ajouter cette ligne immédiatement avant votre commande exit si vous préférez ne pas utiliser la substitution de processus:

kill -SIGPIPE $$ 

Malheureusement, je ne sais pas de toute façon de contrôler le code de sortie en utilisant cette méthode. Ce sera 141 qui est 128 + 13 (le numéro de signal de SIGPIPE).

Si vous essayez de faire dépendre le démarrage d'un démon d'un autre démon, il y a probablement une meilleure façon de le faire.

Soit dit en passant, si vous écrivez vraiment un script Bash (que vous auriez à être utiliser <() substitution de processus), vous pouvez écrire votre if comme ceci: if [[ $line == *launchd* ]].

2

Vous pouvez également quitter le sous-shell avec un code de sortie témoin, puis tester la valeur de "$?" pour obtenir le même effet que vous recherchez:

tail -F -n0 /private/var/log/system.log | while read line 
do 
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then 
     echo 'launchd message' 
     exit 10 
    fi 
done 
if [ $? -eq 10 ]; then exit 0; fi