bash v5 et $EPOCHREALTIME
-
EPOCHREALTIME
valeur à virgule flottante avec une granularité à la microseconde -
EPOCHSECONDS
le nombre de secondes depuis l'époque Unix
Bonne manière
Simplement :
IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
1. À propos de $EPOCHREALTIME
Veuillez prendre soin :
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.
Donc, si je demande la même variable deux fois dans la même ligne :
echo $EPOCHREALTIME... $EPOCHREALTIME
1572000683.886830... 1572000683.886840
ou plus clairement :
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37
Idem sur mon raspberry-pi :
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246
Donc, demander ces deux temps pour construire la partie entière et la partie fractionnaire est un processus séparé pourrait entraîner des problèmes :(sur la même ligne, premier accès à $ EPOCHREALTIME
pourrait donner :NNN1.999995
, puis suivant :NNN2.000002
. Le résultat deviendra :NNN1.000002
avec 1000000 erreur de micro-seconde)
2. ATTENTION! À propos du mélange $EPOCHSECONDS
et $EPOCHREALTIME
L'utilisation des deux ensemble ne conduit pas seulement au premier bogue mentionné !
$EPOCHSECONDS
utiliser l'appel au time()
qui n'est pas mis à jour en permanence, tandis que $EPOCHREALTIME
utiliser l'appel au gettimeofday()
! Les résultats peuvent donc être très différents :
J'ai trouvé cette réponse à time() et gettimeofday() renvoient des secondes différentes avec une bonne explication.
Si j'essaie sur mon hébergeur :
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
}
(
Remarque :j'utilise read -t
au lieu de sleep
, car sleep
n'est pas intégré
Nota2 :vous pouvez jouer avec l'argument de la fonction pour modifier la valeur du délai de lecture (veille)
)
Cela pourrait rendre quelque chose de simple :
$ 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
Où partie entière de $EPOCHREALTIME
pourrait augmenter de plus de 8 000 microsecondes avant $EPOCHSECONDS
(sur mon hébergeur).
Remarque : Cela semble être lié à un bogue , le résultat peut différer beaucoup entre différents hôtes ou sur le même hôte après le redémarrage, et d'autres choses... Étrangement, je pourrais les reproduire sur de nombreux hôtes différents (Intel Core, Intel Xeon, Amd64..) mais pas sur raspberry pi ! ? (Même Debian bash v5.0.3(1)-release), version différente du noyau.
Correct : Ce n'est pas un bug! Mélange time()
et gettimeofday()
est un bug !
Alors évitez d'utiliser les deux ensemble !!!
3. À propos de printf "..%06.0f"
Remarque :j'utilise %06.0f
au lieu de %d
pour assurer $NSEC
à interpréter comme un nombre décimal (flottant), (empêcher l'interprétation octale si la variable commence par 0
).
Comparez :
printf "nn.%06.0f\n" 012345
nn.012345
printf "nn.%06.0f\n" 098765
nn.098765
et
printf "nn.%d\n" 012345
nn.5349
printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0
Échantillon exécuté
Petit essai :
attendez la seconde suivante, puis imprimez l'heure actuelle avec des micro-secondes
while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
IFS=. read ESEC NSEC <<< $EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done
Vous pouvez terminer ce test en appuyant sur Retour
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