Redirecione a saída de um comando no comando `time`


11

Estou tentando cronometrar algo usando:

/usr/bin/time myCommand

No entanto, como /usr/bin/timeescreve no stderr, se o myCommand também grava no stderr, receberei mais do que apenas a saída do tempo no fluxo. O que eu quero fazer é redirecionar toda a saída do myCommand para /dev/null, mas ainda gravar a saída do tempo no stderr. Usando um exemplo myCommand que grava no stderr of ls /nofile, vemos que (obviamente) não há saída alguma com o seguinte:

$ /usr/bin/time ls /nofile 2> /dev/null
$

Sem nenhum redirecionamento, vemos a saída de ls(para stderr) e a saída de tempo (também para stderr):

$ /usr/bin/time ls /nofile
ls: cannot access /nofile: No such file or directory
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

O que eu quero é algo que simplesmente produz:

$ /usr/bin/time ls /nofile > RedirectThatImAskingFor
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Alguma ideia?


Estou usando o comando time no arquivo de script. Eu quero tempo de saída em stdout em vez de stderr. como posso conseguir isso?

Respostas:


20

No ksh, bash e zsh, timeé uma palavra-chave, não um builtin. Os redirecionamentos na mesma linha aplicam-se apenas ao comando que está sendo cronometrado, não à saída em timesi.

$ time ls -d / /nofile >/dev/null 2>/dev/null

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

Para redirecionar a saída de timesi mesma nesses shells, você precisa usar um nível adicional de agrupamento.

{ time mycommand 2>&3; } 3>&2 2>mycommand.time

Se você usar a versão GNU do timeutilitário independente , ele terá a -oopção de gravar a saída de timeoutro local que não o stderr. Você pode timeescrever no terminal:

/usr/bin/time -o /dev/tty mycommand >/dev/null 2>/dev/null

Se você deseja manter a saída timecom erro padrão, é necessário um nível extra de embaralhamento do descritor de arquivo.

/usr/bin/time -o /dev/fd/3 mycommand 3>&2 >/dev/null 2>/dev/null

Com qualquer timeutilitário, você pode chamar um shell intermediário para executar os redirecionamentos desejados. Invocar um shell intermediário para executar ações extras como cdredirecionamentos etc. é bastante comum - é o tipo de pequenas coisas que os shells são projetados para fazer.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'

Alguns acompanhamentos: 1) O que o 'exec' em sua última sugestão faz? Parece funcionar sem ele: / usr / bin / time sh -c 'exec ls / nofile &> ./ output.dat' 2) É um "shell intermediário" o mesmo que um "subshell" (que você obteria pense usando parênteses?). Eu estava tentando coisas como / usr / bin / time (ls / nofile &> ./ output.dat) sem sucesso. 3) O que é / dev / tty? Eu sei que tty0 é stdin, tty1 = stdout, tty2 = stderr, mas e apenas 'tty'?
David Doria

4) Com a opção / dev / fd3, parece que você está dizendo para gravar a saída -o em 3 e depois redirecionar 3 para 2, 1 para nulo e 2 para nulo. Isso não deveria enviar 3 para null também porque os redirecionamentos acontecem da esquerda para a direita?
David Doria

1
@DavidDoria execsubstitui o shell pelo programa especificado em vez de executá-lo como um subprocesso. Alguns shells executam essa otimização automaticamente quando um comando é o último em um script. "Shell intermediário" significa exatamente isso: um shell que está entre timee mycommand; não está relacionado a subcascas. /dev/ttyé o terminal em que o comando está sendo executado (não tem relação com /dev/ttyNUMos consoles físicos; você está confuso com os descritores de arquivo: stdin is /dev/fd/0, etc).
Gilles 'SO- stop be evil'

@DavidDoria Alterar o que um descritor de arquivo está conectado acontece da esquerda para a direita, o que tem o efeito oposto. Veja unix.stackexchange.com/questions/23964/… ou unix.stackexchange.com/questions/37660/order-of-redirections
Gilles 'SO- deixa de ser mau'

0
[artur@asus-ux21e ~]$ find /etc/pki/CA/private/
/etc/pki/CA/private/
find: ‘/etc/pki/CA/private/’: Permission denied
[artur@asus-ux21e ~]$ time (find /etc/pki/CA/private/ &> /dev/null)

real    0m0.006s
user    0m0.001s
sys 0m0.004s

Esse não é o mesmo 'tempo' (é um pseudônimo de bash, acredito). Observe que ele não segue nenhuma regra de redirecionamento sensato? $ time &> / dev / null real 0m0.000s usuário 0m0.000s sys 0m0.000s
David Doria

1
Que tal isso: / usr / bin / time -o time / usr / bin / find / etc / pki / CA / private / &> / dev / null; hora do gato
Artur Szymczak

Sim, eu já vi isso, mas fiquei mais curioso sobre como fazer isso sem usar um mecanismo interno como -o.
22414 David Doria

@DavidDoria O que está lhe dando a impressão de que timeé um alias do bash? which timeé exibido /usr/bin/timeno CentOS 5.7.
Timóteo Martin

type timeirá mostrar-lhe:time is a shell keyword
Artur Szymczak 23/04
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.