Как перенаправить вывод команды времени в файл в Linux?

202

Небольшой вопрос о синхронизации программ в Linux: команда time позволяет измерить время выполнения программы:

[ed@lbox200 ~]$ time sleep 1

real    0m1.004s
user    0m0.000s
sys     0m0.004s

Который работает отлично. Но если я пытаюсь перенаправить вывод в файл, это не удается.

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

Я знаю, что есть другие реализации времени с опцией -o для записи файла, но мой вопрос касается команды без этих опций.

Какие-либо предложения ?

ed82
источник
3
Возможно, дубликат сценария bash записывает время выполнения в файл , и я далеко не убежден, что это первый такой вопрос.
Джонатан Леффлер
1
Это дубликат stackoverflow.com/questions/2408981/…
codeforester

Ответы:

267

Пытаться

{ time sleep 1 ; } 2> time.txt

который объединяет STDERR «времени» и вашу команду в time.txt

Или использовать

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

который помещает STDERR из «сна» в файл «sleep.stderr» и только STDERR из «времени» переходит в «time.txt»

январь
источник
2
Спасибо, что отвечает именно на мой вопрос. Если я правильно понял, результат команды времени можно получить из stderr?
ed82
8
Да, но вы должны поместить его в фигурные скобки, в противном случае перенаправление будет частью команды, которая timeоценивает.
января
5
@Daniel Вы всегда можете перенаправить внутренний вывод команды отдельно (т.е. {time sleep 1 2> sleepStdErr.txt;} 2> time.txt), и это даст вам только вывод времени. Я не уверен, есть ли способ получить это независимо друг от друга.
gms7777
10
Если вы хотите использовать время с чем-то вроде grep, считывающим с stdout, попробуйте { time sleep 1; } 2>&1 | grep real. Это отправляет stderr в stdout, который затем может прочитать grep.
clayzermk1
9
НЕ забывайте ';' символ перед закрытием '}', он НЕ будет работать без (я сделал, и ... удивляюсь, почему не работает :))
THESorcerer
38

Заверните timeи команду, которую вы рассчитываете в набор скобок.

Например, в следующий раз lsи записывает результат lsи результаты синхронизации в outfile:

$ (time ls) > outfile 2>&1

Или, если вы хотите отделить вывод команды от захваченного вывода из time:

$ (time ls) > ls_results 2> time_results
Сэмпсон-чен
источник
12
Здесь нет необходимости вводить подоболочку.
января
1
@ sampson-chen Это работает только потому, что ls ничего не пишет в stderr, верно? Как бы вы «отделили» вывод «time» от вывода команды, которая будет выполнена, если команда записывает как в stdout, так и в stderr?
Дэвид Дория
36

Просто. У timeутилиты GNU есть опция для этого.

Но вы должны убедиться, что вы не используете встроенную timeкоманду вашей оболочки , по крайней мере bashвстроенная не предоставляет эту опцию! Вот почему вам нужно указать полный путь к timeутилите:

/usr/bin/time -o time.txt sleep 1
cmaster - восстановить монику
источник
Вы также можете использовать не встроенный без указания полного пути: stackoverflow.com/questions/29540540/…
Ciro Santilli 4 冠状 病 六四 事件 法轮功
14

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

{ time your_command 2> command.err ; } 2> time.log

или

{ time your_command 2>1 ; } 2> time.log

Как видите, ошибки команды переходят в файл (поскольку stderrон используется для time).

К сожалению, вы не можете отправить его на другой дескриптор (например 3>&2), так как он больше не будет существовать вне{...}

Тем не менее, если вы можете использовать время GNU, просто делайте то, что сказал @Tim Ludwinski.

\time -o time.log command
отметка
источник
8

Поскольку вывод команды 'time' является выводом ошибки, перенаправьте его как стандартный вывод, чтобы сделать дальнейшую обработку более понятной.

{ time sleep 1; } 2>&1 |  cat > time.txt
Джейси Сюй
источник
6

Если вы используете время GNU вместо встроенного в bash, попробуйте

time -o outfile command

(Примечание: формат времени GNU немного отличается от встроенного в bash).

Тим Людвински
источник
1
Это спасибо. И вы можете использовать \time -o outfile command(с ``) для использования GNU вместо встроенного.
Марк
3
&>out time command >/dev/null

в твоем случае

&>out time sleep 1 >/dev/null

затем

cat out
alinsoar
источник
3
Элегантная идея, но приводит к тому, что оболочка не использует встроенную команду. Если у вас не установлен настоящий timeбинарный файл, он outбудет содержать что-то вроде bash: time: command not found.
scy
Кроме того, формат времени GNU отличается от встроенного в bash, что вызывает проблемы при автоматическом разборе.
Guss
3

Я закончил тем, что использовал:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Где "а" является добавлением
  • Где "o" обрабатывается именем файла для добавления к
  • Где "f" - формат с синтаксисом, похожим на printf
  • Где "% E" производит 0:00:00; часы: минуты: секунды
  • Мне пришлось вызвать / usr / bin / time, потому что bash "time" его растоптал и у него не было таких же опций
  • Я просто пытался получить вывод в файл, а не то же самое, что OP
Locane
источник
2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

Преимущество этого заключается в том, что не создаются субоболочки, и в конечном конвейере его stderr восстанавливается до реального stderr.

Адам Хит
источник
0

Если вы не хотите трогать stdout и stderr исходного процесса, вы можете перенаправить stderr в файловый дескриптор 3 и обратно:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

real    0m0.009s
user    0m0.004s
sys     0m0.000s

Вы можете использовать это для оболочки (например, для cronjobs) для мониторинга времени выполнения:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Тобиас Гёддерз
источник
0

Если вы используете, cshвы можете использовать:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

Например:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Лео Кардона
источник