Evite los EOF automáticos en una tubería con nombre y envíe un EOF cuando lo desee

12

Tengo un programa que sale automáticamente al leer un EOF en una secuencia dada (en el siguiente caso, stdin).
Ahora quiero hacer un script de shell, que crea una tubería con nombre y conectar el stdin del programa. Luego, el script escribe en la tubería varias veces usando echoy cat(y otras herramientas que generan automáticamente un EOF cuando salen). El problema al que me enfrento es que, cuando echose realiza el primero , envía un EOF a la tubería y hace que el programa salga. Si uso algo así tail -f, no puedo enviar un EOF cuando tengo la intención de salir del programa. Estoy investigando una solución equilibrada pero fue en vano.
Ya he encontrado cómo prevenir EOF y cómo enviar un EOF manualmente, pero no puedo combinarlos. ¿Hay alguna pista?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg
iBug
fuente

Respuestas:

13

Como otros han indicado, el lector de una tubería recibe EOF una vez que no quedan escritores. Entonces, la solución es asegurarse de que siempre haya un escritor abierto. Ese escritor no tiene que enviar nada, solo manténgalo abierto.

Como está utilizando un script de shell, la solución más simple es decirle al shell que abra la tubería para escribir. Y luego ciérralo cuando hayas terminado.

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

Tenga en cuenta que si omite la última línea, el descriptor de archivo 3 se cerrará automáticamente (y, por lo tanto, el lector recibirá EOF) cuando salga el script. Además de la conveniencia, esto también proporciona una especie de seguridad si el script terminara de alguna manera antes de tiempo.

Patricio
fuente
2
esta exec 3>Pcausa aguanta, ¿por qué?
Wang
@ Wang No debería. Si lo hace, entonces probablemente no esté haciendo lo mismo que el código POC en la pregunta. La única razón por la que puedo pensar que se bloquearía es si estás haciendo algo así exec 2>P, y tienes activado el modo de rastreo ( set -x), en el que bash va a escribir en la tubería, pero no hay lector, por lo que bloquea la espera algo para leer.
Patrick
1
@Wang @Patrick De hecho, también se exec 3>Pcuelga en mi máquina. Esto se debe a que no hay proceso de lectura P. Por lo tanto, la solución fue intercambiar líneas exec 3>Py program < P &(agregar el ampersand para que el programa se ejecute en segundo plano).
macieksk
2

Una tubería recibe EOF cuando el último escritor se va. Para evitar esto, asegúrese de que siempre haya un escritor (un proceso que tiene la tubería abierta para escribir, pero en realidad no escribe nada). Para enviar el EOF, haga que ese escritor de reserva se vaya.

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}
Gilles 'SO- deja de ser malvado'
fuente
0

No hay forma de que el programa distinga entre un EOF que significa "es hora de dejar de fumar" y un EOF que significa "un escritor ha terminado, pero puede haber más información de alguien más".

Si tiene la capacidad de modificar el comportamiento de su programa, haga la lectura en un bucle infinito (una iteración dura hasta EOF) y envíele una cadena de comando específica que significa "hora de salir". Enviar esa cadena sería la tarea del send_eofcomando en su pregunta.

Otra opción:

( echo some stuff; cat more_stuff.txt ) >P

o

{ echo some stuff; cat more_stuff.txt; } >P
Kusalananda
fuente