¿Cuál es la diferencia entre esos cuatro comandos?

8

Mi objetivo es crear un servidor de eco simple usando ncy uno único fifo. No estoy buscando la mejor manera de hacerlo, simplemente estoy tratando de entender la semántica de los siguientes comandos (cuándo ocurre la bifurcación, por qué, qué cambia, por qué los comandos se comportan de manera diferente ...).

Estoy usando Bash, así que no estoy seguro de si todos los comandos funcionará con un POSIX sho zsh, ksh, ...

Aquí están los cuatro comandos que menciono en el título (suponiendo que ya lo hice mkfifo fifo):

cat fifo | nc -l localhost 8888 > fifo
exec 3<> fifo && nc -l localhost 8888 <&3 >&3 && exec 3>&-
nc -l localhost 8888 <(cat fifo) > fifo
nc -l localhost 8888 < fifo > fifo

Ahora esperaría que los 4 comandos hagan lo mismo, al menos los dos últimos hagan lo mismo.

  1. El primer comando se comporta como se esperaba, un servidor de eco simple que se apaga cuando el cliente cierra la conexión.
  2. Se comporta como 1.
  3. Puedo conectarme al servidor, enviar datos, pero nunca recibo nada. Cuando cierro la conexión del cliente, el servidor se apaga.
  4. No se puede conectar al servidor, el servidor escucha para siempre.
foo
fuente

Respuestas:

8

La clave aquí es que abrir un FIFO es una operación de bloqueo. Los openúnicos retornos una vez que ambos extremos están conectados, es decir, una vez que el fifo está abierto para leer y escribir.

hombre fifo (7)

Normally, opening the FIFO blocks until the other end is opened also.

En el primer caso, el shell se bifurca para ejecutar la canalización, por lo que abrir el fifo para leer ( cat fifo) y abrir el fifo para escribir ( > fifo) suceden en procesos separados, por lo que suceden de forma independiente.

En el segundo caso, el abierto para leer y el abierto para escribir ( 3<>fifo) ocurren en un solo paso.

En el tercer caso, se <(cat fifo)expande a un nombre de archivo, por ejemplo /dev/fd/42. Entonces es como si estuvieras corriendo nc -l localhost 8888 /dev/fd/42 > fifo. Necesita un extra <para que sea equivalente, por ejemplo nc -l localhost 8888 < <(cat fifo) > fifo.

En el cuarto caso, el shell está tratando de abrir el fifo para lectura ( < fifo) y abrirlo para escribir ( > fifo) como parte del mismo proceso. El caparazón los hace uno a la vez, de izquierda a derecha. Por lo tanto, intenta abrirse fifopara leer, y se bloquea para siempre, esperando que se abra algo fifopara escribir. Creo que en este caso encontrará que ncnunca comenzó, y que el puerto nunca se abrió para escuchar.

Mikel
fuente
Oh, sí, error tonto en el n. ° 3, pero al final el resultado sigue siendo el mismo. Solo otra pregunta que es más curiosidad que cualquier otra cosa, ¿es exec la única forma de abrir el fifo para r / w en un solo paso? ¿Y hay alguna otra manera de forzar la concha a bifurcar como en el n. ° 1? ¡Gracias!
foo
nc ... <>fifoDebería ser suficiente. gnu.org/software/bash/manual/html_node/Redirections.html
Mikel
1
El shell se bifurcará cada vez que use una tubería, un subshell o una sustitución de proceso.
Mikel
2
Corrección, necesitará nc ... <>fifo >&0, ya que se <>fifoabre fifopara leer y escribir en fd 0, y queremos que la salida vaya allí también.
Mikel