risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come ottenere in modo efficace i tempi di esecuzione di uno script?

Vorrei visualizzare il tempo di completamento di uno script.

Quello che faccio attualmente è -

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

Questo mostra solo l'ora di inizio e fine della sceneggiatura. Sarebbe possibile visualizzare un output a grana fine come tempo processore/tempo io, ecc.?

392
mtk

Basta usare time quando si chiama lo script:

time yourscript.sh
506
Trudbert

Se time non è un'opzione,

start=`date +%s`
stuff
end=`date +%s`

runtime=$((end-start))
204
Rob Bos

Basta chiamare times senza argomenti all'uscita dallo script.

Con ksh o zsh, puoi anche usare time. Con zsh, time ti darà anche l'ora dell'orologio da parete oltre all'utente utente e tempo di CPU del sistema .

Per preservare lo stato di uscita del tuo script, puoi farlo:

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

Oppure puoi anche aggiungere una trap su EXIT:

trap times EXIT

In questo modo, i tempi verranno chiamati ogni volta che Shell esce e lo stato di uscita verrà preservato.

$ 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

Si noti inoltre che tutti bash, ksh e zsh hanno un $SECONDS variabile speciale che viene incrementata automaticamente ogni secondo. In entrambi zsh e ksh93, quella variabile può anche essere resa in virgola mobile (con typeset -F SECONDS) per avere più precisione. Questo è solo il tempo di clock, non il tempo della CPU.

77

Sono un po 'in ritardo con il carrozzone, ma volevo pubblicare la mia soluzione (per precisione sub-secondo) nel caso in cui altri si imbattessero in questo thread attraverso la ricerca. L'output è in formato di giorni, ore, minuti e infine secondi:

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

Spero che qualcuno la trovi utile!

32
jwchew

Il mio metodo per bash:

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

Questa domanda è piuttosto vecchia ma nel tentativo di trovare il mio modo preferito di farlo questa discussione è emersa in alto ... e sono sorpreso che nessuno lo abbia menzionato:

perf stat -r 10 -B sleep 1

'perf' è uno strumento di analisi delle prestazioni incluso nel kernel sotto 'tools/perf' e spesso disponibile per l'installazione come pacchetto separato ('perf' in CentOS e 'linux-tools' su Debian/Ubuntu). The Linux Kernal perf Wiki ha molte più informazioni al riguardo.

L'esecuzione di 'perf stat' fornisce molti dettagli, incluso il tempo medio di esecuzione alla fine:

1.002248382 seconds time elapsed                   ( +-  0.01% )
8
Zaahid
#!/bin/bash
start=$(date +%s.%N)

# HERE BE CODE

end=$(date +%s.%N)    
runtime=$(python -c "print(${end} - ${start})")

echo "Runtime was $runtime"

Sì, questo chiama Python, ma se riesci a conviverci, questa è una soluzione piuttosto piacevole e concisa.

6
Alex

Una piccola funzione Shell che può essere aggiunta prima dei comandi per misurare il loro tempo:

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

Quindi utilizzalo nel tuo script o sulla riga di comando in questo modo:

tm the_original_command with all its parameters
5
Evgeny

Personalmente, mi piace racchiudere tutto il mio codice di script in alcune funzioni "principali" in questo modo:

main () {
 echo running ...
}

# stuff ...

# calling the function at the very end of the script
time main

Nota quanto è facile usare il comando time in questo scenario. Ovviamente non stai misurando il tempo preciso incluso il tempo di analisi dello script, ma lo trovo abbastanza accurato nella maggior parte delle situazioni.

5
LeZuse

Utilizzando solo bash è anche possibile misurare e calcolare la durata del tempo per una parte dello script Shell (o il tempo trascorso per l'intero script):

start=$SECONDS

... # do time consuming stuff

end=$SECONDS

ora puoi semplicemente stampare la differenza:

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

se hai solo bisogno di una durata incrementale fai:

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

Puoi anche memorizzare la durata in una variabile:

let diff=end-start
3
gauteh

Ecco una variante della risposta di Alex. Mi preoccupo solo di minuti e secondi, ma volevo anche che fosse formattato diversamente. Quindi ho fatto questo:

start=$(date +%s)
end=$(date +%s)
runtime=$(python -c "print '%u:%02u' % ((${end} - ${start})/60, (${end} - ${start})%60)")
3
mpontillo
#!/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..."
3
Shicheng Guo

La funzione di temporizzazione basata su SECONDS, limitata alla granularità di secondo livello, non utilizza alcun comando esterno:

time_it() {
  local start=$SECONDS ts ec
  printf -v ts '%(%Y-%m-%d_%H:%M:%S)T' -1
  printf '%s\n' "$ts Starting $*"
  "[email protected]"; 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"
}

Per esempio:

time_it sleep 5

2019-03-30_17:24:37 Starting sleep 5 2019-03-30_17:24:42 Finished
sleep 5; elapsed = 5 seconds
2
codeforester
#!/bin/bash
begin=$(date +"%s")

Script

termin=$(date +"%s")
difftimelps=$(($termin-$begin))
echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."
1
Arun Binoy

Per bash, usa la variabile interna $SECONDS. Ecco una demo:

Nota che dt_min Viene arrotondato da 0.01666666666... (1 secondo = che molti minuti) a 0.017 In questo caso poiché sto usando la funzione printf per arrotondare . La parte sleep 1; Qui sotto è dove chiameresti l'esecuzione del tuo script e il tempo, ma sto solo dormendo per 1 secondo, per il bene di questa demo:

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"
dt_sec = 1; dt_min = 0.017

Relazionato:

0
Gabriel Staples