Chtěl bych zobrazit čas dokončení skriptu.
To, co v současné době dělám, je –
#!/bin/bash date ## echo the date at start # the script contents date ## echo the date at end
Toto jen ukazuje čas začátku a konce skriptu. je možné zobrazit jemně zrnitý výstup, jako je čas procesoru / čas io atd.?
Komentáře
- stackoverflow.com/questions/385408/ …
- Myslím si, že aktuální přijatá odpověď není dostačující kvůli časovým výkyvům.
- @CiroSantilli 烏坎 事件 2016 六四 事件 法轮功 Myslím, že vámi navrhované vlákno stále není dostačující k odstranění vlivu časových událostí.
- Související také: stackoverflow.com/questions/5152858/… nebo něco unix.stackexchange.com/questions/334145 / …
- Existuje příkaz, který můžete spustit, a poté automaticky načasuje všechny unixové příkazy, zapomněli jste, jak je povolit?
Odpověď
Jus Při volání skriptu nepoužívejte time
:
time yourscript.sh
Komentáře
- Toto se zobrazí třikrát:
real
,user
asys
. Jejich význam najdete zde . - a “ real “ je pravděpodobně to, co lidé chtějí vědět – “ reálný je čas nástěnných hodin – čas od začátku do konce hovoru “
- Existuje způsob, jak zachytit standardní výstup do souboru? Například něco jako
time $( ... ) >> out.txt
- Můžete to udělat i se sekvencemi příkazů na příkazovém řádku, např .:
time (command1 && command2)
- Nebo by mohl ve svém skriptu jednoduše udělat: echo $ SECONDS za předpokladu, že je to bash ….
Odpověď
Pokud time
není k dispozici,
start=`date +%s` stuff end=`date +%s` runtime=$((end-start))
Komentáře
- Upozorňujeme, že to funguje, pouze pokud nepotřebujete ‚ přesnost za sekundu. Pro některá použití, která mohou být přijatelná , pro ostatní ne. Pro mírně lepší přesnost (‚ stále vyvoláváte
date
například dvakrát, takže můžete na nejlépe získat v praxi milisekundovou přesnost a pravděpodobně i méně), zkuste použítdate +%s.%N
. (%N
je nanosekunda od celé sekundy .) - @ChrisH Ach. Dobré, poukazuji na to; bash aritmetická expanze je pouze celé číslo. Vidím dvě obvi další možnosti; buď vypusťte období v řetězci formátu data (a výslednou hodnotu považujte od epochy za nanosekundy), použijte tedy
date +%s%N
nebo použijte něco schopnějšího, jako jebc
pro výpočet skutečného běhu ze dvou hodnot, jak navrhuje jwchew. Přesto mám pocit, že tento přístup je neoptimální způsob, jak toho dosáhnout;time
je podstatně lepší, pokud je k dispozici, z důvodů uvedených výše. - Stačí nainstalovat
bc
a provést toto:runtime=$( echo "$end - $start" | bc -l )
- Pokud váš skript trvá několik minut, použijte:
echo "Duration: $((($(date +%s)-$start)/60)) minutes
- Dále k @ rubo77 komentář, pokud váš skript trvá několik hodin, použijte
hours=$((runtime / 3600)); minutes=$(( (runtime % 3600) / 60 )); seconds=$(( (runtime % 3600) % 60 )); echo "Runtime: $hours:$minutes:$seconds (hh:mm:ss)"
odpověď
Po ukončení skriptu stačí zavolat times
bez argumentů.
S ksh
nebo zsh
, místo toho můžete použít time
. S zsh
vám time
kromě uživatelů a poskytne také nástěnné hodiny. systémový čas CPU.
Chcete-li zachovat stav ukončení skriptu, můžete to udělat:
ret=$?; times; exit "$ret"
Nebo vy můžete také přidat trap na EXIT
:
trap times EXIT
Tímto způsobem budou časy volány vždy, když shell opustí a stav ukončení bude zachován.
$ bash -c "trap times EXIT; : {1..1000000}" 0m0.932s 0m0.028s 0m0.000s 0m0.000s $ zsh -c "trap time EXIT; : {1..1000000}" shell 0.67s user 0.01s system 100% cpu 0.677 total children 0.00s user 0.00s system 0% cpu 0.677 total
Upozorňujeme, že všechny bash
, ksh
a zsh
mají $SECONDS
speciální proměnnou, která se každou sekundu automaticky zvyšuje. V zsh
i ksh93
lze z této proměnné udělat také plovoucí desetinnou čárku (s typeset -F SECONDS
) pro větší přesnost. Toto je pouze čas nástěnných hodin, ne čas CPU.
Komentáře
- Tato proměnná $ SECONDS je velmi užitečná, díky!
- Vylučuje váš přístup účinek časových událostí? – – Myslím, že váš přístup je blízko
time
přístupu uvedeného výše.- – Myslím, že přístuptimeit
uvedený v kódu MATLAB může být užitečný zde. - Ahoj, @St é Phane Chazelas. Zjistil jsem, že
times
nedává ‚ čas na zeď, že? napříkladbash -c 'trap times EXIT;sleep 2'
- @Binarus, ano, tato funkce pochází z ksh. Na rozdíl od ksh93 / zsh, kromě bash nepodporujících plovoucí desetinnou čárku, je to také ‚ s rozbité v tom, že když nastavíte SECONDS na 0, změní se na 1 z 0 na 1 sekundu později ( protože bere v úvahu pouze výsledek
time()
který má pouze úplnou druhou zrnitost). - @Binarus, ne to ‚ s mezi 0 a 1. Pokud nastavíte SECONDS na 0 ve 12:00: 00 000, změní se na 1 o jednu sekundu později. Pokud jej ale nastavíte na 12: 00: 00,999, změní se na 1 o milisekundu později. Ale ano, souhlasím, že pravděpodobně v praxi moc nezáleží na tom, jestli ‚ stejně nemáte subsekundovou přesnost.
Odpověď
Jsem trochu pozdě do rozjetého vlaku, ale chtěl jsem zveřejnit své řešení (pro subsekundovou přesnost ) pro případ, že by ostatní narazili na toto vlákno při hledání. Výstup je ve formátu dnů, hodin, minut a nakonec sekund:
res1=$(date +%s.%N) # do stuff in here res2=$(date +%s.%N) dt=$(echo "$res2 - $res1" | bc) dd=$(echo "$dt/86400" | bc) dt2=$(echo "$dt-86400*$dd" | bc) dh=$(echo "$dt2/3600" | bc) dt3=$(echo "$dt2-3600*$dh" | bc) dm=$(echo "$dt3/60" | bc) ds=$(echo "$dt3-60*$dm" | bc) LC_NUMERIC=C printf "Total runtime: %d:%02d:%02d:%02.4f\n" $dd $dh $dm $ds
Doufám, že někdo tam to považuje za užitečné!
Komentáře
- Myslím, že kromě použití ‚ bc ‚ provádět výpočty. BTW opravdu dobrý skript;)
- Pozor, FreeBSD ‚ s
date
nepodporuje přesnost vteřin a do časového razítka pouze připojí doslovný „N
„. - Velmi pěkný scénář, ale můj bash ‚ nezpracovává subsekundovou část. Také jsem se dozvěděl, že / 1 v bc to efektivně odstraní, takže jsem přidal @ / 1 @ do výpočtu $ ds a nyní to vypadá velmi pěkně!
- bc podporuje modulo:
dt2=$(echo "$dt%86400" | bc)
. Jen říkám … BTW Dávám přednost formědt2=$(bc <<< "${dt}%86400")
, ale ‚ je zcela osobní. - Nemám ‚ zatím o
bc
nic nevím, ale dělení86400
mi nedůvěřuje následující důvod: Existují dny, které nemají 86400 sekund, například dny, kdy je čas přepnut z DST na normální čas a naopak, nebo dny s přestupnými sekundami. Pokud jsou takové dny součástí časového rozsahu, který chcete vypočítat, tj. Jsou mezires1
ares2
(včetně těchto hodnot), váš skript pravděpodobně selže.
Odpověď
Moje metoda pro bash
:
# Reset BASH time counter SECONDS=0 # # do stuff # ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec"
Komentáře
- To ukazuje uplynulý čas, ale ‚ nezobrazuje “ jemnozrnný výstup, jako je čas procesoru, čas I / O „, jak je požadováno v otázce.
- Pro ty, kteří hledají odpověď na otázku, kterou pokládají, bude toto řešení pravděpodobně užitečné. Váš komentář by byl lépe adresován na otázku OP.
Odpověď
Osobně rád zabalím všechny své kód skriptu v některých „hlavních“ funkcích:
main () { echo running ... } # stuff ... # calling the function at the very end of the script time main
Všimněte si, jak snadné je použít příkaz time
v tomto scénáři. Je zřejmé, že neměříte přesný čas včetně času analýzy skriptu, ale ve většině situací mi připadá dostatečně přesný.
Komentáře
- Skvělé řešení, nevyžaduje ‚ další nástroje a je samostatná.
Odpovědět
#!/bin/bash start=$(date +%s.%N) # HERE BE CODE end=$(date +%s.%N) runtime=$(python -c "print(${end} - ${start})") echo "Runtime was $runtime"
Ano, toto se nazývá Python, ale pokud s tím dokážete žít, pak je to docela pěkné a stručné řešení.
Komentáře
- Dejte si pozor, aby spuštění příkazu
python
v subshellu a čtení jeho výstupu trvalo na většině současných systémů několik milionů nanosekund. Totéž pro spuštěnídate
. - “ Několik milionů nanosekund “ je několik milisekund . Lidé, kteří časují bash skripty, se tím obvykle příliš nezabývají (pokud nespustí několik miliard skriptů za megasekundu).
- Všimněte si také, že i když výpočet se provádí uvnitř pythonovského procesu, hodnoty byly zcela shromážděny před vyvoláním pythonu. Doba spuštění skriptu bude měřena správně, bez “ milionů nanosekund “ režie.
-
time main
výše je mnohem čistší …ano, můžeme žít se spoustou degradace, ale ‚ je to mnohem lepší, aniž bychom ‚ zůstali inženýři! -
$(echo $end - $start | bc)
udělá totéž bez pythonu
odpověď
Tato otázka je docela stará, ale při hledání mého oblíbeného způsobu, jak to udělat, se toto vlákno dostalo vysoko … a já jsem překvapen, že se o tom nikdo nezmínil:
perf stat -r 10 -B sleep 1
„perf“ je nástroj pro analýzu výkonu, který je součástí jádra pod „tools / perf“ a je často k dispozici k instalaci jako samostatný balíček („perf“ v CentOS a „linux-tools“ v Debianu / Ubuntu). Linux Kernal perf Wiki obsahuje mnohem více informací.
Spuštění „perf stat“ poskytuje spoustu podrobností včetně průměrné doby provedení hned na konci:
1.002248382 seconds time elapsed ( +- 0.01% )
Komentáře
- Co je
perf
? - @B Layer – upravil moji odpověď t o uveďte stručný popis ‚ perf ‚.
-
perf stat
nyní si stěžuje na “ Pravděpodobně nemáte oprávnění ke shromažďování statistik. “ pokud nespustíte některé příkazy pomocísudo
, což je zbytečné ve všech scénářích, kdy nemáte ‚ úplně vlastní cílový stroj. - Úžasné, díky! Způsob jemnějšího řešení, než navrhují
time
. Zejménatime
nelze použít pro měření konkurenčních řešení kódu (protože ‚ t doba tisku v milisekundách a méně) , zatímco vaše řešení ano.
Odpověď
Malá funkce shellu, kterou lze přidat dříve příkazy k měření jejich času:
tm() { local start=$(date +%s) $@ local exit_code=$? echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}" return $exit_code }
Potom jej použijte ve svém skriptu nebo na příkazovém řádku takto:
tm the_original_command with all its parameters
Komentáře
- Bylo by vhodné přidat milisekundy, vyzkoušel jsem ilke
s=$(date +%s000)
, nevím pokud to funguje. - @loretoparisi po dobu milisekund, můžete zkusit
date +%s%N
. Viz serverfault.com/questions/151109/… - To je skvělé, kromě bezpečnějších použijte
"$@"
odpověď
#!/bin/csh #PBS -q glean #PBS -l nodes=1:ppn=1 #PBS -l walltime=10:00:00 #PBS -o a.log #PBS -e a.err #PBS -V #PBS -M [email protected] #PBS -m abe #PBS -A k4zhang-group START=$(date +%s) for i in {1..1000000} do echo 1 done END=$(date +%s) DIFF=$(echo "$END - $START" | bc) echo "It takes DIFF=$DIFF seconds to complete this task..."
Komentáře
- Jak se to opravdu liší od ostatních již uvedených odpovědí, které používají
date
před a po skript a vygenerovat rozdíl mezi nimi?
odpověď
-
Jen použijte
time [any command]
. Příklad:time sleep 1
bude spát v reálném čase (tj. Podle stopek) ~ 1 000 až ~ 1 020 s, jak je znázorněno zde:$ time sleep 1 real 0m1.011s user 0m0.004s sys 0m0.000s
Jaká krásná věc. Po něm můžete vložit libovolný příkaz a výsledek se zobrazí v pěkné, čitelné podobě. Opravdu ho rád používám pro načasování sestavení. Příklad:
# time your "make" build time make # time your "Bazel" build time bazel build //path/to/some:target
… nebo pro operace git, které mohou být skutečně dlouho, takže mohu rozvíjet realistická mentální očekávání:
# time how long it takes to pull from a massive repo when # I"m working from home during COVID-19. NB: `git pull` # is sooooo much slower than just pulling the one branch # you need with `git pull origin <branch>`, so just fetch # or pull what you need! time git pull origin master
-
Pro více přizpůsobené načasování kde možná budete muset manipulovat s výstupem nebo jej převést do jiných forem v bash , použijte interní
$SECONDS
proměnnou. Zde je ukázka, včetně převodu těchto sekund na jiné jednotky, například minuty s plovoucí desetinnou čárkou:Upozorňujeme, že
dt_min
se zaokrouhlí z0.01666666666...
(1 sekunda = tolik minut) na0.017
v tomto případě, protože používám funkciprintf
k zaokrouhlování. Níže uvedená částsleep 1;
je místo, kde zavoláte skript, který se má spustit a spustit, ale místo toho kvůli této ukázce jen spím 1 sekundu.Příkaz:
start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); \ dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); \ echo "dt_sec = $dt_sec; dt_min = $dt_min"
Výstup:
dt_sec = 1; dt_min = 0.017
Související:
- Přečíst více asi
bc
aprintf
v mé odpovědi zde: https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867 - Už si nepamatuji, kde jsem se poprvé dozvěděl o příkazu
time
, ale mohl to být z odpověď @Trudberta právě zde .
Odpověď
Používání pouze bash je také možné měřit a vypočítat dobu trvání části shellového skriptu (nebo uplynulý čas pro celý skript):
start=$SECONDS ... # do time consuming stuff end=$SECONDS
nyní můžete rozdíl pouze vytisknout:
echo "duration: $((end-start)) seconds."
pokud potřebujete pouze přírůstkové trvání, proveďte:
echo "duration: $((SECONDS-start)) seconds elapsed.."
Trvání můžete také uložit do proměnné:
let diff=end-start
Komentáře
- ^ TOTO je odpověď. Nebo jednodušeji: $ SECONDS na konci. Je ‚ s proměnnou BUILT-IN Bash. Všechny ostatní odpovědi právě dělají práci navíc, aby znovu vymysleli toto kolo …
- Toto je jen opakování dřívější odpovědi Marks unix.stackexchange .com / a / 340156/155362 .
Odpověď
Časová funkce založená na SECONDS
, omezeno pouze na granularitu druhé úrovně, nepoužívá žádné externí příkazy:
time_it() { local start=$SECONDS ts ec printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Starting $*" "$@"; ec=$? printf -v ts "%(%Y-%m-%d_%H:%M:%S)T" -1 printf "%s\n" "$ts Finished $*; elapsed = $((SECONDS-start)) seconds" # make sure to return the exit code of the command so that the caller can use it return "$ec" }
Například:
time_it sleep 5
dává
2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished sleep 5; elapsed = 5 seconds
odpověď
Použít integrovaný čas bash?
time: time [-p] PIPELINE Execute PIPELINE and print a summary of the real time, user CPU time, and system CPU time spent executing PIPELINE when it terminates. The return status is the return status of PIPELINE. The `-p" option prints the timing summary in a slightly different format. This uses the value of the TIMEFORMAT variable as the output format.
Příklad:
TIMEFORMAT="The command took %Rs" time { sleep 0.1 }
Výstup:
The command took 0.108s
Odpověď
Zde je variace Alex „Odpověď. Zajímám se jen o minuty a sekundy, ale také jsem chtěl, aby byl formátován jinak. Udělal jsem to takto:
start=$(date +%s) end=$(date +%s) runtime=$(python -c "print "%u:%02u" % ((${end} - ${start})/60, (${end} - ${start})%60)")
Komentáře
- Proč downvote? Mám chybu?
- Použití
python
pro tento výpočet pro mě vypadá jako chyba, omlouvám se. Proč lidé ‚ prostě nemohou volattime
je mimo mě.
Odpověď
#!/bin/bash begin=$(date +"%s") Script termin=$(date +"%s") difftimelps=$(($termin-$begin)) echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."
Odpověď
Přijaté řešení pomocí time
zapíše stderr
.
Řešení používající times
zapíše do stdout
.
V řešeních používajících $SECONDS
chybí přesnost druhé sekundy.
Další řešení zahrnují volání externích programů, jako je date
nebo perf
, které nejsou efektivní.
Pokud vám některý z nich vyhovuje, použijte jej.
Ale pokud potřebujete efektivní řešení pro získání časů s milisekundovou přesností a potřebujete je do proměnných tak, aby původní výstup zůstává nerušený můžete kombinovat substituci procesu s některými přesměrováními kolem time
, které je mnohem rychlejší než volání externích programů a umožňuje přesměrování kolem skriptu časování obálky jako v původním příkazu / skriptu.
# Preparations: Cmd=vgs # example of a program to be timed which is writing to stdout and stderr Cmd="eval { echo stdout; echo stderr >&2; sleep 0.1; }" # other example; replace with your own TIMEFORMAT="%3R %3U %3S" # make time output easy to parse
Vyberte jednu z následujících variant analyzujících výstup time
odpovídající vašim potřebám:
Nejkratší varianta, do které je stdout
z $Cmd
zapsán stderr
a nic stdout
:
read Elapsed User System < <({ time $Cmd 2>&3; } 3>&2 2>&1 >&3)
Delší varianta, která udržuje původní stdout
a stderr
od sebe oddělené:
{ read Elapsed User System < <({ time $Cmd 2>&4; } 4>&2 2>&1 >&3); } 3>&1
Nejkomplikovanější varianta zahrnuje uzavření dalších deskriptorů souborů, takže $Cmd
se volá, jako by bez tohoto časovacího obálky a lvm
příkazy jako vgs
si nestěžují na uniklé deskriptory souborů:
{ read Elapsed User System < <({ time $Cmd 2>&4 4>&-; } 4>&2 2>&1 >&3 3>&-); } 3>&1
vy může dokonce předstírat sčítání s plovoucí desetinnou čárkou v bash
bez volání bc
, což by bylo mnohem pomalejší:
CPU=`printf %04d $((10#${User/.}+10#${System/.}))` # replace with your own postprocessing echo CPU ${CPU::-3}.${CPU: -3} s, Elapsed $Elapsed s >&2 # redirected independent of $Cmd
Možné výstupy se dvěma příklady $Cmd
na pomalé CPU:
File descriptor 3 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash File descriptor 4 (/dev/pts/1) leaked on vgs invocation. Parent PID 10756: bash VG #PV #LV #SN Attr VSize VFree b3 3 24 0 wz--n- 1.31t 1.19t CPU 0.052 s, Elapsed 0.056 s
Nebo:
stdout stderr CPU 0.008 s, Elapsed 0.109 s