Dos ventanas, mismo usuario, con mensajes de bash. En la ventana-1 escriba:
$ mkfifo f; exec <f
Entonces bash ahora está intentando leer desde el descriptor de archivo 0, que se asigna a la canalización con nombre f. En la ventana-2, escriba:
$ echo ls > f
Ahora la ventana-1 imprime un ls y luego el caparazón muere. ¿Por qué?
Siguiente experimento: abra la ventana-1 nuevamente con exec <f. En la ventana-2, escriba:
$ exec 3>f
$ echo ls >&3
Después de la primera línea anterior, la ventana 1 se activa e imprime un mensaje. ¿Por qué? Después de la segunda línea anterior, la ventana-1 imprime la lssalida y el shell permanece vivo. ¿Por qué? De hecho, ahora en window-2, echo ls > fno cierra el shell de window-1.
¡La respuesta debe tener que ver con la existencia del descriptor de archivo 3 de la ventana-2 que hace referencia a la tubería con nombre?
fuente

exec <f,bashno está tratando de leer a partirf, primero se intenta abrir la misma. Elopen()no regresará hasta que haya algún proceso de hacer otro abierto en el modo de escritura en el tubo (momento en el que el tubo se crea una instancia, y la cáscara leerá de entrada de ella).exec 3>fse ejecuta, el primer shell emite un aviso. (Punto menor, ¿quiso decir "en modo de escritura " en su comentario?)Respuestas:
Tiene que ver con el cierre del descriptor de archivo.
En su primer ejemplo,
echoescribe en su flujo de salida estándar que el shell abre para conectarlof, y cuando termina, su descriptor se cierra (por el shell). En el extremo receptor, el shell, que lee la entrada de su flujo de entrada estándar (conectado af) leels, se ejecutalsy luego termina debido a la condición de fin de archivo en su entrada estándar.La condición de fin de archivo se produce porque todos los escritores de la canalización con nombre (solo uno en este ejemplo) han cerrado su final de la canalización.
En su segundo ejemplo,
exec 3>fabre el descriptor de archivo 3 para escribirf, luegoechoescribelsen él. Es el shell que ahora tiene abierto el descriptor de archivo, no elechocomando. El descriptor permanece abierto hasta que lo hagaexec 3>&-. En el extremo receptor, el shell, que lee la entrada de su flujo de entrada estándar (conectado af) leels, se ejecutalsy luego espera más entrada (ya que el flujo aún está abierto).El flujo permanece abierto porque todos los escritores (el shell, la vía
exec 3>fyecho) no han cerrado su extremo de la tubería (exec 3>ftodavía está en vigor).He escrito sobre lo
echoanterior como si fuera un comando externo. Lo más probable es que esté integrado en el caparazón. Sin embargo, el efecto es el mismo.fuente
No hay mucho: cuando no hay escritores en la tubería, parece cerrado para los lectores, es decir, devuelve EOF cuando se lee y se bloquea cuando se abre.
Desde la página de manual de Linux (
pipe(7)pero vea tambiénfifo(7)):Cerrar el final de la escritura es lo que sucede implícitamente al final de la
echo ls >f, y como usted dice, en el otro caso, el descriptor de archivo se mantiene abierto.fuente
Después de leer las dos respuestas de @Kusalananda y @ikkachu, creo que entiendo. En la ventana 1, el shell está esperando que algo abra el extremo de escritura de la tubería y luego lo cierre. Una vez que se abre el final de la escritura, el shell en la ventana-1 imprime un mensaje. Una vez que se cierra el final de escritura, el shell obtiene EOF y muere.
Por el lado de la ventana-2 tenemos las dos situaciones descritas en mi pregunta: en la primera situación con
echo ls > f, no hay descriptor de archivo 3, por lo que hemosechodesove, y sustdinystdouttener este aspecto:Luego
echotermina y el shell cierra ambos descriptores. Dado que el descriptor de archivo 1 está cerrado y las referenciasf, el final de escritura defestá cerrado y eso hace que un EOF a window-1.En la segunda situación, corremos
exec 3>fen nuestro shell, haciendo que el shell tome este entorno:Ahora ejecutamos
echo ls >& 3y el shell asigna descriptores de archivo de laechosiguiente manera:Luego, el shell cierra los tres descriptores anteriores, incluidos
f, perofaún tiene una referencia desde el propio shell. Esta es la diferencia importante. Cerrar el descriptor 3 conexec 3>&-cerraría la última referencia abierta y causaría un EOF a la ventana-1, como señaló @Kusalananda.fuente