Observando os dois comandos separadamente:
utility 2>&1 >output.log
Aqui, como os redirecionamentos são processados da esquerda para a direita, o fluxo de erros padrão será redirecionado primeiro para onde quer que o fluxo de saída padrão vá (possivelmente para o console) e, em seguida, o fluxo de saída padrão será redirecionado para um arquivo. O fluxo de erro padrão não seria redirecionado para esse arquivo.
O efeito visível disso é que você obtém o que é produzido com erro padrão na tela e o que é produzido com a saída padrão no arquivo.
utility 2>&1 | tee output.log
Aqui, você redireciona o erro padrão para o mesmo local que o fluxo de saída padrão. Isso significa que os dois fluxos serão canalizados para o tee
utilitário como um único fluxo de saída entrelaçado e que esses dados de saída padrão serão salvos no arquivo especificado por tee
. Os dados também seriam reproduzidos tee
no console (é isso que tee
ocorre, ele duplica os fluxos de dados).
Qualquer uma dessas opções depende do que você deseja alcançar.
Observe que você não seria capaz de reproduzir o efeito do segundo pipeline apenas >
(como em utility >output.log 2>&1
, o que salvaria a saída padrão e o erro no arquivo). Você precisaria usar tee
para obter os dados no console e no arquivo de saída.
Notas Adicionais:
O efeito visível do primeiro comando,
utility 2>&1 >output.log
seria o mesmo que
utility >output.log
Ou seja, a saída padrão vai para o arquivo e o erro padrão vai para o console.
Se uma etapa de processamento adicional fosse adicionada ao final de cada um dos comandos acima, haveria uma grande diferença:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
No primeiro pipeline, more_stuff
obteria o que originalmente era o fluxo de erro padrão utility
como dados de entrada padrão, enquanto no segundo pipeline, uma vez que é apenas o fluxo de saída padrão resultante que é enviado por um canal, a more_stuff
parte do pipeline não recebe nada para ler em sua entrada padrão.
utility 2>&1 | tee output.log
, você quer dizer que, como 1 está sendo direcionado para tee, 2 também. Como tee duplica o fluxo, a saída é exibida no console e gravada no arquivo? Daí a diferença entreutility 2>&1 > output.log
eutility 2>&1 | tee output.log
étee
que ele duplica o fluxo.Estaria correto?utility 2>&1 > output.log | more_stuff
eutility >ouput.log
| more_stuff, is the difference that
more_stuff` tem como saída o erro padrão para o consolemore_stuff
? Como no segundo exemplo, não há saída para o console, essencialmente não há entrada paramore_stuff
? Se sim, isso não está claro desde o parágrafo anterior, observe que a saída padrão vai para o arquivo e o erro padrão para o console.more_stuff
receberia o queutility
originalmente foi enviado ao seu fluxo de erros (mas que foi redirecionado para a saída padrão). Não porque acabaria no console semore_stuff
não estivesse lá, mas porque está indo para o fluxo de saída padrão . No segundo comando, nãomore_stuff
recebe nada, pois não há saída padrão do lado esquerdo do pipeline. O fluxo de erro deutility
ainda terminaria no console no 2º comando.utility > output.log | more_stuff
não resulta em uma saída no fluxo de saída padrão de um ponto de vista de erro padrão?Nota editorial
Leia os comentários sobre esta resposta - derobert .
Resposta original
2>&1 >output.log
significa primeiro começar a enviar todos os itens do identificador de arquivo 2 (erro padrão) para o identificador de arquivo 1 (saída padrão) e enviá-lo para o arquivooutput.log
. Em outras palavras, envie erro padrão e saída padrão para o arquivo de log.2>&1 | tee output.log
é o mesmo com o2>&1
bit, ele combina saída padrão e erro padrão no fluxo de saída padrão. Em seguida, canaliza isso através dotee
programa que enviará sua entrada padrão para sua saída padrão (comocat
) e também para o arquivo. Por isso, combina os dois fluxos (erro e saída) e depois envia para o terminal e o arquivo.A linha inferior é que o primeiro envia
stderr
/stdout
para o arquivo, enquanto o segundo envia para tanto o arquivo e saída padrão (que é provavelmente o terminal a menos que você está dentro de uma outra construção, que reorientou a saída padrão).Menciono essa última possibilidade, porque você pode ter coisas como:
onde nada acaba no terminal.
fonte
cat /doesnotexist 2>&1 >output.txt
- você verá ocat: /doesnotexist: No such file or directory
display exibido no terminal e o output.txt é um arquivo vazio. A ordem de precedência e fechamento estão em jogo:2>&1
(dup fd2 do atual fd1) e, em seguida>output.txt
(redirecione o fd1 para o output.txt, sem alterar mais nada). O motivo2>&1 |
é diferente por causa da ordem de precedência:|
antes>
.O primeiro comando fará a outra tarefa:
Depois de
o antigo STDOUT será salvo (copiado) no STDERR e o STDOUT será redirecionado para o arquivo.
Portanto, o stdout irá para o arquivo e o stderr irá para o console.
E em
os dois fluxos serão redirecionados para tee. O Tee duplicará qualquer entrada em seu stdout (o console no seu caso) e no arquivo (
output.log
).E há outra forma de primeiro:
isso redirecionará STDOUT e STDERR para o arquivo.
fonte
A saída anterior apenas para o arquivo. O segundo gera saída para o arquivo e para a tela.
fonte
O motivo
2>&1 | tee
é poder capturar stdout e stderr em um arquivo de log e vê-lo na tela ao mesmo tempo. Isso também poderia ser feito>output.txt 2>&1 & tail -f
, mas você não saberia quando o comando em segundo plano foi finalizado - o programa foi finalizado ou está sendo executado sem saída. Esse2>&1 | tee
era um idioma comum para programadores.fonte
Vamos ver um código de exemplo primeiro:
Vamos comparar os resultados:
./helloerror
+ file: no message; console: mensagem 1,2,3;
./helloerror >error.txt
+ arquivo: mensagem 1,2; console: mensagem 3;
./helloerror 2>&1 >error.txt
+ arquivo: mensagem 1,2; console: mensagem 3;
+ igual a ./helloerror> error.txt
./helloerror >error.txt 2>&1
+ arquivo: mensagem 3,1,2; console: nenhuma mensagem;
+ observe que o pedido 3 é primeiro, depois 1 e 2
./helloerror | tee error.txt 2>&1
+ arquivo: mensagem 1,2; console: mensagem 3,1,2;
+ observe que o pedido 3 é primeiro, depois 1 e 2
./helloerror 2>&1 | tee error.txt
+ arquivo: mensagem 3,1,2; console: mensagem 3,1,2;
Para usar:
./helloerror >error.txt 2>&1
-> se alguém quiser todas as mensagens (stdout + stderr) no arquivo, mas não estiver no console
./helloerror 2>&1 | tee error.txt
-> se alguém quiser todas as mensagens (stdout + stderr) em arquivo e impressas no console
fonte
Aqui está uma postagem resumindo os fluxos de saída do Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html
Um trecho da postagem:
Existem 3 fluxos de saída padrão:
fonte