Ottieni il tempo di esecuzione del programma nella shell


407

Voglio eseguire qualcosa in una shell linux in alcune condizioni diverse ed essere in grado di generare il tempo di esecuzione di ogni esecuzione.

So che potrei scrivere uno script perl o python che lo farebbe, ma c'è un modo per farlo nella shell? (che sembra essere bash)



è possibile ottenere Tickscome il caso Windows?
freeforall tousez,

Risposte:


534

Usa la timeparola chiave integrata :

$ tempo di aiuto

time: time [-p] PIPELINE
    Eseguire PIPELINE e stampare un riepilogo del tempo reale, del tempo della CPU dell'utente,
    e il tempo della CPU di sistema impiegato per l'esecuzione di PIPELINE al termine.
    Lo stato di ritorno è lo stato di ritorno di PIPELINE. L'opzione `-p '
    stampa il riepilogo dei tempi in un formato leggermente diverso. Questo usa
    il valore della variabile TIMEFORMAT come formato di output.

Esempio:

$ time sleep 2
0m2.009 reali
utente 0m0.000s
sys 0m0.004s

1
Come viene utilizzato su un comando simile time -p i=x; while read line; do x=x; done < /path/to/file.txt? Restituisce immediatamente 0.00 a meno che non inserisca nulla prima del ciclo while .. cosa dà?
natli,

questa è una versione scadente, incorporata bash. dov'è il comando esterno 'time'?
Znik,

6
@Znik, prova / usr / bin / time
Mark Rajcok il

10
@natli: Anche se è timepossibile cronometrare un'intera pipeline così com'è (in virtù dell'essere una parola chiave Bash ), è necessario utilizzare un comando di gruppo ( { ...; ...; }) per time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }
cronometrare

2
Per vedere tutte le versioni di tempo che hai installato sul tuo sistema, puoi usaretype -a time
spinup

120

Puoi ottenere informazioni molto più dettagliate rispetto al bash integrato time(che Robert Gamble menziona) usando time (1) . Normalmente questo è /usr/bin/time.

Nota del redattore: per assicurarti di invocare l' utilità esterna time anziché la time parola chiave della shell , invocala come /usr/bin/time.
timeè un'utilità POSIX , ma l'unica opzione che è richiesta per supportare è -p.
Piattaforme specifiche implementano estensioni specifiche non standard: -vfunzionano con l' utilità GNUtime , come dimostrato di seguito (la domanda è taggata); l'implementazione di BSD / macOS utilizza -lper produrre un output simile - vedi man 1 time.

Esempio di output dettagliato:


$ /usr/bin/time -v sleep 1
       Command being timed: "sleep 1"
       User time (seconds): 0.00
       System time (seconds): 0.00
       Percent of CPU this job got: 1%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.05
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 0
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 210
       Voluntary context switches: 2
       Involuntary context switches: 1
       Swaps: 0
       File system inputs: 0
       File system outputs: 0
       Socket messages sent: 0
       Socket messages received: 0
       Signals delivered: 0
       Page size (bytes): 4096
       Exit status: 0


2
non ti capita di sapere da quale pacchetto debian verrebbe? non sembra essere installato di default
22ıu

1
Mi riferivo al tuo post Robert. A meno che tu non intenda il comando che suggerisci non è il bash incorporato?
grepsedawk,

24
Abbastanza sorprendentemente, è installato da un pacchetto chiamato "time".
Paul Tomblin,

2
L'output di / usr / bin / time è simile a "0.00user 0.00system 0: 02.00 scaduto 0% CPU (0avgtext + 0avgdata 0maxresident) k 0inputs + 0outputs (0major + 172minor) pagefaults 0swaps"
Paul Tomblin

4
@Nick: "sudo apt-get tempo di installazione".
Robert Gamble,

79
#!/bin/bash
START=$(date +%s)
# do something
# start your script work here
ls -R /etc > /tmp/x
rm -f /tmp/x
# your logic ends here
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

14
C'è un modo molto più semplice. Bash calcola automaticamente la variabile speciale $ SECONDS, quindi non è necessario il ricalcolo basato sul comando data esterno. La variabile $ SECONDS mantiene quanti secondi lo script bash è in esecuzione all'avvio. Questa variabile ha alcune proprietà speciali. Vedi la pagina man: D
Znik

Ho provato sia quanto sopra sia il metodo nel commento. Nel 1 ottengo un errore "variabile non
valida

45

Per una misurazione delta riga per riga, prova gnomon .

Un'utilità della riga di comando, un po 'come ts di moreutils, per anteporre le informazioni di data e ora all'output standard di un altro comando. Utile per i processi di lunga durata in cui desideri un record storico di ciò che richiede così tanto tempo.

Puoi anche usare le opzioni --highe / o --mediumper specificare una soglia di lunghezza in secondi, su cui gnomon evidenzierà il timestamp in rosso o giallo. E puoi fare anche poche altre cose.

esempio


3
Ottimo consiglio, ma solo per essere chiari: questo è utile per i tempi linea per linea , ma il sovraccarico di prendere tali tempi a grana fine aumenta significativamente il tempo complessivo .
mklement0

2
Utilità straordinaria .. Grazie per aver condiviso
Kishan B,

19

Se vuoi maggiore precisione, usa %Ncon date(e usa bcper il diff, perché $(())gestisce solo numeri interi).

Ecco come farlo:

start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)

