Por que a saída de alguns programas Linux não é STDOUT nem STDERR?
Na verdade, quero saber como capturar de forma confiável toda a saída do programa, independentemente do 'fluxo' que ele usa. O problema que tenho é que alguns programas parecem não permitir que sua saída seja 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 está usando o tempo e como posso canalizá-lo para um arquivo?
Uma maneira de contornar o problema é criar um script Bash , por exemplo, combine.sh
contendo este comando:
$@ 2>&1
Então a saída de 'time' pode ser capturada da maneira correta:
combine.sh time sleep 1 &> /dev/null
(nenhuma saída é vista - correta)
Existe uma maneira de conseguir o que eu quero sem usar um script combinado separado?
2>&1 > /dev/null
significa "2 agora vai para onde 1 vai (por exemplo, o terminal, por padrão), e então 1 agora vai para / dev / null (mas 2 ainda vai para o terminal!). use>/dev/null 2>&1
para dizer "1 vai agora para / dev / null, depois 2 vai para onde 1 vai (ou seja, também para / dev / null). Isso ainda não funcionará aqui, pois o 'tempo' interno não será redirecionado, mas é mais geralmente correto (por exemplo, funcionaria se você usar / usr / bin / time). Pense em "2> & 1" como copiar a "direção" de 1 para 2, e não como 2, indo para 1Respostas:
Esta pergunta é abordada no BashFAQ / 032 . No seu exemplo, você:
A razão porque
não se comporta como você espera, porque com essa sintaxe, você desejará
time
o comandosleep 1 2>/dev/null
(sim, o comandosleep 1
com stderr redirecionado para/dev/null
). O builtintime
funciona dessa maneira para tornar isso realmente possível.O
bash
builtin pode realmente fazer isso porque ... bem, é um builtin. Esse comportamento seria impossível com o comando externotime
geralmente localizado em/usr/bin
. De fato:Agora, a resposta para sua pergunta
é: sim, a saída vai para stdout ou stderr .
Espero que isto ajude!
fonte
exec 3>/some/file ; ls >&3 ;
)coproc
builtin. Mas não é o caso dotime
embutido.A sua questão particular sobre
time
builtin foi respondida, mas não são alguns comandos que não escrevem tanto parastdout
ou parastderr
. Um exemplo clássico é o comando Unixcrypt
.crypt
sem argumentos criptografa a entrada padrãostdin
e a grava na saída padrãostdout
. Ele solicita ao usuário uma senha usandogetpass()
, que por padrão gera um prompt para/dev/tty
./dev/tty
é o dispositivo terminal atual. Gravar em/dev/tty
tem o efeito de gravar no terminal atual (se houver um, consulteisatty()
).O motivo pelo qual
crypt
nãostdout
é possível gravar é porque ele grava a saída criptografadastdout
. Além disso, é melhor solicitar, em/dev/tty
vez de escrever, parastderr
que, se um usuário redirecionarstdout
estderr
, o prompt ainda seja visto. (Pelo mesmo motivo,crypt
não é possível ler a senhastdin
, pois está sendo usada para ler os dados para criptografar.)fonte
time sleep 1 > /dev/null 2>&1
# redireciona a saída "sleep" para nulo. Então, "time" grava sua própria saída, sem redirecionamento. É como "time (sleep 1 > /dev/null 2>&1)
".(time sleep 1) > /dev/null 2>&1
# executa "time sleep 1" e redireciona sua saída para null.[] s
fonte
O problema no seu caso é que o redirecionamento funciona de outra maneira. Você escreveu
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 toda a saída, você deve escrever
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
.fonte
time
. Veja minha resposta para algumas explicações.