Tubulação stdout e stderr no bash?

156

Parece que as versões mais recentes do bash têm o &>operador, que (se bem entendi), redireciona stdout e stderr para um arquivo ( &>>acrescenta ao arquivo, como Adrian esclareceu).

Qual é a maneira mais simples de conseguir a mesma coisa, mas ao invés de canalizar para outro comando?

Por exemplo, nesta linha:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError

Gostaria que o grep correspondesse ao conteúdo em stdout e stderr (efetivamente, combine-os em um fluxo).

Nota : esta pergunta é sobre canalização, não redirecionamento - portanto, não é uma duplicata da pergunta que está atualmente marcada como duplicada.

Andrew Ferrier
fonte
Consulte a segunda resposta ( stackoverflow.com/a/637834/1129642 ) na pergunta vinculada para a maneira correta de canalizar stdout e stderr. Não há necessidade de outra pergunta.
Marki555
4
Triplee @ Não é uma cópia exata, é? Pipe vs. redirecionar para arquivo?
Benjamin W.
@BenjaminW Há pelo menos uma resposta lá que resolve os dois cenários, embora não seja a resposta aceita. Essa é uma pergunta bastante comum, portanto, provavelmente poderíamos encontrar uma duplicata melhor ou pedir a um moderador para mesclá-las - ou mesmo, na pior das hipóteses, criar uma canônica totalmente nova para esse tópico. Se você encontrar um idiota melhor, proponha-o. Desde já, obrigado.
tripleee
12
@ tripleeee Resolve, sim, mas nenhuma das respostas usa o |&atalho, que eu acho que é de longe a solução mais conveniente para "redirecionar stdout e stderr para um pipe".
Benjamin W.
3
Esta não é uma duplicata da pergunta vinculada, e não ficou claro que a resposta de Marko fez o que eu queria. Além disso, não menciona | &. Votação para reabrir.
Martin Bonner apoia Monica

Respostas:

163

(Observe que &>>file anexa a um arquivo enquanto &>redirecionaria e substituiria um arquivo existente anteriormente.)

Para combinar stdoute stderrvocê redirecionaria o último para o primeiro usando 2>&1. Isso redireciona stderr (descritor de arquivo 2) para stdout (descritor de arquivo 1), por exemplo:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std
stderr
$

stdoutvai para stdout, stderrvai para stderr. grepsó vê stdout, daístderr imprime no terminal.

Por outro lado:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std
$

Após gravar em stdout e stderr, 2>&1redireciona o stderr de volta para o stdout e grepvê as duas strings no stdin, filtrando as duas.

Você pode ler mais sobre redirecionamento aqui .

Em relação ao seu exemplo (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError

ou, usando >=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError
Adrian Frühwirth
fonte
Obrigado pelo esclarecimento &>>. Corrigi minha pergunta.
Andrew Ferrier
18
Eu adicionei o seu exemplo à minha resposta, para o caso de não ser óbvio com base nos meus exemplos. Como nota lateral, você também pode usar o específico do bash em |&vez de 2>&1 |.
Adrian Frühwirth
13
Nota lateral sobre o atalho |&proposto por AdrianFrühwirth para futuros leitores: esse recurso é suportado apenas na bashversão 4+. Se você estiver usando 3 ou menos, terá que ficar com 2>&1 |.
tomocafe
3
O redirecionamento Bash é muito bem explicado aqui . @ AdrianFrühwirth fez um bom trabalho, o link colado vai ainda mais longe. Às vezes, gostaria que a documentação oficial do Bash fosse tão boa.
David Andreoletti 13/03/2015
112

O Bash tem uma abreviação para 2>&1 |, a saber |&, quais canais stdout e stderr (consulte o manual ):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

Isso foi introduzido no Bash 4.0, veja as notas de versão .

Benjamin W.
fonte
Obrigado por adicionar isso para garantir a integridade. Vou manter a outra resposta correta, pois muitas pessoas ainda estão usando o bash pré-4.0. Mas isso é útil.
Andrew Ferrier 9/16
9
Mais notavelmente, talvez, o Bash enviado no macOS seja muito antigo para suportar isso.
Flimm
@Flimm mas o zsh não é
Trenton
1
Como o ksh usa | & para coproc, isso parece uma má escolha para uma abreviação desnecessária. Eu odeio ver linhas com uma pilha de dups e redirecionamentos tanto quanto o próximo cara, mas há algo a ser dito por ser explícito ... e peço desculpas por esse comentário não adicionar muito. Eu só queria expressar aversão à taquigrafia sem diminuir a resposta realmente útil, porque é bom que as pessoas vejam isso. Eu não sabia disso, então obrigado por me informar.
Paul Hodges
@PaulHodges Concordo que não é portátil - gosto principalmente de usá-lo em sessões interativas do Bash para evitar digitar demais.
Benjamin W.