Como os programas são enviados para outros locais além de STDOUT / STDERR? Como evitar isso?

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 ambos os descritores, às vezes ainda obtenho alguma saída no meu console!

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

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

Na maioria das vezes, resolvo esses problemas usando script , mas ainda estou me perguntando o que está causando esse problema.

    
por MatthewRock 15.07.2016 / 13:11

2 respostas

40

A sintaxe que você usou está errada.

cmd &2>1 >file

será dividido como

cmd &
2>1 >file

Isto irá:

  1. Executar cmd como um trabalho em segundo plano sem redirecionamentos
  2. Em um processo separado (sem um comando!), você redirecionará stderr para um arquivo chamado literalmente de 1 e redirecionará stdout para file

A sintaxe que você quer é:

cmd >file 2>&1

A ordem das operações é importante. Isto irá:

  1. Redirecionar stdout para file
  2. Redirecionar stderr para &1 - ou seja, o mesmo filehandle que stdout

O resultado é que stderr e stdout serão redirecionados para file .

Em bash , uma sintaxe não-padrão mais simples (e por isso não recomendo, por questões de portabilidade), a sintaxe de cmd &> file faz a mesma coisa.

    
por 15.07.2016 / 13:31
10

Existem dois problemas.

A primeira é que a ordem é importante, a segunda é /dev/tty .

Vamos usar este script como um script de exemplo 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 "redirecionar stderr para onde stdout está gerando (assim, saída do console)". Em seguida, obtemos "redirecionar stdout para /dev/null . Acabamos com uma situação como esta:

stdout - > %código% /dev/null - > console

Então, acertamos:

stderr

E nós temos:

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

Agora, fazemos "Redirecionar ttdada para stdout " e, em seguida, "Redirecionar stderr para onde a stdout está apontando" (portanto, /dev/null ). Viva!

No entanto, ainda temos um problema; programa imprime em /dev/null . Agora eu não sei como consertar esse tipo de comportamento, então você provavelmente precisará do /dev/tty , mas esperamos que esse comportamento não aconteça com muita frequência.

    
por 15.07.2016 / 13:40