
Tengo un programa que sale automáticamente al leer un EOF en una secuencia determinada (en el siguiente caso, stdin).
Ahora quiero crear un script de shell, que cree una tubería con nombre y le conecte la entrada estándar del programa. Luego el script escribe en la tubería.varias vecesusando echo
y cat
(y otras herramientas que generan automáticamente un EOF cuando salen). El problema al que me enfrento es que, cuando echo
finaliza 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 pretendo salir del programa. Estoy investigando una solución equilibrada pero fue en vano.
Ya descubrí cómo prevenir los 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
Respuesta1
Como han indicado otros, 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 que lo mantenga abierto. Ese escritor no tiene que enviar nada, simplemente mantenerlo abierto.
Dado que está utilizando un script de shell, la solución más sencilla es decirle al shell que abra la tubería para escribir. Y luego ciérrelo cuando haya 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. Aparte de la conveniencia, esto también proporciona una especie de seguridad si el guión terminara de alguna manera antes de tiempo.
Respuesta2
Una tubería recibe EOF cuando el último escritor desaparece. 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 desaparezca el escritor de reserva.
mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
kill $P_writer_pid
}
Respuesta3
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 aportaciones de otra persona".
Si tiene la capacidad de modificar el comportamiento de su programa, realice la lectura en un bucle infinito (una iteración dura hasta el EOF) y envíele una cadena de comando específica que signifique "hora de salir". Enviar esa cadena sería tarea del send_eof
comando en su pregunta.
Otra opción:
( echo some stuff; cat more_stuff.txt ) >P
o
{ echo some stuff; cat more_stuff.txt; } >P