Como redirecionar e anexar stdout e stderr a um arquivo com o Bash?


1534

Para redirecionar stdout para um arquivo truncado no Bash, eu sei usar:

cmd > file.txt

Para redirecionar stdout no Bash, anexando a um arquivo, eu sei usar:

cmd >> file.txt

Para redirecionar stdout e stderr para um arquivo truncado, eu sei usar:

cmd &> file.txt

Como redireciono stdout e stderr anexando a um arquivo? cmd &>> file.txtnão funcionou para mim.


37
Gostaria de observar que o & outfile é um código específico do Bash (e outros) e não é portátil. O caminho a percorrer portátil (similar às respostas anexando) sempre foi e ainda é> outfile 2> & 1
TheBonsai

Respostas:


1999
cmd >>file.txt 2>&1

O Bash executa os redirecionamentos da esquerda para a direita da seguinte maneira:

  1. >>file.txt: Abra file.txtno modo de acréscimo e redirecione para stdoutlá.
  2. 2>&1: Redirecione stderrpara "stdout para onde está indo atualmente" . Nesse caso, esse é um arquivo aberto no modo de acréscimo. Em outras palavras, &1reutiliza o descritor de arquivo que stdoutatualmente usa.

33
funciona bem! mas existe uma maneira de entender isso ou devo tratar isso como uma construção de basquete atômica?
Flybywire 18/05/09

181
É um redirecionamento simples, as instruções de redirecionamento são avaliadas, como sempre, da esquerda para a direita. >> arquivo: vermelho. STDOUT para arquivo (modo de acréscimo) (abreviação de 1 >> arquivo) 2> & 1: Vermelho. STDERR para "para onde vai o stdout" Observe que a interpretação "redireciona STDERR para STDOUT" está incorreta.
TheBonsai

31
Ele diz "anexa a saída (stdout, descritor de arquivo 1) no arquivo.txt e envia stderr (descritor de arquivo 2) para o mesmo local que o fd1".
Pausado até novo aviso.

2
@TheBonsai no entanto, e se eu precisar redirecionar o STDERR para outro arquivo, mas anexando? Isso é possível?
Arod #

41
se você fizer cmd >>file1 2>>file2isso, deve conseguir o que deseja.
Woodrow Douglass

367

Existem duas maneiras de fazer isso, dependendo da sua versão do Bash.

A maneira clássica e portátil ( Bash pré-4 ) é:

cmd >> outfile 2>&1

Uma maneira não portável, começando com o Bash 4, é

cmd &>> outfile

(analógico para &> outfile)

Para um bom estilo de codificação, você deve

  • decida se a portabilidade é uma preocupação (use o modo clássico)
  • decida se a portabilidade mesmo para o Bash pré-4 é uma preocupação (use o modo clássico)
  • independentemente da sintaxe usada, não a altere no mesmo script (confusão!)

Se o seu script já começar #!/bin/sh(não importa se isso é pretendido ou não), a solução Bash 4 e, em geral, qualquer código específico do Bash, não é o caminho a seguir.

Lembre-se também de que o Bash 4 &>>é apenas uma sintaxe mais curta - ele não apresenta nenhuma nova funcionalidade ou algo parecido.

A sintaxe é (ao lado de outra sintaxe de redirecionamento) descrita aqui: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
Eu prefiro & >>, pois é consistente com &> e >>. Também é mais fácil ler 'anexar saída e erros a este arquivo' do que 'enviar erros à saída, anexar saída a este arquivo'. Nota ao Linux geralmente tem uma versão atual do bash, OS X, no momento da escrita, ainda requer festa de 4 a instalada manualmente via homebrew etc.
mikemaccana

Eu gosto mais porque é mais curto e apenas dois lugares por linha, então o que, por exemplo, o zsh faria com "& >>"?
Phillipp

Também é importante observar que, em um trabalho cron, você tem que usar a sintaxe pré-4, mesmo se o sistema tem Bash 4.
hyperknot

5
O @zsero cron não usa o bash de todo ... ele usa sh. Você pode alterar o shell padrão anexando SHELL=/bin/bashao crontab -earquivo.
Ray Foss

89

No Bash, você também pode especificar explicitamente seus redirecionamentos para arquivos diferentes:

cmd >log.out 2>log_error.out

