Primeiro, vamos criar um programa run_test
, que gera stdout e stderr:
$ run_test() { while sleep 0.2; do echo "Out $((++c))"; echo "err$c">&2; done; }
Agora, vamos enviar o stdout e o stderr para diferentes filtros. Como não tenho um prepend
instalado, usarei sed
para o mesmo propósito:
$ exec 3>&2; { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3
Como funciona
-
exec 3>&2
Isso cria o descritor de arquivos 3 como uma duplicata de stderr.
-
run_test | sed 's/^/stdout: /'
Isso executa
run_test
e adicionastdout:
ao início da stdout. -
{ run_test | sed 's/^/stdout: /'; } 2>&1 1>&3
2>&
redireciona stderr para stdout para que stderr entre no próximo canal.1>&3
redireciona stdout para stderr para que apareça no terminal. -
{ run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
O último pipe captura o stderr do run_test (que agora é stdout) e adiciona
stderr:
a ele.
Usando a substituição de processos
$ run_test > >(sed 's/^/stdout: /') 2> >(stdbuf -oL sed 's/^/stderr: /' >&2)
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3
O acima usa stdbuf
, que é padrão no Linux. Para outros sistemas operacionais, será necessário procurar comandos análogos.