Por que redirecionar a saída para 2> & 1 e 1> & 2?

36

Eu encontrei vários comandos que usam 2>&1e 1>&2, mas não consigo entender o propósito de usá-lo e quando devo usá-lo.

O que eu entendo

Eu sei que 1representa um padrão e 2representa um erro padrão. Eu entendo que 2>&1combina a saída de 2ao 1e vice-versa.

O que eu não entendo

  1. Quando devo usá-lo?
  2. Que finalidade serve?
AmendoimMacaco
fonte

Respostas:

39

Às vezes, você deseja redirecionar stdout e stderr para o mesmo local. É quando >&é usado - aponta um descritor de arquivo para outro.


Por exemplo, se você deseja gravar stdout e stderr no mesmo arquivo (seja /dev/nullou output.txt), poderá redirecioná-los separadamente, com

app 1>/dev/null 2>/dev/null

ou você pode redirecionar um descritor de arquivo para o arquivo e o outro descritor de arquivo para o primeiro:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

No primeiro exemplo, 2>&1 aponta o descritor de arquivo nº 2 para onde o nº 1 já está apontando. O segundo exemplo alcança o mesmo, apenas começando com stderr.

Como outro exemplo, há casos em que o stdout (descritor de arquivo nº 1) já está apontando para o local desejado, mas você não pode fazer referência a ele pelo nome (pode estar associado a um tubo, um soquete ou algo assim). Isso geralmente acontece quando se utiliza a expansão do processo (as ` `ou $( )operadores), que normalmente só captura stdout, mas você pode querer incluir stderr nele. Nesse caso, você também usaria >&para apontar stderr para stdout:

out=$(app 2>&1)

Outro exemplo comum é um pager, ou greputilitário similar, uma vez que o canal |normalmente só funciona no stdout, você redirecionaria o stderr para o stdout antes de usar o canal:

app 2>&1 | grep hello

Como saber qual 2>&1ou 1>&2está correto? O descritor de arquivo já configurado vai para a direita >&e o descritor de arquivo que você deseja redirecionar vai para a esquerda. ( 2>&1significa "apontador descritor de arquivo nº 2 para descritor de arquivo nº 1".)


Alguns shells possuem atalhos para redirecionamentos comuns; Aqui estão alguns exemplos do Bash:

  • 1> pode ser reduzido para apenas >

  • 1>foo 2>&1para >&fooou&>foo

  • 2>&1 | program para |& program

gravidade
fonte
Eu não tinha ideia de que fazer app 1>/dev/null 2>&1significaria que 2> & 1 apontariam para o arquivo para o qual 1 já estava redirecionando. Presumo que eu poderia fazer tão facilmente app > /dev/null &>?
PeanutsMonkey
Estou tendo dificuldade para entender the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. O que você quer dizer com o descritor de arquivo já configurado? O que significa o direito de?
PeanutsMonkey
Desculpe, a menos que você pretendesse me dar instruções, não sigo a declaração que você fez como mencionado anteriormente.
PeanutsMonkey
1
Faça com que cada descritor de arquivo redirecione um de cada vez, da esquerda para a direita, e aplique essas regras nessa ordem. Se você primeiro direcionar o stdout para um arquivo, então stderr redirecionamento para onde stdout nós agora apontando, então stderr e stdout irá para o mesmo arquivo. Se você trocasse esses dois redirecionamentos, obteria resultados diferentes (redirecione o stderr para onde o stdout está indo agora , mova o stdout para apontar para outro arquivo, enquanto o stderr continua para onde foi apontado).
Jason
2

Uma situação em que você precisa é quando deseja exibir strace saída em um pager. straceimprime sua saída em erro padrão e os tubos geralmente conectam a saída padrão à entrada padrão; portanto, você deve usar o redirecionamento:

strace -p $pid 2>&1 | less
jpalecek
fonte
Como assim pipes generally connect standard output to standard input?
PeanutsMonkey
2
Quero dizer que pipe ( |) pega a saída padrão do primeiro comando e o conecta à entrada padrão do segundo comando.
jpalecek
2

