Zapisz wynik „time” w pliku, dlaczego nawiasy są potrzebne?

18

timepisze do stderr, więc można by założyć, że dodanie 2>&1do wiersza poleceń powinno kierować jego wynik stdout. Ale to nie działa:

test@debian:~$ cat file 
one two three four
test@debian:~$ time wc file > wc.out 2>&1

real    0m0.022s
user    0m0.000s
sys     0m0.000s
test@debian:~$ cat wc.out 
 1  4 19 file

Działa tylko z nawiasami:

test@debian:~$ (time wc file) > wc.out 2>&1
test@debian:~$ cat wc.out 
 1  4 19 file

real    0m0.005s
user    0m0.000s
sys     0m0.000s

Dlaczego w tym przypadku potrzebne są nawiasy? Dlaczego nie jest time wcinterpretowane jako jedno polecenie?

wilko-rewo-koty
źródło
3
Zauważ, że wyniki będą się różnić w zależności od tego, czy timejest słowem kluczowym powłoki, czy /usr/bin/time. Może być tu zaangażowanych kilka zestawów deskryptorów (powłoki i tych dołączonych do timeprocesu). I nie zapominajmy o tych sugerowanych przez ()podpowłokę. ( czekając na specjalistę od bash : p)
John WH Smith

Odpowiedzi:

24

W ksh, basha zsh, timenie jest poleceniem (wbudowane lub nie), to słowo zarezerwowane w języku podobnego forlub while.

Służy do pomiaru czasu potoku 1 .

W:

time for i in 1 2; do cmd1 "$i"; done | cmd2 > redir

Masz specjalną składnię, która każe powłoce uruchomić tę linię potoku:

for i in 1 2; do cmd1 "$i"; done | cmd2 > redir

I zgłoś dla niego statystyki czasowe.

W:

time cmd > output 2> error

To ten sam, jesteś rozrządu na cmd > output 2> errorkomendę, a statystyki czasowe nadal iść na stderr przez powłokę.

Potrzebujesz:

{ time cmd > output 2> error; } 2> timing-output

Lub:

exec 3>&2 2> timing-output
time cmd > output 2> error 3>&-
exec 2>&3 3>&-

Aby stderr powłoki został przekierowany, timing-outputzanim zostanie użyta konstrukcja czasu (ponownie, nie polecenie ) (tutaj do czasu cmd > output 2> error 3>&-).

Możesz także uruchomić tę timekonstrukcję w podpowłoce , której przekierowanie stderr:

(time cmd > output 2> error) 2> timing-output

Ale ta podpowłoka nie jest tutaj potrzebna, wystarczy stderr, aby zostać przekierowanym w momencie timewywołania konstrukcji.

Większość systemów ma także timepolecenia. Możesz je wywołać, wyłączając timesłowo kluczowe. Wszystko, co musisz zrobić, to jakoś zacytować to słowo kluczowe, ponieważ słowa kluczowe są rozpoznawane jako takie tylko w dosłownym znaczeniu.

'time' cmd > output 2> error-and-timing-output

Ale uwaga, format może być inny, a stderr obu timei cmdzostanie połączony error-and-timing-output.

Ponadto timepolecenie, w przeciwieństwie do timekonstrukcji, nie może mierzyć czasu potoków lub poleceń złożonych, funkcji lub wbudowanych powłok ...

Gdyby było to polecenie wbudowane, mogłoby ono być w stanie określić czas wywołań funkcji lub poleceń wbudowanych, ale nie byłoby w stanie określić czasu przekierowań, potoków ani poleceń złożonych.


1 Zauważ, że bashma (co można uznać za) błąd, przez który time (cmd) 2> file(ale nie time cmd | (cmd2) 2> filena przykład) przekierowuje wyjście taktowania dofile

Stéphane Chazelas
źródło
Cóż, często podkreślam, że pamiętam, że timeto słowo kluczowe, a nie wbudowana powłoka.
cuonglm,
Dzięki za wskazówkę dotyczącą korzystania 'time'z pliku wykonywalnego - wygodniejszego niż pisanie /usr/bin/time(a nawet command time:-)).
Alexis
@alexis również \time.
ctrl-alt-delor
7

Nie ma polecenia o nazwie time wc, timei wcsą oddzielone słowo w skorupkach.

Teraz często występują dwa osobne programy o nazwie time, jeden to słowo kluczowe powłoki, drugi to polecenie zewnętrzne . W powłokach, które timesą słowem kluczowym powłoki, podczas pisania time wc ..., powłoka używała swojego słowa kluczowego timezamiast zewnętrznego narzędzia czasu .

Kiedy powłoka używa timesłowa kluczowego, nie musi rozwidlać () nowego procesu, aktualny timestandard i standardowy błąd nie są zmieniane. Część przekierowania w:

time wc file > wc.out 2>&1

dotyczy wctylko.

Gdy używasz polecenia złożonego(list) :

(time wc file) > wc.out 2>&1

powłoka działała time wc filew podpowłoce, (time wc file)została uznana za pojedyncze polecenie, a część przekierowania wpływa na jej standardowe wyjście i standardowy błąd, które teraz obejmują zarówno timei wc.


Możesz uzyskać ten sam efekt bez kosztów tworzenia nowego procesu, używając innej formy polecenia grupowania {list;}:

{time wc file;} > wc.out 2>&1

Jeśli używasz zewnętrznego time, nie napotykasz tego problemu, ponieważ został uruchomiony w nowym procesie:

/usr/bin/time wc file > wc.out 2>&1
Cuonglm
źródło
Czy jest jakaś praktyczna różnica między używaniem timea /usr/bin/time? Czy pliki wykonywalne są wywoływane funkcjonalnie tak samo?
Hashim
2

Ponieważ timewykonywane jest wbudowane bash. Bash przetwarza to w specjalny sposób.

Jeśli użyjesz prawdziwego timepliku binarnego, będzie on działał dokładnie tak, jak tego oczekujesz:

/usr/bin/time wc file > wc.out 2>&1

Chociaż wynik tego czasu jest nieco inny:

 $ /usr/bin/time wc file > wc.out 
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata1900maxresident)k
0inputs+8outputs (0major+82minor)pagefaults 0swaps
wysypka
źródło
9
Gdyby to było wbudowane, nie byłoby problemu. Problem polega na tym, że jest to słowo kluczowe w języku. time cmd > outputrazy cmd > outputpolecenie i time foo | barczasy foo | bar.
Stéphane Chazelas,
1

To nie jest tak, timeże zapisuje informacje o czasie. Wbudowane timepowoduje, że powłoka zapisuje to po zakończeniu polecenia. Ale przekierowanie wpływa tylko na polecenie.

W (time ...)przypadku, gdy przekierowanie jest stosowane do całej podpowłoki.

Hauke ​​Laging
źródło
0

Ponieważ czas jest wbudowany w powłokę, zapisuje do stderr powłoki , a nie do stderr polecenia.

Użycie nawiasów powoduje, że całe polecenie staje się powłoką potomną, której stderr można przekierować.

użycie nawiasów klamrowych daje podobny wynik bez faktycznego uruchamiania podpowłoki

  { time who ; } > /tmp/timwho >& /tmp/xx 

(tak, potrzebujesz średnika)

darkonc
źródło