2014-09-17 14 views
8

Ho due script bash. Uno script scrive in un fifo. Il secondo letto dalla fifo, ma DOPO il primo capo da scrivere.Scrivere e leggere da un fifo da due diversi script

Ma qualcosa non funziona. Non capisco dove sia il problema Ecco il codice.

Il primo script è (lo scrittore):

#!/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; 

Il secondo script è (il lettore):

#!/bin/bash 

fifo_name="myfifo"; 

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

Qualcuno mi può aiutare per favore? Grazie

+1

Cosa fare intendi per "Qualcosa non funziona"? – choroba

+0

Nessun script mi ​​dà alcun errore. Ma quando eseguo il secondo script non viene stampato nulla sullo schermo. Quindi non capisco se sbaglio quando scrivo nella fifo o quando leggo dal fifo – Ciccio

risposta

6

sostituire il secondo script con:

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

Questo apre la FIFO solo una volta e legge ogni linea da esso.

+0

Non mi funziona :(Quando eseguo il secondo script non succede nulla e anche lo script non termina :(Devo premere CTRL + C – Ciccio

+0

@Ciccio Sì, lo script non termina perché è in attesa della lettura da parte di fifo. Mentre è in attesa, esegui l'altro script che scrive sulla fifo. – John1024

+0

@Ciccio Inoltre, il primo script non termina fino a quando alcuni processi non hanno letto il fifo. Quando il secondo script termina di leggere ciò che il primo script ha scritto, il primo script termina. Il secondo script, a causa del ciclo 'while true', continua ad attendere ulteriori input. – John1024

2

Il problema con la configurazione è che si ha una creazione di 50 in uno script errato se si desidera controllare l'accesso al tempo quando il lettore è in esecuzione. Al fine di risolvere il problema è necessario fare qualcosa di simile:

lettore: 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 

scrittore: 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 

funzionamento: (avviare il lettore nel 1 ° terminale)

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

(scrittore lancio nel secondo terminale)

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

uscita nel primo terminale:

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

+1 Hai risolto il problema, ma come nota: non dovresti leggere -r line <$ fifo_name' be meglio? Dato che ora lo script * reader * sta per entrare in un ciclo ad alta intensità di CPU dopo il primo messaggio. Lo stesso vale per l'approccio [dato da John1024] (http://stackoverflow.com/a/25901141/1968548). – Runium

+0

Grazie. Come notato nel commento, il reindirizzamento persistente a fd3 non è necessario, lo scopo era solo quello di mantenere la logica di script pulita e rendere evidente che la fifo veniva reindirizzata e utilizzata per alimentare la lettura. (ha anche dato l'opportunità di mostrare la lettura da un descrittore di file personalizzato - che è necessario se si legge da più fds in un singolo ciclo (es. fd3 e stdin). Non vedo alcun motivo per cui il tuo approccio non funzionerebbe allo stesso modo fuori mano, dagli un colpo. –

0

Il seguente script dovrebbe fare il lavoro:

#!/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 

Dato due script a.sh e b.sh dove entrambi gli script passano "a" e "b" allo stdout rispettivamente, si otterrà il seguente risultato (dato che lo script di cui sopra si chiama test.sh):

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

migliore, Julian

Problemi correlati