
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 -f
no 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 tail
um 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 foo
exibirá 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 > foo
foo 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 tail
processo 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 PIPEOUT
terminará quando uma correspondência de linha REGEX
aparecer. (Como isenção de responsabilidade, escrevi retail
há 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.