2014-09-17 1 views
8

J'ai deux scripts bash. Un script écrit dans un fifo. Le deuxième a lu du fifo, mais APRÈS le premier fin à écrire.Écrire et lire à partir d'un fifo à partir de deux scripts différents

Mais quelque chose ne fonctionne pas. Je ne comprends pas où est le problème. Voici le code.

Le premier script est (l'auteur):

#!/bin/bash 

fifo_name="myfifo"; 

# Se non esiste, crea la fifo; 
[ -p $fifo_name ] || mkfifo $fifo_name; 

exec 3<> $fifo_name; 

echo "foo" > $fifo_name; 
echo "bar" > $fifo_name; 

Le second script est (le lecteur):

#!/bin/bash 

fifo_name="myfifo"; 

while true 
do 
    if read line <$fifo_name; then 
     # if [[ "$line" == 'ar' ]]; then 
     # break 
     #fi 
     echo $line 
    fi 
done 

Quelqu'un peut-il me aider s'il vous plaît? Merci

+1

Qu'est-ce que vous voulez dire par "Quelque chose ne fonctionne pas"? – choroba

+0

Aucun script ne me donne d'erreur. Mais quand je cours le deuxième script rien n'est imprimé sur l'écran. Donc, je ne comprends pas si je me trompe quand j'écris dans le fifo ou quand je lis du fifo – Ciccio

Répondre

6

Remettez en place le second script avec:

#!/bin/bash  
fifo_name="myfifo" 
while true 
do 
    if read line; then 
     echo $line 
    fi 
done <"$fifo_name" 

Cela ouvre la fifo une seule fois et lit toutes les lignes de celui-ci.

+0

Ne fonctionne pas pour moi :(Quand je lance le deuxième script rien ne se passe et aussi le script ne se termine pas :(Je dois appuyer CTRL + C – Ciccio

+0

@Ciccio Oui, le script ne se termine pas car il attend que quelque chose soit lu par le fifo, alors qu'il attend, exécutez l'autre script qui écrit sur le fifo. – John1024

+0

@Ciccio En outre, le premier script ne se termine pas avant que certains processus aient été lus depuis le fifo. Lorsque le deuxième script a fini de lire ce que le premier script a écrit, le premier script se termine. Le deuxième script, en raison de la boucle while while, continue d'attendre plus de saisie. – John1024

2

Le problème avec votre installation est que vous avez une création fifo dans le mauvais script si vous souhaitez contrôler l'accès fifo à l'heure lorsque le lecteur est en cours d'exécution. Pour corriger le problème, vous aurez besoin de faire quelque chose comme ceci:

lecteur : fifo_read.sh

#!/bin/bash 

fifo_name="/tmp/myfifo"       # fifo name 

trap "rm -f $fifo_name" EXIT     # set trap to rm fifo_name at exit 

[ -p "$fifo_name" ] || mkfifo "$fifo_name"  # if fifo not found, create 

exec 3< $fifo_name        # redirect fifo_name to fd 3 
               # (not required, but makes read clearer) 
while :; do 
    if read -r -u 3 line; then     # read line from fifo_name 
     if [ "$line" = 'quit' ]; then   # if line is quit, quit 
      printf "%s: 'quit' command received\n" "$fifo_name" 
      break 
     fi 
     printf "%s: %s\n" "$fifo_name" "$line" # print line read 
    fi 
done 

exec 3<&-          # reset fd 3 redirection 

exit 0 

écrivain: fifo_write.sh

#!/bin/bash 

fifo_name="/tmp/myfifo" 

# Se non esiste, exit :); 
[ -p "$fifo_name" ] || { 
    printf "\n Error fifo '%s' not found.\n\n" "$fifo_name" 
    exit 1 
} 

[ -n "$1" ] && 
    printf "%s\n" "$1" > "$fifo_name" || 
    printf "pid: '%s' writing to fifo\n" "$$" > "$fifo_name" 

exit 0 

opération: (démarrer le lecteur dans le 1er terminal)

$ ./fifo_read.sh       # you can background with & at end 

(auteur de lancement en second terminal)

$ ./fifo_write.sh "message from writer" # second terminal 
$ ./fifo_write.sh 
$ ./fifo_write.sh quit 

de sortie en 1ère borne:

$ ./fifo_read.sh 
/tmp/myfifo: message from writer 
/tmp/myfifo: pid: '28698' writing to fifo 
/tmp/myfifo: 'quit' command received 
+0

+1 Vous abordez le problème en cours, mais comme une note: Ne serait pas 'read -r line <$ fifo_name' être meilleur? Comme c'est maintenant le script * lecteur * va entrer une boucle intensive CPU après le premier message. La même chose vaut pour l'approche [donnée par John1024] (http://stackoverflow.com/a/25901141/1968548). – Runium

+0

Merci. Comme indiqué dans le commentaire, la redirection persistante vers fd3 n'est pas nécessaire, le but était simplement de garder la logique du script propre et de faire en sorte que le fifo soit redirigé et utilisé pour alimenter read. (cela a également donné l'opportunité de montrer la lecture d'un descripteur de fichier personnalisé - ce qui est nécessaire si vous lisez plusieurs fds dans une seule boucle (par exemple fd3 & stdin) .Je ne vois pas pourquoi votre approche ne fonctionnerait pas également désinvolte. –

0

Le script suivant devrait faire le travail:

#!/bin/bash 

FIFO="/tmp/fifo" 

if [ ! -e "$FIFO" ]; then 
     mkfifo "$FIFO" 
fi 

for script in "[email protected]"; do 
     echo $script > $FIFO & 
done 

while read script; do 
     /bin/bash -c $script 
done < $FIFO 

Compte tenu deux scripts a.sh et b.sh où les deux scripts passent "a" et "b" à stdout, respectivement, on obtient le résultat suivant (étant donné que le script ci-dessus est appelé test.sh):

./test.sh /tmp/a.sh /tmp/b.sh 
a 
b 

Best, Julian

Questions connexes