2011-07-26 13 views
7

ls:O nazwie Przedwczesne zamknięcie potoku w skrypcie?

prwx------ 1 root root 0 fifo 

write.sh:

#! /bin/bash 
while true; 
do 
    echo "blah" > fifo 
done 

read.sh:

#! /bin/bash 
while true; 
do 
    cat fifo 
done 

mam dwa terminale otwarty, jeden działa write.sh a drugi działa read.sh. Kiedy najpierw uruchamiam write.sh, zawiesza się (tak jak powinien). Następnie przechodzę do innego terminala i uruchamiam read.sh i wypuszczam na nim "blah" tonę razy, po czym zatrzymuje się mój write.sh. Dlaczego mój skrypt zapisu się zatrzymuje? To jest mały test, który próbuję zrozumieć i zrozumieć trochę lepiej, ponieważ zamierzam wysyłać wszystkie logi do potoku, dzięki czemu mogę je przeanalizować przed zapisaniem ich do pliku.

Czego mi tu brakuje?

Odpowiedz

5

Istnieje tutaj stan wyścigu. Niezależnie od tego, który skrypt najpierw wykona komendę wewnętrznej pętli (odpowiednio cat i echo), zablokuje i zaczeka, aż inny skrypt wykona polecenie z wewnętrznej pętli. Jednak po synchronizacji skryptów, jeśli kot wywoła metodę close() na rurze, zanim echo wykona polecenie write(), echo zostanie wysłane SIGPIPE i skrypt zakończy działanie. Nie możesz pisać do rury, która została zamknięta przez czytnik.

Jeśli zmienisz czytnik na ogon -f zamiast na pętlę z kotem, czytnik pozostanie przy życiu, a nie otworzy i zamknie fifo bezterminowo i nie powinieneś otrzymywać SIGPIPE.

referencyjny: man fifo

+0

Perfect! Dzięki. – n0pe

5

Aby uzyskać non-blocking zachowanie rurociągów można także pierwszy otwarty deskryptor pliku do odczytu, a następnie deskryptor pisać na fifo.

# cf. https://stackoverflow.com/questions/2776994/tee-a-pipe-asynchronously 
(
rm -f fifo 
mkfifo fifo 
exec 3<fifo # open fifo for reading 
trap "exit" 1 2 3 15 
exec cat fifo | nl 
) & 
bpid=$! 

(
exec 3>fifo # open fifo for writing 
trap "exit" 1 2 3 15 
while true; 
do 
    echo "blah" > fifo 
done 
) 
#kill -TERM $bpid 

Zobacz także: How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?