Чтобы выяснить, сколько времени занимают определенные операции в скрипте Bash (v4 +), я хотел бы проанализировать выходные данные time
команды «по отдельности» и (в конечном итоге) перехватить ее в переменной Bash ( let VARNAME=...
).
Теперь я использую time -f '%e' ...
(или, скорее, command time -f '%e' ...
из-за встроенного Bash), но так как я уже перенаправил вывод выполненной команды, я действительно потерян, чтобы узнать, как я собираюсь захватить вывод time
команды. В основном проблема здесь , чтобы отделить выход из time
от выхода выполненной команды (ов).
Что мне нужно, так это функциональность подсчета количества времени в секундах (целых числах) между началом команды и ее завершением. Это не обязательно должна быть time
команда или соответствующий встроенный элемент.
Изменить: учитывая два полезных ответа ниже, я хотел бы добавить два разъяснения.
- Я не хочу отбрасывать вывод выполненной команды, но на самом деле не имеет значения, окажется ли он на stdout или stderr.
- Я бы предпочел прямой подход, а не косвенный (т. Е. Перехватывать вывод напрямую, а не сохранять его в промежуточных файлах).
Решение, использующее date
до сих пор, подходит к тому, что я хочу.
источник
fork()
,execvp()
иwait3()/wait4()
. В конечном итоге это то, что время и друзья делают. Я не знаю простого способа сделать это в bash / perl без перенаправления в файл или подобного подхода.Ответы:
Чтобы получить выходные данные
time
в var, используйте следующее:Вы также можете просто запросить один тип времени, например, utime:
Чтобы получить время, которое вы также можете использовать
date +%s.%N
, возьмите его до и после выполнения и рассчитайте разницу:источник
DIFF=$((END-START))
, используя арифметические выражения. :) ... Спасибо за ответ. +1.%N
в коде binfalse), вам нужныbc
или более сложные вычисления.time (cmd) 2> something
работа по перенаправлению вывода синхронизации выполняетсяfile
, она не предназначена (согласно документации), не используется в других оболочках, гдеtime
есть ключевое слово, и может рассматриваться как ошибка . Я бы не стал полагаться на это, так как это может не сработать в будущих версияхbash
.В bash выходные данные
time
конструкции возвращаются к стандартной ошибке, и вы можете перенаправить стандартную ошибку конвейера, на которую она влияет. Итак , давайте начнем с командой , которая записывает его вывода и ошибок streamas:sh -c 'echo out; echo 1>&2 err'
. Чтобы не перепутать поток ошибок команды с выводом изtime
, мы можем временно перенаправить поток ошибок команды в другой файловый дескриптор:Это записывает
out
в fd 1,err
в fd 3 и время в fd 2:Было бы приятнее иметь
err
на fd 2 и время на fd 3, поэтому мы поменяем их местами, что обременительно, потому что нет прямого способа поменять местами два дескриптора файла:Это показывает, как вы можете постобработать выходные данные команды, но если вы хотите захватить как выходные данные команды, так и ее время, вам нужно работать усерднее. Использование временного файла является одним из решений. Фактически, это единственное надежное решение, если вам нужно зафиксировать как стандартную ошибку команды, так и ее стандартный вывод. Но в противном случае вы можете захватить весь вывод и использовать тот факт, что он
time
имеет предсказуемый формат (если вы используете,time -p
чтобы получить формат POSIX илиTIMEFORMAT
переменную, специфичную для bash ).Если вы заботитесь только о времени настенных часов, запуск
date
до и после является простым решением (если немного более неточным из-за дополнительного времени, потраченного на загрузку внешней команды).источник
Со временем выходные данные команды выводятся на стандартный вывод, а время - на стандартный вывод. Итак, чтобы разделить их, вы можете сделать:
Но сейчас время в файле. Я не думаю, что Bash может напрямую помещать stderr в переменную. Если вы не против перенаправить вывод команды куда-то, вы можете сделать:
Когда вы сделаете это, вывод команды будет включен,
outputfile
и время, необходимое для выполнения, будет$FOO
.источник
time
пишет в stderr, но я не знал, что он объединит stdout и stderr выполненной команды в свой stdout. Но вообще нет прямого метода (т.е. без промежуточного файла)? +1.time
не объединяет командыstdout
иstderr
. Способ, который я показал, предполагал, что вам нужен только вывод команды stdout. Так какbash
будет хранить только то, что выходитstdout
, вам придется перенаправить. В случае, если вы можете безопасно отбросить команду stderr: время всегда будет на последней строке stderr. Если вам нужны оба выходных потока вашей команды, я бы предложил обернуть их в другой скрипт.Если вы находитесь
bash
(и неsh
), и вам НЕ нужна точность менее секунды, вы можете полностью пропустить вызовdate
и сделать это, не вызывая дополнительных процессов, не разделяя объединенный вывод и не собирая и не анализируя вывод. из любых команд:источник
Для этой цели, вероятно, лучше использовать
times
(чемtime
), вbash
котором печатается накопленное пользовательское и системное время для оболочки и для процессов, запускаемых из оболочки, пример использования:Смотрите:
help -m times
для получения дополнительной информации.источник
Во все предыдущие ответы, когда в OSX
ты можешь делать как
источник
Установить
/bin/time
(напримерpacman -S time
)Так что вместо ошибки при попытке
-f
пометки:Вы можете фактически использовать это:
И получите то, что вы хотите - время в переменной (пример использует
%e
для реального времени, для проверки других параметровman time
):источник
/usr/bin/time
на многих системахtime
это оболочка, встроенная в Bash (и, вероятно, другие оболочки), но пока путь кtime
исполняемому файлу находится внутриPATH
, мы можем использовать ее,command time
чтобы убедиться, что мы запускаем внешнюю команду, а не встроенную.Так же, как хедз-ап, работая с приведенными выше утверждениями и особенно принимая во внимание ответ Гжегожа. Я был удивлен, увидев на моей системе Ubuntu 16.04 Xenial эти два результата:
У меня не установлены псевдонимы, и поэтому я не знаю, почему это происходит.
источник
time
также встроенная оболочка.command
, если вы хотите убедиться, что вы используете встроенную команду, используйтеbuiltin
. Здесь нет магии. Используетсяhelp
для определения доступных команд илиtype <command>
для определения типа<command>
(например, встроенная, внешняя команда, функция или псевдоним).command
команды. Что является фактом, гарантирует, что / usr / bin / time вызывается. Это означает, что следующие два утверждения совместимы:$ command time -f %e sleep 4
и$ /usr/bin/time -f %e sleep
попробуйте это, он запускает простую команду с аргументами и помещает времена $ real $ user $ sys и сохраняет код выхода.
Он также не разветвляет подоболочки и не вмешивается ни в какие переменные, кроме реального пользователя sys, и не мешает выполнению сценария.
например
примечание: это всего лишь простая команда, а не конвейер, компоненты которого запускаются в подоболочке
Эта версия позволяет указать в качестве $ 1 имя переменных, которые должны получить 3 раза:
например
и может быть полезно, если в конечном итоге он вызывается рекурсивно, чтобы не растоптать время; но тогда рус и т. д. должны быть объявлены локальными при их использовании.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
источник