Пытаемся разобрать (bash) команду времени - PullRequest
15 голосов
/ 14 октября 2010

Я изо всех сил пытаюсь проанализировать вывод команды времени в bash - и даже не дать ей распечатать вывод, когда я его вызываю.Это мой тестовый код:

#!/bin/bash
TIME=`time ls -lh > /dev/null`
echo "Testing..."
echo $TIME

В настоящее время он печатается:

{blank-line}
real    0m0.064s
user    0m0.002s
sys     0m0.005s
Testing
{blank-line}

Итак, похоже, что значение, присвоенное $TIME, является пустой строкой в ​​началераспечатка времени.Мне нужно получить значение секунд в строке sys, то есть «0.005».Я гарантированно, что у меня будут только секунды, поэтому мне не нужно ничего перед "m" - однако, часть секунд может быть в форме xx.xxx, если она идет> = 10 секунд.В настоящее время я не знаю, как подавить вывод 'time', захватить все вместо пустой строки и проанализировать, чтобы получить нужные мне значения.

Любая помощь будет принята с благодарностью ...

Ответы [ 5 ]

18 голосов
/ 14 октября 2010

Если вы используете встроенную функцию Bash time, вы можете управлять ее выводом, установив переменную TIMEFORMAT:

TIMEFORMAT=%R

, и вам не придется выполнять какой-либо анализ, поскольку это приведет к time только для вывода количества секунд.

и использования этого:

echo "Testing..."
TIME=$( { time ls -lh > /dev/null; } 2>&1 )
echo $TIME

или одного из других методов из BashFAQ / 032 .

7 голосов
/ 14 октября 2010

Прежде всего, данные, которые вы пытаетесь захватить, записываются со стандартной ошибкой. Но захват этого вывода довольно сложен в этом случае.

time является одновременно исполняемым (в /usr/bin), а также встроенной командой оболочки в bash и других оболочках. Когда вы выполняете time без указания /usr/bin/time, вы выполняете встроенную команду в bash. Это затрудняет работу с выводом, поскольку bash не рассматривает его как обычную программу; это специальная встроенная функция, написанная bash.

Зная это, и глядя на справочную страницу для time(1), я вижу, что данные, которые вы пытаетесь захватить с time, выводятся в stderr. Так что мой обходной путь для этого заключается в прямом выполнении /usr/bin/time следующим образом:

TIME=`/usr/bin/time ls -lh 2>&1 >/dev/null`

Копирует стандартный поток ошибок в стандартный вывод, а затем перенаправляет то, что обычно идет в стандартный вывод, в /dev/null. Стандартная ошибка, тем не менее, все равно будет преобразована в стандартную, поскольку она была продублирована до перенаправления. Обратный порядок этих не будет работать. (Да, это сбивает с толку.)

К сожалению, /usr/bin/time немного менее точен в выводе:

    0.00 real         0.00 user         0.00 sys
<ч />

В качестве альтернативы, вы можете использовать 2 подоболочки следующим образом:

TIME=$((time ls -lh >/dev/null) 2>&1)

Это переписало бы то, что записано в стандартную ошибку на втором подоболочке внутри первого, что позволит вам захватить вывод. См. http://www.tldp.org/LDP/abs/html/subshells.html для получения дополнительной информации о подоболочках.

2 голосов
/ 28 мая 2014

Хотя решения основаны на одной и той же логике, но все же я не смог найти в списке следующее, поэтому другая версия решения:

TIME=$(time (ls -lh >/dev/null) 2>&1)
1 голос
/ 14 октября 2010

Команда time выводит информацию о синхронизации в STDERR, которую вы не захватываете или не перенаправляете.Таким образом, во время назначения эта информация выводится на вашу консоль, а переменная $TIME получает STDOUT команды - которую вы перенаправили на /dev/null, поэтому она пуста.

Возможно, вам следует попытаться перехватить STDERR команды?

0 голосов
/ 04 июня 2013

Я хотел опубликовать это как комментарий, но это было бы слишком долго. Я хотел представить другой немного другой способ получения данных.

Вы можете использовать две вложенные оболочки, чтобы получить вывод времени в виде потока, используя /bin/sh вместо /usr/bin/time для получения времени выполнения. Я полагаю, вы можете заменить time здесь на /usr/bin/time.

$ ((time ./print_test.sh > deleteme) 2>&1) > deletemetime

$ cat deleteme
test

$ cat deletemetime
./print_test.sh > deleteme  0.00s user 0.00s system 86% cpu 0.003 total

$ ((time ./print_test.sh > deleteme) 2>&1) | sed 's/system/kernel/'
./print_test.sh > deleteme  0.00s user 0.00s kernel 86% cpu 0.003 total

Обратите внимание, что, как представляется, существует разница в способе получения результата. Иногда это в этом формате, а иногда в этом формате:

real    0m0.420s
user    0m0.385s
sys     0m0.040s

Не уверен, на данный момент, что определяет так или иначе.

Конечно, вы можете использовать, например,

TIMEFORMAT='%3R' 

чтобы исправить формат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...