bash v5 e $EPOCHREALTIME
-
EPOCHREALTIME
valore in virgola mobile con granularità di microsecondi -
EPOCHSECONDS
il numero di secondi dall'epoca Unix
Modo corretto
Semplicemente:
IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
1. Circa $EPOCHREALTIME
Si prega di prestare attenzione:
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.
Quindi, se chiedo la stessa variabile due volte nella stessa riga:
echo $EPOCHREALTIME... $EPOCHREALTIME
1572000683.886830... 1572000683.886840
o più chiaramente:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37
Lo stesso sul mio raspberry-pi:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246
Quindi chiedere questa due volte per costruire la parte intera e la parte frazionaria è un processo separato potrebbe portare a problemi:(Sulla stessa riga primo accesso a $ EPOCHREALTIME
potrebbe dare:NNN1.999995
, quindi successivo:NNN2.000002
. Il risultato diventerà:NNN1.000002
con 1000000 errore di microsecondi)
2. AVVERTIMENTO! A proposito di mescolare $EPOCHSECONDS
e $EPOCHREALTIME
L'uso di entrambi insieme non solo porta al bug menzionato per primo!
$EPOCHSECONDS
usa la chiamata a time()
che non viene aggiornato costantemente, mentre $EPOCHREALTIME
usa la chiamata a gettimeofday()
! Quindi i risultati potrebbero differire molto:
Ho trovato Questa risposta a time() e gettimeofday() restituiscono secondi diversi con una buona spiegazione.
Se provo sul mio host:
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
}
(
Nota:io uso read -t
invece di sleep
, perché sleep
non è integrato
Nota2:potresti giocare con l'argomento della funzione per cambiare il valore del timeout di lettura (sleep)
)
Questo potrebbe rendere qualcosa di piccolo:
$ 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
Dove parte intera di $EPOCHREALTIME
potrebbe aumentare di oltre 8000 microsecondi prima di $EPOCHSECONDS
(sul mio host).
Nota: Questo sembra essere collegato a qualche bug , il risultato potrebbe differire molto tra host diversi o sullo stesso host dopo il riavvio e altre cose ... Stranamente potrei riprodurli su molti host diversi (Intel Core, Intel Xeon, Amd64 ..) ma non su Raspberry Pi! ? (Stesso rilascio di Debian bash v5.0.3(1)), diversa versione del kernel.
Corretto: Questo non è un bug! Mescolando time()
e gettimeofday()
è un bug!
Quindi evita di usarli entrambi insieme!!!
3. Informazioni su printf "..%06.0f"
Nota:utilizzo %06.0f
invece di %d
per garantire $NSEC
da interpretare come decimale (virgola mobile), (impedisci l'interpretazione ottale se la variabile inizia con 0
).
Confronta:
printf "nn.%06.0f\n" 012345
nn.012345
printf "nn.%06.0f\n" 098765
nn.098765
e
printf "nn.%d\n" 012345
nn.5349
printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0
Esecuzione di esempio
Piccolo test:
attendere fino al secondo successivo, quindi stampare l'ora corrente con i microsecondi
while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
IFS=. read ESEC NSEC <<< $EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done
Puoi terminare questo test premendo Invio
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