Por que a saída de alguns programas do Linux não é para STDOUT nem para STDERR?

20

Por que a saída de alguns programas do Linux não chega nem a STDOUT nem a STDERR?

Na verdade, eu quero saber como capturar de forma confiável toda a saída do programa, não importa qual 'stream' seja usado. O problema que tenho é que alguns programas não parecem deixar sua saída ser capturada.

Um exemplo é o comando 'time':

time sleep 1 2>&1 > /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

ou

time sleep 1 &> /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

Por que vejo a saída nas duas vezes? Eu esperava que tudo fosse canalizado para / dev / null .

Qual fluxo de saída é usado no tempo e como posso canalizá-lo em um arquivo?

Uma maneira de contornar o problema é criar um script Bash , por exemplo, combine.sh contendo este comando:

$@ 2>&1

Em seguida, a saída de 'tempo' pode ser capturada da maneira correta:

combine.sh time sleep 1 &> /dev/null

(nenhuma saída é vista - correta)

Existe uma maneira de alcançar o que eu quero sem usar um script de combinação separado?

    
por Will Sheppard 03.07.2013 / 13:43

3 respostas

38

Esta questão é abordada em BashFAQ / 032 . No seu exemplo, você faria:

{ time sleep 1; } 2> /dev/null

A razão pela qual

time sleep 1 2>/dev/null

não se comporta como você está esperando é porque com essa sintaxe, você vai querer time o comando sleep 1 2>/dev/null (sim, o comando sleep 1 com stderr redirecionado para %código%). O /dev/null embutido funciona dessa maneira para tornar isso realmente possível.

O time builtin pode realmente fazer isso porque ... bem, é um embutido. Tal comportamento seria impossível com o comando externo bash geralmente localizado em time . De fato:

$ /usr/bin/time sleep 1 2>/dev/null
$

Agora, a resposta para sua pergunta

Why does the output of some linux programs go to neither STDOUT nor STDERR?

é: o resultado é stdout ou stderr .

Espero que isso ajude!

    
por 03.07.2013 / 13:48
13

Sua pergunta específica sobre time builtin foi respondida, mas são alguns comandos que não escrevem para stdout ou para stderr . Um exemplo clássico é o comando Unix crypt . crypt sem argumentos criptografa a entrada padrão stdin e a grava na saída padrão stdout . Ele solicita ao usuário uma senha usando getpass() , que por padrão exibe um prompt codificar%. /dev/tty é o dispositivo de terminal atual. Escrevendo para /dev/tty tem o efeito de gravar no terminal atual (se houver um, veja /dev/tty ).

O motivo isatty() não pode gravar em crypt porque grava a saída criptografada em stdout . Além disso, é melhor solicitar a stdout em vez de gravar em /dev/tty , para que, se um usuário redirecionar stderr e stdout , o prompt ainda seja visto. (Pela mesma razão, stderr não pode ler a senha de crypt , pois está sendo usada para ler os dados para criptografar.)

    
por 03.07.2013 / 17:56
-1

O problema no seu caso é que o redirecionamento funciona de outra maneira. Você escreveu

time sleep 1 2>&1 > /dev/null

Isso redireciona a saída padrão para /dev/null e, em seguida, redireciona o erro padrão para a saída padrão.

Para redirecionar todas as saídas que você precisa escrever

time sleep 1 > /dev/null 2>&1 

Em seguida, o erro padrão será redirecionado para a saída padrão e, depois disso, toda a saída padrão (contendo o erro padrão) será redirecionada para /dev/null .

    
por 03.07.2013 / 13:56