2011-07-26 13 views
7

ls:Canalización con nombre que se cierra prematuramente en el script?

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 

que tienen dos terminales abiertos, uno corriendo write.sh y otro corriendo read.sh. Cuando comienzo write.sh primero, se cuelga (como debería). Luego voy a la otra terminal y comienzo read.sh y se imprime "blah" una tonelada de veces, luego se detiene mi write.sh. ¿Por qué se detiene mi script de escritura? Esta es una pequeña prueba que estoy haciendo para tratar de entender las tuberías un poco mejor porque voy a enviar todos mis registros a una tubería para poder analizarlos antes de escribirlos en un archivo.

¿Qué me falta aquí?

Respuesta

5

Aquí hay una condición de carrera. Cualquiera que sea el script que ejecute su comando de bucle interno primero (cat y echo respectivamente) bloqueará y esperará a que el otro script ejecute su comando de bucle interno. Sin embargo, una vez que las secuencias de comandos se sincronizan, si el gato llama a close() en la tubería antes de que echo ejecute su escritura(), el eco se enviará un SIGPIPE y su secuencia de comandos se cerrará. No puede escribir en una tubería que ha sido cerrada por su lector.

Si cambia su lector a tail -f en lugar de a while loop con cat, el lector se mantiene activo en lugar de abrir y cerrar la fifo a perpetuidad y no debe obtener un SIGPIPE.

referencia: man fifo

+0

perfecto! Gracias. – n0pe

5

Para conseguir el bloqueo no el comportamiento de tuberías también se puede abrir por primera vez un descriptor de archivo de lectura y un descriptor de archivo de escritura en 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 

Consulte también: How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?

Cuestiones relacionadas