Leer stdout/stderr desde el subshell al padre

Leer stdout/stderr desde el subshell al padre

En un script de shell, quiero escribir en la entrada estándar de un proceso externo X usando una canalización con nombre, y quiero enviar la salida estándar/stderr desde otra canalización con nombre a la terminal actual.

El proceso externo X recibe stdin a través de PIPEIN y envía su stdout/stderr a PIPEOUT.

tail -f $(tail -F PIPEOUT) &  # (1) this is completely wrong, need help here

for i; do
    echo "${i}" > PIPEIN  # send stdin to X
done

echo "[stdin end]" > PIPEIN  # signal that we are done writing (there might be a better way lol)

Entonces, en el script anterior, ya iniciamos el proceso X, ha estado ejecutándose durante algún tiempo. Pero ahora, cuando ejecutamos el script anterior, queremos enviarle a X alguna entrada estándar y queremos leer la salida estándar del proceso X, usando PIPEOUT.

Lo que estoy tratando de hacer arriba es configurar una lectura en PIPEOUT antes de enviar stdin a X, para asegurarme de capturar toda la salida estándar/stderr de X. El problema es que no sé cómo ejecutar algún proceso en segundo plano. (cola o gato para leer desde PIPEOUT) y enviar ese stdio al terminal actual.

¿Alguien sabe de qué estoy hablando? Si no me equivoco, solo necesito arreglar la línea etiquetada (1) y de alguna manera configurar una lectura en segundo plano que pueda leer desde PIPEOUT y enviar ese stdio al terminal/tty actual de alguna manera.

Respuesta1

No tengo claro lo que pretendías tail -f $(tail -F PIPEOUT) &hacer. Es tail -fel archivo quees el resultado de tail -F, que convencionalmente nunca termina. Supongo que desea generar todo lo que pasa por la tubería, sin importar el tiempo que lleve.

El problema con just tail -fes que tiene que encontrar el final del archivo antes de generar algo, lo que nunca sucede con la tubería. Puededar tailun punto de partida explícito en su lugar con-n +x, eligiendo la línea para comenzar (desde el principio, indexada en 1). tail -n 1 -f foomostrará todo lo que puede obtener foo.

tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
    echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN

Sin embargo, tenga en cuenta que esto echo > foocerrará foo después de escribir la línea; el comando en el otro extremo deberá estar dispuesto a lidiar con eso. Si este ejemplo es artificial y la información real proviene de otro lugar, puede ignorarlo.


Tenga en cuenta también queel tailproceso nunca terminará— sigue esperando que algo más pueda salir por la tubería. Tendrás que eliminarlo explícitamente tú mismo, tal vez con el control de trabajo de tu shell. Si hay algún patrón en el resultado que indique que se realizó, es posible que encuentreretail("cola con expresiones regulares")útil: retail -n +1 -f -u REGEX PIPEOUTfinalizará cuando REGEXaparezca una línea coincidente. (Como descargo de responsabilidad, escribí retailhace varios años exactamente con este propósito)

Respuesta2

Al abrir PIPEIN para escribir solo una vez, el programa finaliza, incluso si hay un retraso de 2 segundos:

mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
    echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN

Si abre el quince veces, es posible que el lector del quince lo vea cerrado y, por lo tanto, el escritor quedará colgado hasta que venga otro lector a leer del quince.

Entonces, la apuesta segura es abrir PIPEIN solo una vez. De lo contrario, es posible que veas que el programa se bloquea.

información relacionada