Hogyan lehet hatékonyan megszerezni a szkript végrehajtási idejét?

Szeretném megjeleníteni egy szkript befejezési idejét.

Amit jelenleg csinálok, az –

#!/bin/bash date ## echo the date at start # the script contents date ## echo the date at end 

Ez csak a szkript kezdetének és végének idejét mutatja. finom szemcsés kimenet jeleníthető meg, például a processzor ideje / io idő stb.?

Megjegyzések

Válasz

Jus A szkript meghívásakor ne használja a time -t:

time yourscript.sh 

megjegyzések

  • Ez háromszor ad ki: real, user és sys. Ezek jelentését lásd: itt .
  • és ” real ” valószínűleg az, amit tudni akarnak az emberek – ” A valós a falióra ideje – a hívás kezdetétől a végéig tartó idő
  • Van-e mód arra, hogy az állományt fájlba foglalja? Például valami olyasmi, mint time $( ... ) >> out.txt
  • Ezt megteheti a parancssoron lévő parancssorokkal is, például: time (command1 && command2)
  • Vagy a szkriptjében egyszerűen megteheti: echo $ SECONDS feltételezve, hogy bash ….
  • Válasz

    Ha time nincs lehetőség,

    start=`date +%s` stuff end=`date +%s` runtime=$((end-start)) 

    Megjegyzések

    • Ne feledje, hogy ez csak akkor működik, ha nem kell ‘ szüksége a másodperc alatti pontosságra. Néhány felhasználásnál ez elfogadható lehet mások számára nem. Valamivel jobb pontosság érdekében (‘ még mindig kétszer hívja meg például a date -t, így a a legjobb ha milliszekundumos pontosságú a gyakorlatban, és valószínűleg kevesebb is), próbálkozzon a date +%s.%N használatával. (%N nanoszekundum, mivel az egész másodperc .)
    • @ChrisH Oh. Jó rámutatni; a bash aritmetikai bővítése csak egész szám. Két obvi-t látok ous opciók; vagy árkolja el a periódust a dátumformátum-karakterláncban (és az eredő értéket korszak óta nanoszekundumként kezeli), ezért használja a date +%s%N elemet, vagy használjon valami alkalmasabbat, például a bc a tényleges futási idő kiszámításához a két értékből, mint például a jwchew. Ennek ellenére úgy érzem, hogy ez a megközelítés nem optimális módja ennek; A time lényegesen jobb, ha rendelkezésre áll, a fentiekben vázolt okokból.
    • Csak telepítse a bc alkalmazást, majd tegye ezt: runtime=$( echo "$end - $start" | bc -l )
    • Ha a szkript több percet vesz igénybe, használja a következőt: echo "Duration: $((($(date +%s)-$start)/60)) minutes
    • Tovább a @ rubo77 címre megjegyzés, ha a szkripted több órát vesz igénybe, használd a hours=$((runtime / 3600)); minutes=$(( (runtime % 3600) / 60 )); seconds=$(( (runtime % 3600) % 60 )); echo "Runtime: $hours:$minutes:$seconds (hh:mm:ss)"

    Válasz

    Csak a times hívása argumentumok nélkül a szkriptből való kilépéskor.

    ksh vagy zsh, használhatja helyette az time -t is. A zsh használatával a time a faliórát is megadja a felhasználó és mellett system CPU idő.

    A szkript kilépési állapotának megőrzése érdekében megteheti:

    ret=$?; times; exit "$ret" 

    Vagy Ön csapdát is hozzáadhat a EXIT címre:

    trap times EXIT 

    Így a rendszer a héj kilépésekor meghívja az időket, és a kilépési állapot megmarad.

    $ 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 

    Ne feledje, hogy a bash, ksh és zsh rendelkezik egy $SECONDS speciális változóval, amely másodpercenként automatikusan növekszik. Mind a zsh, mind a ksh93 esetében ez a változó lebegőponttá is tehető (typeset -F SECONDS ) a nagyobb pontosság érdekében. Ez csak a falióra ideje, nem a CPU-idő.

    Megjegyzések

    • Ez a $ SECONDS változó nagyon hasznos, köszönöm!
    • Megszünteti-e megközelítése az időbeli események hatását? – – Úgy gondolom, hogy megközelítése közel áll a korábban bemutatott time megközelítéshez.- – Úgy gondolom, hogy a MATLAB kódban bemutatott timeit megközelítés itt hasznos lehet.
    • Szia, @St é phane Chazelas. Úgy találtam, hogy times nem ad ‘ nem ad falidőt, igaz? például bash -c 'trap times EXIT;sleep 2'
    • @Binarus, igen, ez a szolgáltatás a ksh-ből származik. A ksh93 / zsh-vel ellentétben a lebegőpontot nem támogató bash mellett ‘ abban is megszakad, hogy miután a SECONDS értéket 0-ra állította, később 0-ról 1 másodpercre 1-re változik ( mivel csak a time() eredményét veszi figyelembe, amelynek csak a teljes második részletessége van).
    • @Binarus, nem pedig azt, hogy ‘ s 0 és 1 között. Ha a SECONDS értéket 0-ra állítja 12: 00: 00.000-kor, akkor ez egy másodperccel később 1-re változik. De ha 12: 00: 00.999-re állítja, később 1 milliszekundumra változik. De igen, egyetértek azzal, hogy valószínűleg ‘ nincs jelentősége a gyakorlatban, ha egyébként nincs ‘ pontja másodperc alatt.

    Válasz

    Későn érkeztem a sávhoz, de el akartam küldeni a megoldásomat (a másodperc alatti pontosság érdekében) ) arra az esetre, ha mások véletlenül ráakadnának erre a szálra a keresés során. A kimenet napok, órák, percek és végül másodpercek formátumú:

    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 

    Remélem, hogy valaki odakinn hasznosnak találja ezt!

    Megjegyzések

    • Azt hiszem, nincs más (csak bash) módszer, kivéve a ‘ bc ‘ a számítások elvégzéséhez. BTW nagyon jó szkript;)
    • Vigyázzon, hogy a FreeBSD ‘ Az s date nem támogatja a másodperc alatti pontosságot, és csak a szó szerinti „N” szót fűzi az időbélyeghez.
    • Nagyon szép szkript, de a bash nem ‘ t ne kezelje az alsodik részt. Azt is megtanultam, hogy a / 1 BC-ben ezt hatékonyan levetkőzi, ezért hozzáadtam a $ /s @ értéket a $ ds számításhoz, és most nagyon szép dolgokat jelenít meg.
    • A bc támogatja a modulo: dt2=$(echo "$dt%86400" | bc). Csak azt mondom … BTW inkább a dt2=$(bc <<< "${dt}%86400") formát preferálom, de a ‘ teljesen személyes.
    • Nem ‘ még nem tud semmit a bc -ről, de az 86400 által történő felosztás bizalmatlanná tesz a következő ok: Vannak olyan napok, amelyek nem rendelkeznek 86400 másodperccel, például olyan napok, amikor az idő DST-ről normál időre változik, és fordítva, vagy szökő másodpercekkel rendelkező napok. Ha az ilyen napok a számítani kívánt időtartam részét képezik, azaz res1 és res2 között vannak (ezeket az értékeket is beleértve), akkor a parancsfájl valószínűleg nem fog sikerülni.

    Válasz

    Saját módszer a bash :

    # Reset BASH time counter SECONDS=0 # # do stuff # ELAPSED="Elapsed: $(($SECONDS / 3600))hrs $((($SECONDS / 60) % 60))min $(($SECONDS % 60))sec" 

    Megjegyzések

    • Ez az eltelt időt mutatja, de nem ‘ t ” finom szemcsés kimenetet mutat, például a processzor idejét, az I / O időt “, ahogyan azt a kérdés megkívánja.
    • Akik a feltett kérdésre választ keresnek, valószínűleg hasznosnak találják ezt a megoldást. Megjegyzésed jobban szólna az OP-k kérdéséről.

    Válasz

    Személy szerint szeretném az összes szkriptkód néhány “main” funkcióban, például:

    main () { echo running ... } # stuff ... # calling the function at the very end of the script time main 

    Figyelje meg, mennyire egyszerű használni a time parancsot ebben a forgatókönyvben. Nyilvánvaló, hogy nem a pontos időt méri, beleértve a parancsfájl elemzési idejét is, de a legtöbb helyzetben elég pontosnak találom.

    Megjegyzések

    • Remek megoldás, nem igényel további eszközöket, és önálló.

    Válasz

    #!/bin/bash start=$(date +%s.%N) # HERE BE CODE end=$(date +%s.%N) runtime=$(python -c "print(${end} - ${start})") echo "Runtime was $runtime" 

    Igen, ez meghívja a Python-ot, de ha tudsz ezzel élni, akkor ez nagyon szép, szűkszavú megoldás.

    Megjegyzések

    • Vigyázzon, hogy a python parancs futtatása egy alhéjban és annak kimenetének kiolvasása több millió nanoszekundumot vesz igénybe a legtöbb jelenlegi rendszeren. div id = “33e4a5674d”>

    .

  • ” Több millió nanoszekundum ” több milliszekundum . A bash szkripteket időzítő emberek általában nem aggódnak emiatt (hacsak nem futnak több milliárd szkriptet megaszekundumonként).
  • Vegye figyelembe, hogy még akkor is, ha A számítás egy python folyamaton belül történik, az értékeket teljesen összegyűjtötték, mielőtt a python meghívásra került volna. A szkript végrehajtási idejét helyesen fogják mérni, a ” nanoszekundumok milliói ” nélkül.
  • sokkal tisztább …igen, sok degradációval élhetünk, de ez ‘ sokkal jobb anélkül, hogy ‘ mérnökök maradnának!
  • $(echo $end - $start | bc) ugyanazt fogja tenni python nélkül
  • Válasz

    Ez a kérdés meglehetősen régi, de amikor megpróbáltam megtalálni a kedvenc módomat, ez a szál magasra került … és “meglepődtem, hogy senki sem említette:

    perf stat -r 10 -B sleep 1 

    “perf” egy teljesítményelemző eszköz, amely a rendszermagban található az “tools / perf” alatt, és gyakran külön csomagként telepíthető (a “perf” a CentOS-ban és a “linux-tools” a Debianban / Ubuntuban). A Linux Kernal perf Wiki sokkal több információt tartalmaz róla.

    A “perf stat” futtatása elég sok részletet tartalmaz, beleértve az átlagos végrehajtási időt közvetlenül a végén:

    1.002248382 seconds time elapsed ( +- 0.01% ) 

    megjegyzések

    • mi az a perf?
    • @B Layer – szerkesztette válaszomat t o röviden ismertesse a következőt: ‘ perf ‘.
    • perf stat most ” miatt panaszkodik. Lehet, hogy nincs jogosultsága statisztikák gyűjtésére. “, hacsak nem futtat néhány parancsot a , ami haszontalanná teszi minden olyan esetben, amikor nem ‘ nem teljesen a saját célgépe.
    • Elképesztő, köszönöm! Sokkal finomabb megoldás, mint time mások javasolják. Különösen az time nem alkalmazható a kódversenyes megoldások mérésére (mivel ‘ nem nyomtatja az időt ezredmásodpercekben és kevesebbben) , míg a megoldása igen.

    Válasz

    Egy kis shell funkció, amely korábban hozzáadható parancsok az idő mérésére:

    tm() { local start=$(date +%s) $@ local exit_code=$? echo >&2 "took ~$(($(date +%s)-${start})) seconds. exited with ${exit_code}" return $exit_code } 

    Ezután használja a szkriptben vagy a parancssorban így:

    tm the_original_command with all its parameters 

    Megjegyzések

    • Érdemes ezredmásodperceket adni, megpróbálta az ilke s=$(date +%s000) -t, nem biztos ha működik.
    • @loretoparisi milliszekundumig, próbálkozzon a date +%s%N próbával. Lásd: serverfault.com/questions/151109/…
    • Ez nagyszerű, kivéve a biztonságosabbat használja az "$@"

    Válasz

    #!/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..." 

    Megjegyzések

    • Miben különbözik ez valójában a többi már adott választól, amelyek date -t használnak előtte és utána a szkriptet, és kiadja a köztük lévő különbséget?

    Válasz

    1. Csak használja time [any command] . Például: time sleep 1 valós idejű (azaz egy stopperóra időzített) ~ 1.000 és ~ 1.020 másodperc közötti alvás, az itt látható módon:

        $ time sleep 1 real 0m1.011s user 0m0.004s sys 0m0.000s  

      Milyen szép dolog. Bármelyik parancsot felteheti utána, és az eredményt szép, ember által olvasható formában adja ki. Nagyon szeretek az építések időzítésére használni. Például:

        # time your "make" build time make # time your "Bazel" build time bazel build //path/to/some:target  

      … vagy git műveletekhez, amelyek potenciálisan valóban hosszú, így reális mentális elvárásokat tudok kialakítani:

        # 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  
    2. A személyre szabottabb időzítési igényekhez ahol szükség lehet a kimenet manipulálására vagy más formákká alakítására, a bash , használja a belső $SECONDS változót. Itt van egy bemutató, beleértve a másodpercek más egységekké történő átalakítását, például lebegőpontos percek:

      Ne feledje, hogy az dt_min kerekítésre kerül 0.01666666666... (1 másodperc = annyi perc) és 0.017 között ebben az esetben, mivel “a printf függvényt használom a kerekítéshez. Az alábbi sleep 1; részben megtalálhatod a szkripted futtatását és időzítését, de én csak 1 másodpercig alszom a bemutató kedvéért.

      Parancs:

        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"  

      Kimenet:

        dt_sec = 1; dt_min = 0.017  

    Kapcsolódó:

    1. körülbelül bc és printf az itteni válaszomban: https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-division-in-bash/58479867#58479867
    2. Már nem emlékszem, hol tudtam meg először a time parancsot, de lehet, hogy a @Trudbert válasza itt .

    Válasz

    Csak a használatával bash azt is meg lehet mérni és kiszámolni a shell script egy részének időtartamát (vagy a teljes szkript eltelt ideje):

    start=$SECONDS ... # do time consuming stuff end=$SECONDS 

    most már csak kinyomtathatja a különbséget:

    echo "duration: $((end-start)) seconds." 

    ha csak növekményes időtartamra van szüksége, tegye:

    echo "duration: $((SECONDS-start)) seconds elapsed.." 

    Az időtartamot egy változóban is elmentheti:

    let diff=end-start 

    megjegyzések

    • ^ EZ a válasz az embereknek. Vagy egyszerűbben: $ SECONDS a végén. ‘ egy BUILT-IN Bash változó. Az összes többi válasz csak extra munkát végez a kerék újrafeltalálásához …
    • Ez csak a Marks korábbi válaszának megismétlése unix.stackexchange .com / a / 340156/155362 .

    Válasz

    Időzítési függvény a SECONDS nem használ semmilyen külső parancsot:

    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" } 

    Például:

    time_it sleep 5 

    ad

    2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished sleep 5; elapsed = 5 seconds 

    Válasz

    Használja a bash beépített idejét?

    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élda:

    TIMEFORMAT="The command took %Rs" time { sleep 0.1 } 

    Kimenet:

    The command took 0.108s 

    Válasz

    Itt található Alex variációja válaszok. Csak percek és másodpercek érdekelnek, de azt is szerettem volna, ha másképp lenne formázva. Tehát ezt tettem:

    start=$(date +%s) end=$(date +%s) runtime=$(python -c "print "%u:%02u" % ((${end} - ${start})/60, (${end} - ${start})%60)") 

    megjegyzések

    • Miért van a visszavonás? Van egy hibám?
    • A python használata ehhez a számításhoz nekem is hibának tűnik, sajnálom, ember. Miért nem tudnak ‘ hívni az time -t, meghaladja rajtam.

    Válasz

    #!/bin/bash begin=$(date +"%s") Script termin=$(date +"%s") difftimelps=$(($termin-$begin)) echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution." 

    Válasz

    Az elfogadott megoldás A (z) time használatával a következőhöz ír: stderr.
    A times parancsot használó div id = “ddc1bd7074”>

    .
    A$SECONDS-t használó megoldásokból hiányzik a másodpercek alatti pontosság.
    A többi megoldás külső programok, példáuldatevagyperf, amely nem hatékony.
    Ha ezek bármelyikével jól áll, használja.

    De ha hatékony megoldásra van szükség az idők megszerzéséhez milliszekundumos pontossággal és szükségük van rájuk változókká úgy, hogy a az eredeti kimenet zavartalan marad kombinálhatja a folyamat helyettesítését néhány átirányítással az time körül, ami sokkal gyorsabb, mint a hívás külső programokat, és lehetővé teszi az átirányítást az időburkoló szkript körül, mint az eredeti parancsban / szkriptben.

    # 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 

    Válassza ki a következő változatok egyikét, elemezve a time az Ön igényeinek megfelelő:
    A legrövidebb változat, ahol a $Cmd stdout beírása stderr és semmi stdout:

    read Elapsed User System < <({ time $Cmd 2>&3; } 3>&2 2>&1 >&3) 

    Hosszabb változat, amely megtartja eredeti stdout és stderr egymástól elkülönítve:

    { read Elapsed User System < <({ time $Cmd 2>&4; } 4>&2 2>&1 >&3); } 3>&1 

    A legbonyolultabb változat magában foglalja az extra fájlleírók bezárását úgy, hogy a $Cmd -t úgy hívják meg, mintha ez az időzítő nem lenne körülötte, és lvm parancsok, mint például a vgs, nem panaszkodnak a kiszivárgott fájlleírókra:

    { read Elapsed User System < <({ time $Cmd 2>&4 4>&-; } 4>&2 2>&1 >&3 3>&-); } 3>&1 

    Ön akár lebegőpontos összeadást is képes hamisítani a bash fájlban anélkül, hogy felhívná a bc -t, ami sokkal lassabb lenne:

    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 

    Lehetséges kimenetek a $Cmd két példájával egy lassú CPU-n:

    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 

    Vagy:

    stdout stderr CPU 0.008 s, Elapsed 0.109 s 

    Vélemény, hozzászólás?

    Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük