Jak przekierować wyjście polecenia time do pliku w systemie Linux?

202

Małe pytanie dotyczące programów czasowych w systemie Linux: komenda time pozwala zmierzyć czas wykonywania programu:

[ed@lbox200 ~]$ time sleep 1

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

Które działa dobrze. Ale jeśli spróbuję przekierować dane wyjściowe do pliku, nie powiedzie się.

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

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

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

Wiem, że istnieją inne implementacje czasu z opcją -o do napisania pliku, ale moje pytanie dotyczy polecenia bez tych opcji.

Jakieś sugestie ?

ed82
źródło
3
Możliwe duplikowanie czasu wykonywania skryptu bash w pliku i nie jestem przekonany, że to pierwsze takie pytanie.
Jonathan Leffler
1
To jest duplikat stackoverflow.com/questions/2408981/...
codeforester

Odpowiedzi:

266

Próbować

{ time sleep 1 ; } 2> time.txt

który łączy STDERR „time” i twoje polecenie w time.txt

Albo użyj

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

który wstawia STDERR z „sleep” do pliku „sleep.stderr” i tylko STDERR z „time” przechodzi do „time.txt”

styczeń
źródło
2
Dzięki, to odpowiada dokładnie na moje pytanie. Jeśli poprawnie zrozumiałem, wynik polecenia czasowego można uzyskać ze stderr?
ed82
7
Tak, ale musisz umieścić go w nawiasach klamrowych, w przeciwnym razie przekierowanie będzie częścią polecenia, które timeocenia.
styczeń
5
@Daniel Zawsze możesz przekierować wewnętrzne wyjście komendy osobno (tj. {Time sleep 1 2> sleepStdErr.txt;} 2> time.txt), a to da ci tylko wynik czasu. Nie jestem pewien, czy istnieje sposób, aby uzyskać go niezależnie.
gms7777
10
Jeśli chcesz użyć czasu z czymś takim jak grep, który odczytuje standardowe wyjście, spróbuj { time sleep 1; } 2>&1 | grep real. To wysyła stderr do stdout, który grep może następnie odczytać.
clayzermk1
9
nie zapomnij o „;” znak przed zamknięciem „}”, NIE zadziała bez (ja to zrobiłem i ... zastanawiam się, dlaczego nie działa :))
THESorcerer
38

Zawiń timei polecenie, które mierzysz w zestawie nawiasów.

Na przykład następujące czasy lsi zapisuje wynik lsi wyniki pomiaru czasu w outfile:

$ (time ls) > outfile 2>&1

Lub jeśli chcesz oddzielić dane wyjściowe polecenia od przechwyconego wyniku od time:

$ (time ls) > ls_results 2> time_results
sampson-chen
źródło
12
Nie ma potrzeby wprowadzania tutaj podpowłoki.
stycznia
1
@ sampson-chen To działa tylko dlatego, że ls nic nie pisze do stderr, prawda? Jak „oddzieliłbyś” wyjście „czasu” od wyniku polecenia, które ma zostać uruchomione, jeśli polecenie zapisuje zarówno na standardowe wyjście, jak i standardowe?
David Doria
36

Prosty. Narzędzie GNU timema taką opcję.

Ale musisz upewnić się, że nie używasz wbudowanego timepolecenia powłoki , przynajmniej bashwbudowane nie zapewnia tej opcji! Dlatego musisz podać pełną ścieżkę timenarzędzia:

/usr/bin/time -o time.txt sleep 1
cmaster - przywróć monikę
źródło
Możesz także użyć tego, co nie jest wbudowane, bez określania pełnej ścieżki: stackoverflow.com/questions/29540540/...
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
14

Jeśli zależy Ci na wyjściu błędu polecenia, możesz je oddzielić w ten sposób, wciąż korzystając z wbudowanego polecenia time.

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

lub

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

Jak widzisz, błędy polecenia idą do pliku (ponieważ stderrjest używany do time).

Niestety nie możesz wysłać go do innego uchwytu (takiego jak 3>&2), ponieważ nie będzie on już istniał poza{...}

To powiedziawszy, jeśli możesz wykorzystać czas GNU, po prostu rób to, co powiedział @Tim Ludwinski.

\time -o time.log command
znak
źródło
8

Ponieważ wyjście polecenia „czas” jest wyjściem błędu, przekieruj je, ponieważ wyjście standardowe byłoby bardziej intuicyjne w celu dalszego przetwarzania.

{ time sleep 1; } 2>&1 |  cat > time.txt
jaycee xu
źródło
6

Jeśli używasz czasu GNU zamiast wbudowanego bash, spróbuj

time -o outfile command

(Uwaga: czas GNU formatuje się trochę inaczej niż wbudowany bash).

Tim Ludwinski
źródło
1
Dziękuję I możesz używać \time -o outfile command(z ``) do używania GNU zamiast wbudowanego.
Mark
3
&>out time command >/dev/null

w Twoim przypadku

&>out time sleep 1 >/dev/null

następnie

cat out
Alinsoar
źródło
3
Elegancki pomysł, ale prowadzi do tego, że powłoka nie używa wbudowanego polecenia. Jeśli nie masz timezainstalowanego prawdziwego pliku binarnego, outbędzie zawierał coś takiego bash: time: command not found.
scy
Również format czasu GNU nie jest taki sam jak wbudowany bash, co powoduje problemy z automatycznym parsowaniem.
Guss,
3

Skończyło się na tym, że:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Gdzie jest dołączane „a”
  • Gdzie „o” jest poprzedzone nazwą pliku, do którego należy dołączyć
  • Gdzie „f” jest formatem o składni podobnej do printf
  • Gdzie „% E” wytwarza 0:00:00; godziny: minuty: sekundy
  • Musiałem wywołać / usr / bin / time, ponieważ „czas” bash był zdeptany i nie ma tych samych opcji
  • Właśnie próbowałem uzyskać wyjście do pliku, a nie to samo, co OP
Locane
źródło
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

Ma to tę zaletę, że nie spawnuje pocisków podrzędnych, a końcowy potok ma przywrócenie stderr do prawdziwego stderr.

Adam Heath
źródło
0

Jeśli nie chcesz dotykać stdout i stderr pierwotnego procesu, możesz przekierować stderr do deskryptora pliku 3 i odwrotnie:

$ { 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

Możesz użyć tego dla opakowania (np. Dla cronjobs) do monitorowania środowisk wykonawczych:

#!/bin/bash

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

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Tobias Gödderz
źródło
0

Jeśli używasz csh, możesz użyć:

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

Na przykład:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Leo Cardona
źródło