Wie messe ich die Dauer in Sekunden in einem Shell-Skript?


74

Ich möchte herausfinden, wie lange eine Operation in einem Linux-Shell-Skript dauert. Wie kann ich das machen?

Antworten:


108

Es ist eine gute Idee, den Befehl time zu verwenden, wie andere vorgeschlagen haben.

Eine weitere Option ist die Verwendung der in Magic integrierten Variablen $ SECONDS, die die Anzahl der Sekunden seit Beginn der Skriptausführung enthält. Sie können sagen:

START_TIME=$SECONDS
dosomething
ELAPSED_TIME=$(($SECONDS - $START_TIME))

Ich denke, das ist Bash-spezifisch, aber da Sie unter Linux arbeiten, gehe ich davon aus, dass Sie Bash verwenden.


3
Die einzige Einschränkung, die ich hier hinzufügen möchte, ist, dass die Verwendung von All-Caps-Namen für Ihre eigenen Variablen eine schlechte Form ist, da dies bedeutet, dass Sie versehentlich in die Shell eingebaute Variablen überschreiben können (f / e, wenn jemand sie zuweist, SECONDShat sie keine besonderen Eigenschaften mehr) Bedeutung). Siehe POSIX spec @ pubs.opengroup.org/onlinepubs/9699919799/basedefs/… , Reservieren von Kleinbuchstaben für die Verwendung durch Anwendungen. Beachten Sie dabei , dass Shell- und Umgebungsvariablen einen einzigen Namespace verwenden. - Der Namensraum von Umgebungsvariablennamen mit Kleinbuchstaben ist reserviert für Anwendungen.
Charles Duffy

40

Verwenden Sie den timeBefehl. time ls /bin.


1
timeist nicht geeignet, wenn Sie komplexe Befehlssequenz
Shiplu Mokaddim

4
@ shiplu.mokadd.im Nein? Wie wäre es mit : time (ls / ; sleep 2; ls /bin).
Keith

Wenn Sie verwenden \ und ()es wurde komplexer.
Shiplu Mokaddim

2
@ shiplu.mokadd.im - warum nicht geeignet? Erklären. Scheint mir in Ordnung / genau und wird seit Jahren verwendet ...
bshea

1
@ Keith Dies hat einige Probleme, wie /usr/bin/time -f '%C => %E' (ls / ; sleep 2; ls /bin)Würfebash: syntax error near unexpected token '('
Shiplu Mokaddim

35

Versuchen Sie folgendes Beispiel:

START_TIME=$SECONDS
# do something
sleep 65

ELAPSED_TIME=$(($SECONDS - $START_TIME))

echo "$(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"    
#> 1 min 5 sec

Zeige Minuten und Sekunden, vielen Dank.
Amr Lotfy

9

Viele der Antworten erwähnen $SECONDS, aber diese Variable ist sogar noch besser als sie denken :

Durch die Zuweisung zu dieser Variablen wird die Anzahl auf den zugewiesenen Wert zurückgesetzt, und der erweiterte Wert wird zum zugewiesenen Wert plus der Anzahl der Sekunden seit der Zuweisung.

Dies bedeutet, dass Sie diese Variable einfach direkt am Ende Ihres Skripts abfragen können, um die verstrichene Zeit zu drucken:

#!/usr/bin/env bash

# Do stuff...

echo "Script finished in $SECONDS seconds."

Sie können auch kleinere Abschnitte wie folgt zeitlich festlegen:

#!/usr/bin/env bash

# Do stuff

SECONDS=0

# Do timed stuff...

echo "Timed stuff finished in $SECONDS seconds."

5

Hier ist das Skript, um die verstrichene Zeit in Millisekunden zu ermitteln. Ersetzen Sie die Zeile sleep 60 durch den Code, den Sie ausführen möchten.

a=0
while [ $a -lt 10 ]
do
START_TIME=`echo $(($(date +%s%N)/1000000))`
sleep 3
END_TIME=`echo $(($(date +%s%N)/1000000))`
ELAPSED_TIME=$(($END_TIME - $START_TIME))
echo $ELAPSED_TIME
if [ $a -eq 10 ]
then
  break
fi
a=`expr $a + 1`
done

Angemessene Lösung für Millisekunden.
Blaf

3

Nur um jemandem wie mir zu helfen, der einen Fehler erhält:

 arithmetic expression: expecting primary: "-"

Überprüfen Sie Ihr Shellscript, das beginnen soll mit:

#!/bin/bash

Prost!


1

GNU time

Ich habe auch großen Spaß mit dem GNU- timeBefehl: https://www.gnu.org/software/time/, der im Vergleich zum integrierten timeBash einige wichtige Optionen bietet .

Beispielnutzung:

env time --format '%e' --output time.log sleep 1

Ausgabe:

1.00

Erläuterung:

  • env: /usr/bin/timeanstelle des eingebauten Bash zu finden

  • --format '%e': Druckzeit in Sekunden, siehe man time.

    Dies ist oft das, was ich beim Benchmarking möchte: eine einzelne Zahl anstelle von Minuten + Sekunden.

Und ein wichtiges Muster, das ich oft benutze, ist:

bench-cmd() (
  logfile=time.log
  echo "cmd $@" >> "$logfile"
  printf 'time ' >> "$logfile"
  bench_cmd="env time --append --format '%e' --output '$logfile' $@"
  eval "$bench_cmd"
  echo >> "$logfile"
)

rm -f time.log
bench-cmd sleep 1
bench-cmd sleep 2
bench-cmd sleep 3
cat time.log

GitHub stromaufwärts .

Ausgabe:

cmd sleep 1
time 1.00

cmd sleep 2
time 2.00

cmd sleep 3
time 3.00

Erläuterung:

  • --output: Gibt die Zeit in eine Datei aus.

    Standardmäßig geht die Ausgabe an stderr, daher ist diese Option wichtig, um das Timing vom stderr des Befehls zu trennen.

  • --append: an die Datei anhängen anstatt zu überschreiben.

    Dadurch kann ich die gesamte Benchmark-Ausgabe in einer einzigen Datei konzentrieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.