bash v5 und $EPOCHREALTIME
-
EPOCHREALTIME
Fließkommawert mit Mikrosekunden-Granularität -
EPOCHSECONDS
die Anzahl der Sekunden seit der Unix-Epoche
Richtiger Weg
Einfach:
IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
1. Über $EPOCHREALTIME
Bitte beachten:
EPOCHREALTIME Each time this parameter is referenced, it expands to the number of seconds since the Unix Epoch (see time(3)) as a floating point value with micro-second granularity.
Wenn ich also zweimal in derselben Zeile nach derselben Variablen frage:
echo $EPOCHREALTIME... $EPOCHREALTIME
1572000683.886830... 1572000683.886840
oder deutlicher:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37
Dasselbe auf meinem Himbeer-Pi:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246
Daher kann es zu Problemen führen, wenn Sie diese zwei Mal zum Erstellen des ganzzahligen Teils und des Bruchteils abfragen, was zu Problemen führen kann:(In derselben Zeile erster Zugriff auf $ EPOCHREALTIME
könnte geben:NNN1.999995
, dann weiter:NNN2.000002
. Als Ergebnis wird:NNN1.000002
mit 1000000 Mikrosekundenfehler)
2. WARNUNG! Über das Mischen von $EPOCHSECONDS
und $EPOCHREALTIME
Die Verwendung beider zusammen führte nicht nur zum erstgenannten Fehler!
$EPOCHSECONDS
Rufen Sie time()
an die nicht ständig aktualisiert wird, während $EPOCHREALTIME
Verwenden Sie den Aufruf von gettimeofday()
! Die Ergebnisse können also sehr unterschiedlich sein:
Ich habe diese Antwort auf time() und gettimeofday() gefunden, die unterschiedliche Sekunden zurückgeben mit guter Erklärung.
Wenn ich es auf meinem Host versuche:
epochVariableDiff () {
local errcnt=0 lasterrcnt v1 v2 v3 us vals line
while ((errcnt==0)) || ((errcnt>lasterrcnt)); do
lasterrcnt=$errcnt
printf -v vals '%(%s)T %s %s' -1 $EPOCHSECONDS $EPOCHREALTIME
IFS=$' .' read v1 v2 v3 us <<<"$vals"
[ "$v1" = "$v2" ] && [ "$v2" = "$v3" ] || ((errcnt++))
[ $errcnt -eq 1 ] && echo "$line"
printf -v line '%3d %s - %s - %s . %s' $errcnt $v1 $v2 $v3 $us
printf "%s\r" "$line"
((errcnt)) && echo "$line"
read -t ${1:-.0002}
done
}
(
Hinweis:Ich verwende read -t
statt sleep
, weil sleep
ist nicht eingebaut
Nota2:Sie könnten mit dem Argument der Funktion spielen, um den Wert des Lese-Timeouts (sleep) zu ändern.
)
Dies könnte etwas wie folgt darstellen:
$ epochVariableDiff .0002
0 1586851573 - 1586851573 - 1586851573 . 999894
1 1586851573 - 1586851573 - 1586851574 . 000277
2 1586851573 - 1586851573 - 1586851574 . 000686
3 1586851573 - 1586851573 - 1586851574 . 001087
4 1586851573 - 1586851573 - 1586851574 . 001502
5 1586851573 - 1586851573 - 1586851574 . 001910
6 1586851573 - 1586851573 - 1586851574 . 002309
7 1586851573 - 1586851573 - 1586851574 . 002701
8 1586851573 - 1586851573 - 1586851574 . 003108
9 1586851573 - 1586851573 - 1586851574 . 003495
10 1586851573 - 1586851573 - 1586851574 . 003899
11 1586851573 - 1586851573 - 1586851574 . 004400
12 1586851573 - 1586851573 - 1586851574 . 004898
13 1586851573 - 1586851573 - 1586851574 . 005324
14 1586851573 - 1586851573 - 1586851574 . 005720
15 1586851573 - 1586851573 - 1586851574 . 006113
16 1586851573 - 1586851573 - 1586851574 . 006526
17 1586851573 - 1586851573 - 1586851574 . 006932
18 1586851573 - 1586851573 - 1586851574 . 007324
19 1586851573 - 1586851573 - 1586851574 . 007733
19 1586851574 - 1586851574 - 1586851574 . 008144
Wobei ganzzahliger Teil von $EPOCHREALTIME
um mehr als 8000 erhöhen könnte Mikrosekunden vor $EPOCHSECONDS
(auf meinem Host).
Hinweis: Dies scheint mit einem Fehler zusammenzuhängen , das Ergebnis kann sich nach dem Neustart zwischen verschiedenen Hosts oder auf demselben Host stark unterscheiden, und andere Dinge ... Seltsamerweise konnte ich sie auf vielen verschiedenen Hosts (Intel Core, Intel Xeon, Amd64 ...) reproduzieren, aber nicht auf Himbeer-Pi! ? (Gleiches Debian bash v5.0.3(1)-Release), andere Kernel-Version.
Richtig: Das ist kein Fehler! Mischen von time()
und gettimeofday()
ist ein Fehler!
Vermeiden Sie es also, beides zusammen zu verwenden !!!
3. Über printf "..%06.0f"
Hinweis:Ich verwende %06.0f
statt %d
um $NSEC
sicherzustellen als Dezimalzahl (float) zu interpretieren, (oktale Interpretation verhindern, wenn Variable mit 0
beginnt ).
Vergleichen Sie:
printf "nn.%06.0f\n" 012345
nn.012345
printf "nn.%06.0f\n" 098765
nn.098765
und
printf "nn.%d\n" 012345
nn.5349
printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0
Probelauf
Kleiner Test:
bis zur nächsten Sekunde warten, dann aktuelle Zeit mit Mikrosekunden drucken
while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
IFS=. read ESEC NSEC <<< $EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done
Sie können diesen Test beenden, indem Sie Return drücken
2019-10-25:13:16:46.000444
2019-10-25:13:16:47.000489
2019-10-25:13:16:48.000399
2019-10-25:13:16:49.000383
2019-10-25:13:16:50.000508