Para descobrir quanto tempo levam certas operações em um script Bash (v4 +), eu gostaria de analisar a saída do time
comando "separadamente" e (em última análise) capturá-la em uma variável Bash ( let VARNAME=...
).
Agora, estou usando time -f '%e' ...
(ou melhor, command time -f '%e' ...
por causa do Bash interno), mas como já redirecionei a saída do comando executado, estou realmente perdido quanto à maneira como capturaria a saída do time
comando. Basicamente, o problema aqui é separar a saída da time
saída do (s) comando (s) executado (s).
O que eu quero é a funcionalidade de contar a quantidade de tempo em segundos (números inteiros) entre o início de um comando e sua conclusão. Não precisa ser o time
comando ou o respectivo built-in.
Editar: dadas as duas respostas úteis abaixo, eu queria acrescentar dois esclarecimentos.
- Eu não quero jogar fora a saída do comando executado, mas realmente não importa se ele termina em stdout ou stderr.
- Eu preferiria uma abordagem direta sobre uma indireta (ou seja, capturando a saída diretamente, em vez de armazená-la em arquivos intermediários).
A solução usando date
até agora chega perto do que eu quero.
fonte
fork()
,execvp()
ewait3()/wait4()
. Em última análise, é isso que tempo e amigos estão fazendo. Não conheço uma maneira simples de fazer isso no bash / perl sem redirecionar para um arquivo ou abordagem semelhante.Respostas:
Para obter a saída de
time
em um var, use o seguinte:Você também pode pedir apenas um tipo de horário, por exemplo, utime:
Para obter o tempo que você também pode usar
date +%s.%N
, faça isso antes e depois da execução e calcule o diff:fonte
DIFF=$((END-START))
, usando as expressões aritméticas. :) ... obrigado pela resposta. +1.%N
no código do binfalse), precisará debc
cálculos mais sofisticados.time (cmd) 2> something
trabalho de redirecionar a saída de tempo parafile
, não seja feito (conforme a documentação), não ocorre em outros shells ondetime
existe uma palavra-chave e pode ser considerado um bug . Eu não confiaria nele, pois pode não funcionar em versões futuras dobash
.No bash, a saída da
time
construção vai para o erro padrão e você pode redirecionar o erro padrão do pipeline que ele afeta. Então, vamos começar com um comando que grava seus streamas de saída e de erro:sh -c 'echo out; echo 1>&2 err'
. Para não misturar o fluxo de erros do comando com a saída detime
, podemos desviar temporariamente o fluxo de erros do comando para um descritor de arquivo diferente:Isso grava
out
em fd 1,err
em fd 3 e os tempos em fd 2:Seria mais agradável ter
err
no fd 2 e os tempos no fd 3, por isso, nós os trocamos, o que é complicado porque não há maneira direta de trocar dois descritores de arquivo:Isso mostra como você pode pós-processar a saída do comando, mas se desejar capturar a saída do comando e seus horários, precisará trabalhar mais. Usar um arquivo temporário é uma solução. De fato, é a única solução confiável se você precisar capturar o erro padrão do comando e sua saída padrão. Mas, caso contrário, você pode capturar toda a saída e aproveitar o fato de
time
ter um formato previsível (se você usartime -p
para obter o formato POSIX ou aTIMEFORMAT
variável específica do bash ).Se você se importa apenas com o tempo do relógio de parede, executar o
date
antes e o depois é uma solução simples (se um pouco mais imprecisa devido ao tempo extra gasto no carregamento do comando externo).fonte
Com o tempo, a saída do comando sai no stdout e o tempo sai no stderr. Então, para separá-los, você pode fazer:
Mas agora o tempo está em um arquivo. Eu não acho que o Bash é capaz de colocar o stderr em uma variável diretamente. Se você não se importa em redirecionar a saída do comando para algum lugar, você pode:
Quando você fizer isso, a saída do comando estará dentro
outputfile
e o tempo que levou para executar será$FOO
.fonte
time
escrevia para stderr, mas não sabia que ele mesclaria stdout e stderr do comando executado em seu stdout. Mas geralmente não há método direto (ou seja, sem arquivo intermediário)? +1.time
não mescla os comandosstdout
estderr
. A maneira como mostrei assumiu que você só precisava da saída stdout do comando. Comobash
apenas armazenará o que saistdout
, você precisará redirecionar. Caso você possa descartar com segurança o stderr do seu comando: o tempo sempre estará na última linha do stderr. Se você precisar dos dois fluxos de saída do comando, sugiro agrupá-lo em outro script.Se você está dentro
bash
(e nãosh
) e NÃO precisa de precisão de um segundo, pode pular a chamadadate
totalmente e fazê-lo sem gerar nenhum processo extra, sem ter que separar a saída combinada e sem ter que capturar e analisar a saída de qualquer comando:fonte
Para esse propósito, é provavelmente melhor usar
times
(quetime
) obash
qual imprime os tempos acumulados de usuário e sistema para o shell e para processos executados a partir do shell, por exemplo, use:Veja:
help -m times
para mais informações.fonte
Ao reunir todas as respostas anteriores, quando estiver no OSX
você pode fazer como
fonte
Instalar
/bin/time
(por exemplopacman -S time
)Então, em vez de erro ao tentar
-f
sinalizar:Você pode realmente usá-lo:
E obtenha o que deseja - tempo na variável (exemplo: usa
%e
para o tempo decorrido real, para outras opções, verifiqueman time
):fonte
/usr/bin/time
em muitos sistemastime
é um shell embutido no Bash (e presumivelmente em outros shells), mas enquanto o caminho para otime
executável estiverPATH
, podemos usarcommand time
para garantir que estamos executando o comando externo em oposição ao embutido.Assim como um aviso, ao trabalhar com as declarações acima e, especialmente, tendo em mente a resposta de Grzegorz. Fiquei surpreso ao ver no meu sistema Ubuntu 16.04 Xenial esses dois resultados:
Eu não tenho nenhum apelido definido e, portanto, não sei por que isso está acontecendo.
fonte
time
também é um shell interno.command
, se deseja garantir que está executando o builtin, usebuiltin
. Não há mágica aqui. Usehelp
para descobrir os comandos disponíveis outype <command>
para descobrir qual<command>
é o tipo (por exemplo, um interno, comando externo, função ou alias).command
comando. O que garante que é chamado / usr / bin / time. Isso significa que as duas instruções a seguir são compatíveis:$ command time -f %e sleep 4
e$ /usr/bin/time -f %e sleep
tente isso, ele executa um comando simples com argumentos e coloca as vezes $ real $ user $ sys e preserva o código de saída.
Ele também não bifurca subconjuntos ou atropela nenhuma variável, exceto o sistema do usuário real, e não interfere na execução do script.
por exemplo
note: apenas o comando simples não é um pipeline, cujos componentes são executados em uma subshell
Esta versão permite especificar como $ 1 o nome das variáveis que devem receber as 3 vezes:
por exemplo
e pode ser útil se acabar sendo chamado recursivamente, para evitar pisar nos tempos; mas então rus etc deve ser declarado local em seu uso.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
fonte