Anexar seria:

cmd >>log.out 2>>log_error.out

6
Redirecionar dois fluxos para o mesmo arquivo usando sua primeira opção fará com que o primeiro escreva "em cima" do segundo, substituindo parte ou todo o conteúdo. Use cmd >> log.out 2> log.out .
Orestis P.

3
Obrigado por capturar isso; você está certo, um vai derrotar o outro. No entanto, seu comando também não funciona. Eu acho que a única maneira de gravar no mesmo arquivo é como foi dado antes cmd >log.out 2>&1. Estou editando minha resposta para remover o primeiro exemplo.
Aaron R.

65

No Bash 4 (assim como no ZSH 4.3.11):

cmd &>>outfile

apenas fora da caixa


2
@ all: esta é uma boa resposta, pois funciona com o bash e é breve, então editei para garantir que ele mencione explicitamente o bash.
Mikemaccana 20/05

10
@mikemaccana: A resposta do TheBonsai mostra a solução do bash 4 desde 2009
jfs 27/03

52

Isso deve funcionar bem:

your_command 2>&1 | tee -a file.txt

Ele armazenará todos os logs no arquivo.txt e os despejará no terminal.


Esta é a resposta correta se você quiser ver a saída no terminal também. No entanto, essa não foi a pergunta originalmente feita.
Mikko Rantalainen 15/04

25

Tente isto

You_command 1>output.log  2>&1

Seu uso do &> x.file funciona no bash4. Desculpe por isso : (

Aqui estão algumas dicas adicionais.

0, 1, 2 ... 9 são descritores de arquivo no bash.

0 significa stdin, 1 significa stdout, 2 significa stderror. 3 ~ 9 é de reposição para qualquer outro uso temporário.

Qualquer descritor de arquivo pode ser redirecionado para outro descritor ou arquivo usando o operador >ou >>(anexar).

Uso: < file_descriptor > > < filename | & file_descriptor >

Consulte http://www.tldp.org/LDP/abs/html/io-redirection.html


Seu exemplo fará algo diferente do que o OP pediu: Ele redirecionará o stderr de You_commandpara stdout e o stdout de You_commandpara o arquivo output.log. Além disso, ele não será anexado ao arquivo, mas o substituirá.
Pabouk 31/05

Correto: o descritor de arquivo pode ter qualquer valor maior que 3 para todos os outros arquivos.
Itachi

5
Sua resposta mostra o erro de redirecionamento de saída mais comum: redirecionando STDERR para onde o STDOUT está apontando no momento e somente depois redirecionando o STDOUT para o arquivo. Isso não fará com que o STDERR seja redirecionado para o mesmo arquivo. A ordem dos redirecionamentos é importante.
Jan Wikholm

1
isso significa que eu deveria primeiro redirecionar STDERROR para STDOUT e depois redirecionar STDOUT para um arquivo. 1 > output.log 2>&1
Quintus.Zhou

1
@ Quintus.Zhou Yup. Seus redirecionamentos de versão são errados e, ao mesmo tempo, arquivados.
Alex Yaroshevich

11

Estou surpreso que, em quase dez anos, ninguém postou essa abordagem ainda:

Se estiver usando versões mais antigas do bash, onde &>>não estiver disponível, você também poderá:

(cmd 2>&1) >> file.txt

Isso gera um subshell, portanto é menos eficiente do que a abordagem tradicional cmd >> file.txt 2>&1e, consequentemente, não funcionará para comandos que precisam modificar o shell atual (por exemplo cd, pushd), mas essa abordagem parece mais natural e compreensível para mim:

  1. Redirecione stderr para stdout.
  2. Redirecione o novo stdout anexando a um arquivo.

Além disso, os parênteses removem qualquer ambiguidade de ordem, especialmente se você deseja canalizar stdout e stderr para outro comando.


Essa implementação causa um processo extra para a execução do sistema. O uso da sintaxe cmd >> file 2>&1funciona em todos os shells e não precisa de um processo extra para ser executado.
Mikko Rantalainen 15/04

@MikkoRantalainen Eu já expliquei que gera um subshell e é menos eficiente. O objetivo dessa abordagem é que, se a eficiência não é grande coisa (e raramente é), é mais fácil lembrar e difícil errar.
jamesdlin 15/04
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.