Aby dowiedzieć się, jak długo trwają niektóre operacje w skrypcie Bash (v4 +), chciałbym przeanalizować dane wyjściowe time
polecenia „osobno” i (ostatecznie) przechwycić je w zmiennej Bash ( let VARNAME=...
).
Teraz używam time -f '%e' ...
(a raczej command time -f '%e' ...
ze względu na wbudowane Bash), ale ponieważ już przekierowałem dane wyjściowe wykonanego polecenia, jestem naprawdę zagubiony w kwestii sposobu przechwycenia wyniku time
polecenia. Zasadniczo problemem jest oddzielenie wyjście z time
z wyjścia wykonywanego polecenia (ów).
Potrzebuję funkcji zliczania czasu w sekundach (liczbach całkowitych) między uruchomieniem polecenia a jego zakończeniem. Nie musi to być time
polecenie ani odpowiednie wbudowane.
Edycja: biorąc pod uwagę dwie przydatne odpowiedzi poniżej, chciałem dodać dwa wyjaśnienia.
- Nie chcę wyrzucać danych wyjściowych wykonanego polecenia, ale tak naprawdę nie będzie miało znaczenia, czy zakończy się na stdout, czy stderr.
- Wolałbym podejście bezpośrednie niż pośrednie (tzn. Przechwytywanie danych wyjściowych w przeciwieństwie do przechowywania ich w plikach pośrednich).
Dotychczasowe rozwiązanie date
zbliża się do tego, czego chcę.
źródło
fork()
,execvp()
iwait3()/wait4()
. To jest właśnie czas i przyjaciele. Nie znam prostego sposobu na zrobienie tego w bash / perl bez przekierowywania do pliku lub podobnego podejścia.Odpowiedzi:
Aby uzyskać wyjście
time
zmiennej var, użyj:Możesz także poprosić o pojedynczy typ czasu, np. Utime:
Aby uzyskać czas, którego możesz użyć
date +%s.%N
, więc weź go przed i po wykonaniu i oblicz różnicę:źródło
DIFF=$((END-START))
, korzystając z wyrażeń arytmetycznych. :) ... Dziękuję za odpowiedź. +1.%N
w kodzie binfalse), potrzebujeszbc
albo bardziej wyszukanych obliczeń.time (cmd) 2> something
prace nad przekierowaniem wyjścia timingu dofile
, nie mają (zgodnie z dokumentacją), nie znajdują się w innych powłokach, w którychtime
znajduje się słowo kluczowe i mogą być uważane za błąd . Nie polegałbym na tym, ponieważ może nie działać w przyszłych wersjachbash
.W bashu wynik wyjściowy
time
konstrukcji przechodzi w błąd standardowy i można przekierować standardowy błąd potoku, na który wpływa. Więc zacznijmy od komendy, która pisze do swoich wyjściowych i błędów streamas:sh -c 'echo out; echo 1>&2 err'
. Aby nie pomieszać strumienia błędów polecenia z danymi wyjściowymitime
, możemy tymczasowo przekierować strumień błędów polecenia na inny deskryptor pliku:Zapisuje to
out
na fd 1,err
na fd 3, a czasy na fd 2:Przyjemniej byłoby mieć
err
na fd 2 i czasy na fd 3, więc zamieniamy je, co jest uciążliwe, ponieważ nie ma bezpośredniego sposobu na zamianę dwóch deskryptorów plików:To pokazuje, jak możesz przetworzyć dane wyjściowe polecenia, ale jeśli chcesz uchwycić zarówno wynik polecenia, jak i jego czasy, musisz ciężko pracować. Jednym z rozwiązań jest użycie pliku tymczasowego. W rzeczywistości jest to jedyne niezawodne rozwiązanie, jeśli chcesz uchwycić zarówno standardowy błąd polecenia, jak i standardowe wyjście. Ale w przeciwnym razie możesz uchwycić cały wynik i skorzystać z faktu, że
time
ma on przewidywalny format (jeśli używasz,time -p
aby uzyskać format POSIX lubTIMEFORMAT
zmienną specyficzną dla bash ).Jeśli zależy Ci tylko na czasie naściennym, bieganie
date
przed i po jest prostym rozwiązaniem (jeśli jest nieco bardziej nieprecyzyjne ze względu na dodatkowy czas spędzony na ładowaniu polecenia zewnętrznego).źródło
Z czasem wyjście komendy wychodzi na standardowe wyjście, a czas wychodzi na standardowe wyjście. Aby je rozdzielić, możesz:
Ale teraz czas jest w pliku. Nie sądzę, że Bash jest w stanie bezpośrednio wstawić stderr do zmiennej. Jeśli nie masz nic przeciwko przekierowaniu gdzieś polecenia, możesz:
Gdy to zrobisz, wyjście polecenia zostanie włączone i upłynie
outputfile
czas potrzebny do uruchomienia$FOO
.źródło
time
pisze do stderr, ale nie zdawałem sobie sprawy, że połączy stdout i stderr wykonanego polecenia z jego stdout. Ale generalnie nie ma bezpośredniej metody (tj. Bez pliku pośredniego)? +1.time
nie scala poleceństdout
istderr
. Sposób, w jaki pokazałem, zakładał, że potrzebujesz tylko wyjścia standardowego polecenia. Ponieważbash
będziesz przechowywać tylko to, co z niego wyjdziestdout
, musisz przekierować. W przypadku, gdy możesz bezpiecznie upuścić stderr polecenia: czas zawsze będzie na ostatniej linii stderr. Jeśli potrzebujesz obu strumieni wyjściowych polecenia, sugeruję zawinięcie go w inny skrypt.Jeśli jesteś w
bash
(i niesh
) i NIE potrzebujesz dokładności poniżej sekundy, możeszdate
całkowicie pominąć wywołanie i zrobić to bez tworzenia dodatkowych procesów, bez konieczności oddzielania połączonych danych wyjściowych i bez przechwytywania i analizowania danych wyjściowych z dowolnego polecenia:źródło
W tym celu prawdopodobnie lepiej jest użyć
times
(niżtime
), wbash
którym drukuje skumulowane czasy użytkownika i systemu dla powłoki i dla procesów uruchamianych z powłoki, na przykład:Zobacz:
help -m times
aby uzyskać więcej informacji.źródło
W łączeniu wszystkich poprzednich odpowiedzi w OSX
możesz zrobić jak
źródło
Zainstaluj
/bin/time
(np.pacman -S time
)Więc zamiast błędu przy próbie
-f
flagi:Możesz go właściwie użyć:
I uzyskaj to, czego chcesz - czas w zmiennej (przykład wykorzystuje
%e
dla rzeczywistego czasu, który upłynął, w celu sprawdzenia innych opcjiman time
):źródło
/usr/bin/time
na wielu systemachtime
jest powłoką wbudowaną w Bash (i przypuszczalnie inne powłoki), ale dopóki jest ścieżka dotime
pliku wykonywalnegoPATH
, możemy użyć,command time
aby upewnić się, że uruchamiamy zewnętrzne polecenie, a nie wbudowane.Tak samo, jak podczas pojedynku z powyższymi stwierdzeniami, szczególnie biorąc pod uwagę odpowiedź Grzegorza. Byłem zaskoczony, widząc na moim systemie Ubuntu 16.04 Xenial te dwa wyniki:
Nie mam ustawionych żadnych aliasów, więc nie wiem, dlaczego tak się dzieje.
źródło
time
jest także wbudowaną powłoką.command
, jeśli chcesz mieć pewność, że uruchomiłeś wbudowane, użyjbuiltin
. Tu nie ma magii. Użyj,help
aby dowiedzieć się, jakie są dostępne polecenia lubtype <command>
dowiedzieć się, jaki<command>
jest typ (np. Wbudowane, zewnętrzne polecenie, funkcja lub alias).command
polecenia. Jest to faktem, że wywoływane jest / usr / bin / time. Oznacza to, że następujące dwa stwierdzenia są kompatybilne:$ command time -f %e sleep 4
i$ /usr/bin/time -f %e sleep
spróbuj tego, uruchamia proste polecenie z argumentami i podaje czasy $ real $ user $ sys i zachowuje kod wyjścia.
Nie rozwidla również podpowłok ani nie depcze żadnych zmiennych poza prawdziwym systemem użytkownika i w żaden inny sposób nie zakłóca działania skryptu
na przykład
Uwaga: tylko proste polecenie nie jest potokiem, którego komponenty są uruchamiane w podpowłoce
Ta wersja pozwala określić jako 1 $ nazwę zmiennych, które powinny otrzymać 3 razy:
na przykład
i może być przydatny, jeśli zostanie wywołany rekurencyjnie, aby uniknąć deptania na czas; ale wtedy rus itp. należy uznać za lokalne w ich użyciu.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
źródło