Lê stdout / stderr de subshell para parent

0

Em um script de shell, eu quero escrever para o stdin de um processo externo X usando um pipe nomeado, e eu quero enviar o stdout / stderr de outro pipe 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)

Então, no script acima, nós já iniciamos o processo X, ele está sendo executado há algum tempo. Mas agora, quando executamos o script acima, queremos enviar X algum stdin e queremos ler o stdout do processo X, usando PIPEOUT.

O que eu 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 eu não sei como rodar algum processo em segundo plano (cauda ou gato para ler do PIPEOUT) e enviar esse stdio para o terminal atual.

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

    
por Alexander Mills 07.07.2017 / 09:36

2 respostas

2

Não estou claro sobre o que você quis dizer com tail -f $(tail -F PIPEOUT) & . É tail -f ing o arquivo que é o resultado de tail -F , que convencionalmente nunca termina. Minha suposição é que você quer dar saída de tudo o que vem pelo pipe, não importa quanto tempo demore.

O problema com apenas tail -f é que ele precisa encontrar o final do arquivo antes de gerar qualquer saída, o que para o pipe nunca acontece. Você pode dar a tail um ponto inicial explícito, em vez de -n +x , escolhendo a linha para comece em (desde o início, 1 indexado). tail -n 1 -f foo exibirá tudo o que puder obter de 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, no entanto, que echo > foo fechará o foo após escrever a linha - o comando do outro lado precisará ter prazer em lidar com isso. Se este exemplo é artificial e a entrada real vem de outro lugar, você pode desconsiderar isso.

Note também que o processo tail nunca terminará - ele espera que algo mais venha pelo canal. Você terá que matá-lo explicitamente, talvez com o controle do trabalho do seu shell. Se houver algum padrão na saída que indique que foi feito, talvez você encontre retail ("tail with regular expressions") útil - retail -n +1 -f -u REGEX PIPEOUT terminará quando uma linha correspondente a REGEX aparecer. (Como aviso de isenção, eu escrevi retail alguns anos atrás para este propósito exato)

    
por 07.07.2017 / 09:57
0

Ao abrir apenas o PIPEIN para escrever 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, então ele pode ser visto como fechado pelo leitor do fifo, e assim o escritor ficará pendurado até que outro leitor venha ler o fifo.

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

    
por 08.07.2017 / 03:31