$ command >stdout.txt 2>stderr.txt && cat stdout.txt stderr.txt > both.txt
Existem vários legal truques você pode usar, mas nenhum deles parece ter sucesso em produzir os 3 arquivos melhor do que o anterior. O principal problema é que o arquivo both.txt
não mostrará as mensagens (STDERR e STDOUT) na ordem correta. Isso ocorre porque (como explicado aqui ):
When you redirect both standard output and standard error to the same file, you may get some unexpected results. This is due to the fact that STDOUT is a buffered stream while STDERR is always unbuffered. This means that every character of STDERR is written as soon as it is available while STDOUT writes stuff in batches. When both STDOUT and STDERR are going to the same file you may see error messages appear sooner than you would have expected them in relation to the actual output of your program or script. It isn’t anything to be alarmed about but is simply a side-effect of buffered vs. unbuffered streams, you just need to keep it in mind.
A melhor alternativa que eu consegui encontrar foi o uso de subshells bash, é meio complexo e still não exibe a saída na ordem correta. Fiz um script Perl simples, test.pl
que imprime "OUT" para STDOUT
e "ERR" para STDERR
, repetindo o processo 3 vezes:
#/usr/bin/perl
for($i=0; $i<=2; $i++){
print STDOUT "OUT\n";
print STDERR "ERR\n"
}
Sua saída normal e não redirecionada é:
$ ./test.pl
OUT
ERR
OUT
ERR
OUT
ERR
Para redirecionar a (s) saída (s) que eu executei:
(./test.pl 2> >(tee error.txt) > >(tee out.txt)) > both.txt
Isso usa tee
, um programa que imprimirá sua entrada para a tela e para um nome de arquivo. Portanto, estou redirecionando STDERR
e passando-o como entrada para tee
, solicitando que ele grave no arquivo error.txt
. Da mesma forma, com STDOUT
e o arquivo out.txt
. Eu estou colocando a coisa toda em um subshell ( (...)
) para que eu possa capturar all de sua saída e redirecionar para both.txt
.
Agora, isso funciona na medida em que cria três arquivos, um com STDERR
, um com STDOUT
e um com ambos. No entanto, conforme explicado acima, isso resulta em mensagens que aparecem na ordem incorreta em both.txt
:
$ cat both.txt
ERR
ERR
ERR
OUT
OUT
OUT
A única maneira de contornar isso foi encontrar o tempo que foi impresso em cada linha de saída e, em seguida, a classificação, mas ele está ficando seriamente complicado e, em seu lugar, eu perguntaria: eu mesmo se realmente vale a pena:
$(./test.pl \
2> >(while read n; do echo 'date +%N'" $n"; echo "$n" >>error.txt; done) \
> >(while read n; do echo 'date +%N'" $n"; echo "$n" >> out.txt; done )) \
| gawk '{print $2}'> both.txt