Przekieruj wyjście polecenia w `time time`

11

Próbuję zmierzyć czas za pomocą:

/usr/bin/time myCommand

Ponieważ jednak /usr/bin/timepisze do stderr, jeśli myCommand również pisze do stderr, otrzymam więcej niż tylko dane wyjściowe czasu w strumieniu. Chcę zrobić, przekierować wszystkie dane wyjściowe myCommand do /dev/null, ale nadal zapisywać dane wyjściowe czasu do stderr. Korzystając z przykładu myCommand, który pisze do stderr ls /nofile, widzimy, że (oczywiście) nie ma żadnych danych wyjściowych z następującymi:

$ /usr/bin/time ls /nofile 2> /dev/null
$

Bez żadnego przekierowania widzimy zarówno dane wyjściowe z ls(do stderr), jak i dane wyjściowe z czasu (także do stderr):

$ /usr/bin/time ls /nofile
ls: cannot access /nofile: No such file or directory
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

To, czego chcę, to coś, co po prostu produkuje:

$ /usr/bin/time ls /nofile > RedirectThatImAskingFor
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Jakieś pomysły?

David Doria
źródło
Korzystam z polecenia time w pliku skryptu. Chcę wyjściowy czas w stdout zamiast stderr. jak mogę to zdobyć?
powiązane: stackoverflow.com/questions/13356628/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Odpowiedzi:

20

W ksh, bash i zsh, timejest słowem kluczowym, a nie wbudowanym. Przekierowania w tym samym wierszu dotyczą tylko polecenia czasowego, a nie samego wyjścia time.

$ time ls -d / /nofile >/dev/null 2>/dev/null

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

Aby przekierować dane wyjściowe z timesiebie w tych powłokach, musisz użyć dodatkowego poziomu grupowania.

{ time mycommand 2>&3; } 3>&2 2>mycommand.time

Jeśli używasz wersji GNU autonomicznego timenarzędzia, ma on -oopcję zapisu danych wyjściowych w timeinnym miejscu niż stderr. Możesz timenapisać do terminala:

/usr/bin/time -o /dev/tty mycommand >/dev/null 2>/dev/null

Jeśli chcesz zachować wyjściowy timebłąd przy standardowym błędzie, potrzebujesz dodatkowego poziomu tasowania deskryptorów plików.

/usr/bin/time -o /dev/fd/3 mycommand 3>&2 >/dev/null 2>/dev/null

Za pomocą dowolnego timenarzędzia można wywołać powłokę pośrednią, aby wykonać żądane przekierowania. Wywoływanie powłoki pośredniej w celu wykonania dodatkowych działań, takich jak cdprzekierowania itp., Jest dość powszechne - jest to rodzaj małych rzeczy, do których powłoki są przeznaczone.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'
Gilles „SO- przestań być zły”
źródło
Kilka następnych: 1) Co robi „exec” w twojej ostatniej sugestii? Wydaje się, że działa bez niego: / usr / bin / time sh -c 'exec ls / nofile &> ./ output.dat' 2) Jest „powłoką pośrednią”, taką samą jak „podpowłoka” (którą można uzyskać I myślisz używając nawiasów?). Próbowałem takich rzeczy jak / usr / bin / time (ls / nofile &> ./ output.dat) bezskutecznie. 3) Co to jest / dev / tty? Wiem, że tty0 to stdin, tty1 = stdout, tty2 = stderr, ale co z samym „tty”?
David Doria
4) Z opcją / dev / fd3 wydaje się, że mówisz, aby zapisać wynik -o na 3, a następnie przekierować 3 na 2, 1 na null i 2 na null. Czy nie powinno to również przesłać liczby 3 na zero, ponieważ przekierowania następują od lewej do prawej?
David Doria
1
@DavidDoria execzastępuje powłokę określonym programem zamiast uruchamiać ten program jako podproces. Niektóre powłoki wykonują tę optymalizację automatycznie, gdy polecenie jest ostatnim w skrypcie. „Pośrednia powłoka” oznacza po prostu: powłokę pomiędzy timei mycommand; nie jest związany z podpowłokami. /dev/ttyjest terminalem, na którym uruchomiona jest komenda (nie ma ona związku z /dev/ttyNUMfizycznymi konsolami; mylisz się z deskryptorami plików: stdin jest /dev/fd/0itp.).
Gilles 'SO - przestań być zły'
@DavidDoria Zmiana tego, do czego podłączony jest deskryptor pliku, odbywa się od lewej do prawej, co ma odwrotny skutek. Zobacz unix.stackexchange.com/questions/23964/… lub unix.stackexchange.com/questions/37660/order-of-redirections
Gilles 'SO- przestań być zły'
0
[artur@asus-ux21e ~]$ find /etc/pki/CA/private/
/etc/pki/CA/private/
find: ‘/etc/pki/CA/private/’: Permission denied
[artur@asus-ux21e ~]$ time (find /etc/pki/CA/private/ &> /dev/null)

real    0m0.006s
user    0m0.001s
sys 0m0.004s
Artur Szymczak
źródło
To nie jest ten sam „czas” (wierzę, że to bash). Pamiętaj, że nie przestrzega żadnych rozsądnych zasad przekierowywania? $ time &> / dev / null real 0m0.000s użytkownik 0m0.000s sys 0m0.000s
David Doria
1
Co powiesz na: / usr / bin / time -o time / usr / bin / find / etc / pki / CA / private / &> / dev / null; czas kota
Artur Szymczak
Tak, widziałem to, ale byłem bardziej ciekawy, jak to zrobić bez użycia wewnętrznego mechanizmu, takiego jak -o.
David Doria
@DavidDoria Co sprawia wrażenie, że timejest to alias bash? which timewyświetla się /usr/bin/timew CentOS 5.7.
Timothy Martin
type timepokaże ci:time is a shell keyword
Artur Szymczak