No bash, a saída da construção time
vai para o erro padrão e você pode redirecionar o erro padrão do pipeline que ela afeta. Então, vamos começar com um comando que grava seus streamas de saída e erro: sh -c 'echo out; echo 1>&2 err'
. Para não misturar o fluxo de erros do comando com a saída de time
, podemos desviar temporariamente o fluxo de erros do comando para um descritor de arquivo diferente:
{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; }
Isto escreve out
para fd 1, err
para fd 3 e os tempos para fd 2:
{ time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } \
3> >(sed 's/^/ERR:/') 2> >(sed 's/^/TIME:/') > >(sed 's/^/OUT:/')
Seria mais agradável ter err
no fd 2 e os tempos no fd 3, então nós os trocamos, o que é complicado porque não há nenhum modo direto de trocar dois descritores de arquivos:
{ { { time -p sh -c 'echo out; echo 1>&2 err' 2>&3; } 3>&2 2>&4; } 4>&3; } 3> >(sed 's/^/TIME:/') 2> >(sed 's/^/ERR:/') > >(sed 's/^/OUT:/')
Isso mostra como você pode pós-processar a saída do comando, mas se você quiser capturar a saída do comando e seus horários, precisará trabalhar mais. Usando um arquivo temporário é uma solução. Na verdade, é a única solução confiável se você precisar capturar o erro padrão do comando e sua saída padrão. Caso contrário, você pode capturar toda a saída e aproveitar o fato de que time
tem um formato previsível (se você usa time -p
para obter o formato POSIX ou a variável TIMEFORMAT
específica do bash).
nl=$'\n'
output=$(TIMEFORMAT='%R %U %S %P'; mycommand)
set ${output##*$nl}; real_time=$1 user_time=$2 system_time=$3 cpu_percent=$4
output=${output%$nl*}
Se você se importa apenas com o relógio de parede, executar date
antes e depois é uma solução simples (se for um pouco mais imprecisa devido ao tempo extra gasto carregando o comando externo).