printf "Execution time: %.6f seconds" $dur

Esempio:

start=$(date +%s.%N); \
  sleep 0.1s; \
  dur=$(echo "$(date +%s.%N) - $start" | bc); \
  printf "Execution time: %.6f seconds\n" $dur

Risultato:

Execution time: 0.104623 seconds

15

Se hai intenzione di utilizzare i tempi in seguito per calcolare, scopri come utilizzare l' -fopzione di /usr/bin/timeoutput del codice che salva i tempi. Ecco un po 'di codice che ho usato di recente per ottenere e ordinare i tempi di esecuzione di un'intera classe di programmi per studenti:

fmt="run { date = '$(date)', user = '$who', test = '$test', host = '$(hostname)', times = { user = %U, system = %S, elapsed = %e } }"
/usr/bin/time -f "$fmt" -o $timefile command args...

Successivamente ho concatenato tutti i $timefilefile e convogliato l'output in un interprete Lua . Puoi fare lo stesso con Python o bash o qualunque sia la tua sintassi preferita. Adoro questa tecnica.


Nota: il percorso completo /usr/bin/timeè necessario perché, sebbene which timeti dirà altrimenti, se esegui semplicemente time, eseguirà la versione della shell di timecui non accetta alcun argomento.
Kevin Dice,

Vorrei andare con env time:-)
Ciro Santilli 4 冠状 病 六四 事件 法轮功

13

Se hai solo bisogno di precisione al secondo, puoi usare la $SECONDSvariabile built-in , che conta il numero di secondi in cui la shell è stata in esecuzione.

while true; do
    start=$SECONDS
    some_long_running_command
    duration=$(( SECONDS - start ))
    echo "This run took $duration seconds"
    if some_condition; then break; fi
done

10

È possibile utilizzare timee subshell () :

time (
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
)

O nella stessa shell {}:

time {
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
}

Hai pubblicato due snippet di codice identici. Devi aver pensato di avere qualcosa di diverso lì.
Stason

3
@StasBekman non è vero, per prima cosa usa (& )(nuovo contesto, subshell ), e altri con {& }(stessa shell, stesso contesto)
Eduardo Cuomo

Aha! Stavo guardando molto duramente i due e non ho visto la differenza. Grazie per aver chiarito che {} vs ().
Stason,

2

Il modo è

$ > g++ -lpthread perform.c -o per
$ > time ./per

l'output è >>

real    0m0.014s
user    0m0.010s
sys     0m0.002s

Non c'è bisogno di usare -lphtreado -otag. Ho solo bisogno di usare il timecomando, che la risposta accettata spiega meglio.
Dennis,

7
Era un esempio. Questo è il mio perform.c con threading, quindi ho bisogno di -lpthread e per una semplice identità è -o per.
Robel Sharma,

0

un metodo possibilmente semplice (che potrebbe non soddisfare le diverse esigenze degli utenti) è l'uso della shell PROMPT.it è una soluzione semplice che può essere utile in alcuni casi. È possibile utilizzare la funzione di prompt di bash come nell'esempio seguente:

export PS1 = '[\ t \ u @ \ h] \ $' 

Il comando precedente comporterà la modifica del prompt della shell in:

[HH: MM: nome utente SS @ nome host] $ 

Ogni volta che si esegue un comando (o si preme invio) tornando al prompt della shell, il prompt visualizzerà l'ora corrente.

note:
1) attenzione che se si è aspettato qualche tempo prima di digitare il comando successivo, è necessario considerare questa volta, ovvero l'ora visualizzata nel prompt della shell è il timestamp quando è stato visualizzato il prompt della shell, non quando si immette il comando. alcuni utenti scelgono di premere il tasto Invio per ottenere un nuovo prompt con un nuovo timestamp prima di essere pronti per il comando successivo.
2) Ci sono altre opzioni e modificatori disponibili che possono essere usati per cambiare il prompt di bash, fare riferimento a (man bash) per maggiori dettagli.


Non il punto in cui il programma viene eseguito, ma la durata dell'esecuzione del programma.
Geno Chen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.