Отримати час виконання програми в оболонці


407

Я хочу виконати щось у оболонці Linux за кількох різних умов і мати змогу вивести час виконання кожного виконання.

Я знаю, що можу написати сценарій perl або python, який би це зробив, але чи є спосіб це зробити в оболонці? (що буває баш)


2
Випадок для Windows: stackoverflow.com/questions/673523 / ...
n611x007

чи можна отримати Ticksподібний корпус Windows?
freeforall tousez

Відповіді:


534

Використовуйте вбудоване timeключове слово:

$ час допомоги

час: час [-p] PIPELINE
    Виконати PIPELINE та роздрукувати підсумок реального часу, час процесора користувача,
    і системний час процесора, витрачений на виконання PIPELINE після його завершення.
    Статус повернення - це стан повернення PIPELINE. Варіант `-p '
    друкує підсумок часу про дещо інший формат Для цього використовується
    значення змінної TIMEFORMAT як вихідного формату.

Приклад:

$ time sleep 2
реальні 0м2.009с
користувач 0m0.000s
sys 0m0.004s

1
Як це використовується в такій команді time -p i=x; while read line; do x=x; done < /path/to/file.txt? Це негайно повертає 0,00, якщо я не ставлю нічого до циклу while .. що дає?
natli

це погана версія "часу", bash buildin. де зовнішня команда 'time'?
Znik

6
@Znik, спробуйте / usr / bin / time
Марк Райкок

10
@natli: Хоча timeчас роботи конвеєра може бути таким, який є (в силу ключового слова Bash ), вам потрібно використовувати команду групи ( { ...; ...; }), щоб ввести кілька команд:time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }
mklement0

2
Щоб побачити всі версії часу, встановлені у вашій системі, ви можете скористатисяtype -a time
spinup

120

Ви можете отримати набагато більш детальну інформацію, ніж вбудований баш time(про який згадує Роберт Гембл), використовуючи час (1) . Зазвичай це так /usr/bin/time.

Примітка редактора. Щоб переконатися, що ви викликаєте зовнішню утиліту, time а не time ключове слово оболонки , викликайте її як /usr/bin/time.
time- це утиліта , призначена POSIX , але єдиний варіант, який потрібно підтримувати, - це -p.
Конкретні платформи реалізують конкретні, нестандартні розширення: -vпрацює з GNU «s timeутилітами, як показано нижче (питання позначений); реалізація BSD / macOS використовує -lдля отримання аналогічних результатів - див man 1 time.

Приклад багатослівного виведення:


$ /usr/bin/time -v sleep 1
       Command being timed: "sleep 1"
       User time (seconds): 0.00
       System time (seconds): 0.00
       Percent of CPU this job got: 1%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.05
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 0
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 210
       Voluntary context switches: 2
       Involuntary context switches: 1
       Swaps: 0
       File system inputs: 0
       File system outputs: 0
       Socket messages sent: 0
       Socket messages received: 0
       Signals delivered: 0
       Page size (bytes): 4096
       Exit status: 0


2
вам не трапилось би дізнатися, з якого пакета debian буде взятись? здається, не встановлюється за умовчанням
ʞɔıu

1
Я посилався на твій пост Роберт. Якщо ви не маєте на увазі запропоновану вами команду, це не bash вбудований?
grepsedawk

24
Дивно, але він встановлений з пакету під назвою "час".
Пол Томблін

2
Вихід з / usr / bin / time виглядає як "0,00user 0,00system 0: 02.00elapsed 0% CPU (0avgtext + 0avgdata 0maxresident) k 0inputs + 0outputs (0major + 172minor) defaultfault 0swaps"
Пол Томблін

4
@ Nick: "sudo apt-get time install time".
Роберт Гембл

79
#!/bin/bash
START=$(date +%s)
# do something
# start your script work here
ls -R /etc > /tmp/x
rm -f /tmp/x
# your logic ends here
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

14
Є набагато простіший спосіб. Bash автоматично обчислює спеціальну змінну $ SECONDS, тоді перерахунок на основі команди зовнішньої дати не потрібний. Змінна $ SECONDS зберігає, скільки секунд працює сценарій bash при запуску. Ця змінна має деяку особливу властивість. Див. Сторінку чоловіка: D
Znik

Я спробував і вище, і метод у коментарі. У 1-й я отримую помилку "незаконної змінної", а у 2-й я отримую "невстановлену змінну"
DrBwts

45

Для лінійного вимірювання дельти спробуйте gnomon .

Утиліта командного рядка, трохи схожа на ts moreutils, надає інформацію про часові позначки до стандартного виводу іншої команди. Корисно для тривалих процесів, де ви хочете отримати історичний запис того, що триває так довго.

Ви також можете використовувати --highта / або --mediumпараметри, щоб вказати поріг довжини в секундах, протягом якого gnomon виділить часову позначку червоним або жовтим кольором. І ви можете зробити ще кілька речей.

приклад


3
Великий наконечник, але тільки , щоб бути ясний: це корисно для лінії по лінії таймингов, але накладні витрати приймати такі дрібнозернисті тайминги значно збільшують загальний час.
mklement0

2
Дивовижна утиліта. Дякую за обмін
Kishan B

19

Якщо ви хочете більше точності, використання %Nз date(і використовувати bcдля відмінностей, тому що $(())обробляє тільки цілі числа).

Ось як це зробити:

start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)

printf "Execution time: %.6f seconds" $dur

Приклад:

start=$(date +%s.%N); \
  sleep 0.1s; \
  dur=$(echo "$(date +%s.%N) - $start" | bc); \
  printf "Execution time: %.6f seconds\n" $dur

Результат:

Execution time: 0.104623 seconds

15

Якщо ви маєте намір використати час для пізніше для обчислення, дізнайтеся, як використовувати -fопцію /usr/bin/timeдля виведення коду, який зберігає час. Ось який-небудь код, який я нещодавно використав, щоб зібрати та сортувати час виконання цілого класу програм студентів:

fmt="run { date = '$(date)', user = '$who', test = '$test', host = '$(hostname)', times = { user = %U, system = %S, elapsed = %e } }"
/usr/bin/time -f "$fmt" -o $timefile command args...

Пізніше я об'єднав усі $timefileфайли та передав вихід у інтерпретатор Lua . Ви можете зробити те ж саме з Python або bash або будь-яким улюбленим синтаксисом. Я люблю цю техніку.


Примітка: Повний шлях /usr/bin/timeнеобхідний, тому що хоч which timeвін скаже вам інакше, якщо ви просто запустите time, він запустить версію вашої оболонки, timeяка не приймає жодних аргументів.
Кевін Діс


13

Якщо вам потрібна точність до другої, ви можете використовувати вбудовану $SECONDSзмінну, яка рахує кількість секунд, що працює оболонка.

while true; do
    start=$SECONDS
    some_long_running_command
    duration=$(( SECONDS - start ))
    echo "This run took $duration seconds"
    if some_condition; then break; fi
done

10

Ви можете використовувати timeта передплатити () :

time (
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
)

Або в одній оболонці {}:

time {
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
}

Ви опублікували два однакові фрагменти коду. Ви, мабуть, мали на увазі там щось інше.
стасон

3
@StasBekman - це неправда, спочатку використовуючи (& )(новий контекст, підзаклад ) та інше з {& }( та сама оболонка, той же контекст)
Едуардо Куомо

Ага! Я дуже важко дивився на двох і не бачив різниці. Дякуємо, що пояснили, що {} vs ().
стасон

2

Шлях є

$ > g++ -lpthread perform.c -o per
$ > time ./per

вихід >>

real    0m0.014s
user    0m0.010s
sys     0m0.002s

Не потрібно використовувати -lphtreadабо -oтеги. Просто потрібно скористатися timeкомандою, яку прийнята відповідь пояснює краще.
Денніс

7
Це був приклад. Це мій perform.c має нитки, тому мені потрібна -lpthread, а для простої ідентичності - -o per.
Robel Sharma

0

Один, можливо, простий метод (який може не відповідати потребам різних користувачів) - це використання оболонки PROMPT.it - ​​це просте рішення, яке може бути корисним у деяких випадках. Ви можете використовувати функцію підказки bash, як у наведеному нижче прикладі:

експортувати PS1 = '[\ t \ u @ \ h] \ $' 

Наведена вище команда призведе до зміни підказки оболонки на:

[HH: MM: SS ім'я користувача @ ім'я хоста] $ 

Кожен раз, коли ви запускаєте команду (або натискаєте клавішу Enter), повертаючись до підказки оболонки, підказка відображатиме поточний час.

Примітки:
1) будьте уважні, що якщо ви чекали десь перед тим, як ввести наступну команду, то цей час потрібно врахувати, тобто час, який відображається в рядку оболонки, є часовою позначкою, коли відображався запит на оболонку, а не при введенні команди. деякі користувачі вирішили натиснути клавішу Enter, щоб отримати нове підказку з новою часовою позначкою, перш ніж вони будуть готові до наступної команди.
2) Існують інші доступні варіанти та модифікатори, які можна використовувати для зміни підказки bash, для отримання детальної інформації зверніться до (man bash).


Справа не в тому, коли програма виконується, а в тривалості виконання програми.
Джено Чен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.