Leia stdout/stderr do subshell para o pai

Leia stdout/stderr do subshell para o pai

Em um script de shell, quero escrever no stdin de um processo externo X usando um canal nomeado e quero enviar o stdout/stderr de outro canal nomeado para o terminal atual.

O processo externo X está recebendo stdin via PIPEIN e está enviando stdout/stderr para 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)

Portanto, no script acima, já iniciamos o processo X, ele está em execução há algum tempo. Mas agora, quando executamos o script acima, queremos enviar ao X algum stdin e queremos ler o stdout do processo X, usando PIPEOUT.

O que estou tentando fazer acima é configurar uma leitura no PIPEOUT antes de enviar o stdin para o X, para ter certeza de capturar todo o stdout/stderr do X. O problema é que não sei como executar algum processo em segundo plano (tail ou cat para ler do PIPEOUT) e envie esse stdio para o terminal atual.

Alguém sabe do que estou falando. Se não me engano, só preciso corrigir a linha rotulada (1) e de alguma forma configurar uma leitura em segundo plano que possa ler do PIPEOUT e enviar esse stdio para o terminal/tty atual de alguma forma.

Responder1

Não estou claro sobre o que você pretendia tail -f $(tail -F PIPEOUT) &fazer. Está tail -fno arquivo queé o resultado de tail -F, que convencionalmente nunca termina. Minha suposição é que você deseja produzir tudo o que passa pelo tubo, não importa quanto tempo leve.

O problema com just tail -fé que ele precisa encontrar o final do arquivo antes de gerar qualquer coisa, o que nunca acontece com o pipe. Você podeforneça tailum ponto de partida explícito em vez disso com-n +x, escolhendo a linha para começar (desde o início, indexado em 1). tail -n 1 -f fooexibirá tudo o que pode obter 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

Observe, entretanto, que echo > foofoo será fechado após escrever a linha - o comando do outro lado precisará estar feliz em lidar com isso. Se este exemplo for artificial e a entrada real vier de outro lugar, você poderá desconsiderar isso.


Observe também queo tailprocesso nunca terminará– continua esperando que algo mais possa sair pelo cano. Você mesmo terá que eliminá-lo explicitamente, talvez com o controle de trabalho do seu shell. Se houver algum padrão na saída que indique que foi feito, você poderá encontrarretail("cauda com expressões regulares")útil – retail -n +1 -f -u REGEX PIPEOUTterminará quando uma correspondência de linha REGEXaparecer. (Como isenção de responsabilidade, escrevi retailhá vários anos exatamente com esse propósito)

Responder2

Ao abrir o PIPEIN para escrita apenas uma vez, o programa termina - mesmo que haja um atraso 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

Se você abrir o fifo várias vezes, ele poderá ser visto como fechado pelo leitor do fifo e, portanto, o escritor ficará pendurado até que outro leitor apareça para ler o fifo.

Portanto, a aposta salva é abrir o PIPEIN apenas uma vez. Caso contrário, você poderá ver que o programa trava.

informação relacionada