Como os programas saem para outros lugares além de STDOUT / STDERR? Como evitá-lo?

15

Aparentemente, não conheço todos os destinos de saída disponíveis para uso. Eu sei sobre stdout( &1) e stderr( &2). No entanto, depois de redirecionar os dois descritores, às vezes ainda recebo alguma saída no meu console!

O exemplo mais fácil que consigo pensar é o GNU Parallel; Cada vez que o uso, vejo um aviso de citação. Mesmo quando o faço &2>1 > file, ainda vejo o aviso.

E o mesmo se aplica a emerge: Quando executo o emerge e há alguns problemas, algumas informações não são impressas stdoutnem stdin, uma vez que eu as redireciono e elas ainda passam.

Eu geralmente resolvo esses problemas usando script, mas ainda estou me perguntando o que está causando esse problema.

MatthewRock
fonte
1
Por favor, forneça um exemplo completo .
Kusalananda
8
Você não vai conseguir todos eles . Um script sempre pode gravar em /dev/tty.
Satō Katsura
1
Quanto ao GNU parallel: mkdir ~/.parallel; touch ~/.parallel/will-citeirá desativar a mensagem irritante. Como alternativa, procure outras implementações de parallel.
Satō Katsura
2
@OleTange Porque não é um problema - estou perguntando por que algo está acontecendo e estou usando parallelcomo exemplo.
MatthewRock

Respostas:

40

A sintaxe que você usou está errada.

cmd &2>1 >file

será dividido como

cmd &
2>1 >file

Isso vai:

  1. Executar cmdcomo um trabalho em segundo plano sem redirecionamentos
  2. Em um processo separado (sem um comando!) Será redirecionado stderrpara um arquivo literalmente chamado 1e redirecionado stdoutparafile

A sintaxe que você deseja é:

cmd >file 2>&1

A ordem das operações é importante. Isso vai:

  1. Redirecionar stdoutparafile
  2. Redirecione stderrpara &1- ou seja, o mesmo tratamento de arquivo questdout

O resultado é que ambos stderre stdoutserão redirecionados para file.

Em bash, uma sintaxe não-padrão mais simples (e, portanto, não recomendo, por motivos de portabilidade) cmd &> filefaz a mesma coisa.

Stephen Harris
fonte
Bom obrigado. O outro problema pode ser /dev/tty, mas espero que isso não aconteça com muita frequência (se houver).
MatthewRock
5
Se você possui o atcomando em sua máquina e possui privilégios para usá-lo, pode executar o comando via at now. Veja a página de manual para detalhes. Isso executará o comando por meio de um mecanismo de processo em lote e o processo nunca terá um tty para gravar. Mas, em geral, eu não me preocuparia com esse caso extremo. Normalmente, apenas processos que requerem interação e deliberadamente precisam exibir itens para os usuários, apesar do redirecionamento /dev/tty.
Stephen Harris
estado lá, feito isso
davidbak
10

Existem dois problemas.

O primeiro é que a ordem importa, o segundo é /dev/tty.

Vamos usar esse script como um exemplo de script do qual queremos capturar a saída:

test.sh:

#!/bin/bash

echo dada
echo edada 1>&2
echo ttdada >/dev/tty

Agora vamos ver as saídas dos comandos:

./testmyscript.sh 2>&1 >/dev/null:

edada
ttdada

Como a ordem de avaliação é da esquerda para a direita, primeiro obtemos "redirecionamento stderrpara onde quer que stdoutesteja saindo (portanto, saída do console)". Então obtemos "redirecionar stdoutpara /dev/null. Terminamos com uma situação como esta:

stdout-> /dev/null stderr-> console

Então, acertamos:

./testmyscript.sh >/dev/null 2>&1

E temos:

ttdada.

Agora fazemos "Redirecionar stdoutpara /dev/null" e depois "Redirecionar stderr para onde stdout está apontando" (então, /dev/null). Viva!

No entanto, ainda temos um problema; programa imprime em /dev/tty. Agora não sei como consertar esse tipo de comportamento, então é provável que você precise script, mas espero que esse comportamento não ocorra com muita frequência.

MatthewRock
fonte