Às vezes você deseja redirecionar ambos stdout( 1) estderr ( 2) para o mesmo local ( /dev/nullpor exemplo). Uma maneira de conseguir isso seria:

$ program 1>/dev/null 2>/dev/null

Mas a maioria das pessoas encurtar isso redirecionando stderrpara stdoutcom 2>&1:

$ program 1>/dev/null 2>&1

Uma versão ainda mais curta é:

$ program >&- 2>&-
Zaz
fonte
1

2: É para quando você terá saída proveniente de erro padrão e saída padrão e deseja que eles sejam compostos em uma única sequência.

1: Quando você deseja manipular a saída do erro padrão e da saída padrão.

soandos
fonte
O que você quer dizer com manipular? Meu entendimento é que qualquer coisa redirecionada para >2é enviada para / dev / null. Ou eu entendi completamente errado?
fácil fazer o download
Isso não está correto. Ao manipular, quero dizer que o grep ou algo semelhante. Veja aqui um exemplo.
Soandos
0

Eu o uso para iniciar um trabalho desanexado:

someProgram 2>&1 >& my.log &

então eu posso sair e algum programa ainda estará em execução. A funcionalidade é fornecida pelo GNU Screen, tmux e alguns outros programas - mas aqui é alcançada sem dependências externas.

Adobe
fonte
1
Isso funciona apenas enquanto não houver SIGHUP enviado ao programa. Melhor uso nohupou disownem tais casos.
slhck
@slhck: ok. Mas se eu não enviar o SIGHUP para o programa - ninguém o fará, certo?
Adobe
Não, o terminal de controle avisará os processos de logout com o SIGHUP. Na prática, se você executar um shell remoto através do SSH e sair, seu processo também morrerá, por exemplo.
slhck
@ slhck: Não pode ser verdade: eu uso por alguns anos - eu saio do ssh e o processo ainda está em execução.
Adobe
Vou ter que procurar isso com mais detalhes, mas apenas colocar programas em segundo plano não funcionou para mim em todos os casos, e definitivamente nem funciona na minha máquina local. Parece que Zsh e Bash também se comportam de maneira diferente aqui.
slhck 28/07
0

Imagine que existe um diretório chamado try que possui esses três arquivos:file file1 and file2.

Agora execute este comando:

cat file file1 file2 file3

Os três primeiros arquivos são abertos, mas cat gera um erro ao abrir o quarto, pois ele não existe.

Agora execute:

cat file file1 file2 file3 1>outfile 2>&1

Você não verá nenhuma saída na tela: Primeiro 1>outfileredirecionará a saída do comando para outfilee, em seguida, redirecionará ( 2>&1) o erro gerado ao tentar abrir file3paraoutfile .

1>&2 funciona de maneira semelhante e redireciona o fluxo de erros para a saída padrão.

Espero que isto ajude!

Faiz
fonte
0

Cenário alternativo: os comandos do terminal mostram a saída em outro terminal

Use o ttycomando em cada terminal para identificá-los:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Supondo que esses TTYs, para redirecionar o stdout do primeiro para o segundo, execute isso no primeiro terminal:

exec 1>/dev/pts/1

Nota: Agora toda saída de comando será exibida em pts / 1

Para restaurar o comportamento padrão stdout de pts / 0:

exec 1>/dev/pts/0

Veja este vídeo para uma demonstração.

Vitalie Ghelbert
fonte
0

O caso ao redirecionar o stderr para o stdout já foi abordado aqui (por exemplo, use-o para filtrar mensagens de erro (grep)).

O outro caso está redirecionando stdout para stderr. Uma maneira comum de usar (pelo menos para mim) é enviar avisos / mensagens de erro impressas com "echo" (em meus shellscripts) para o stderr (para que possam chamar a atenção do usuário mais facilmente).

Por exemplo,

echo "file \"${file\" does not exist..." 1>&2
umläute
fonte