bash v5 a $EPOCHREALTIME
-
EPOCHREALTIME
hodnota s plovoucí desetinnou čárkou s mikrosekundovou zrnitostí -
EPOCHSECONDS
počet sekund od epochy Unix
Správný způsob
Jednoduše:
IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
1. O $EPOCHREALTIME
Dávejte pozor:
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.
Pokud tedy požádám o stejnou proměnnou dvakrát na stejném řádku:
echo $EPOCHREALTIME... $EPOCHREALTIME
1572000683.886830... 1572000683.886840
nebo jasněji:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37
To samé na mém malinovém pi:
printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694
echo $(( -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246
Takže dotazování na tento čas pro vytvoření intergerové části a odděleného procesu zlomkové části by mohlo vést k problémům:(Na stejné lince první přístup k $ EPOCHREALTIME
může dát:NNN1.999995
, pak další:NNN2.000002
. Výsledek bude:NNN1.000002
s 1000000 chyba mikrosekund)
2. VAROVÁNÍ! O míchání $EPOCHSECONDS
a $EPOCHREALTIME
Použití obou dohromady nejenže vede k první zmíněné chybě!
$EPOCHSECONDS
použijte volání na time()
který se neaktualizuje neustále, zatímco $EPOCHREALTIME
použijte volání gettimeofday()
! Takže výsledky se mohou hodně lišit:
Našel jsem tuto odpověď na time() a gettimeofday() vrací různé sekundy s dobrým vysvětlením.
Pokud to zkusím na svém hostiteli:
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
}
(
Poznámka:Používám read -t
místo sleep
, protože sleep
není vestavěný
Poznámka2:Můžete si pohrát s argumentem funkce, abyste změnili hodnotu časového limitu čtení (spánku)
)
To by mohlo něco vykreslit:
$ 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
Kde celá část z $EPOCHREALTIME
se může zvýšit o více než 8 000 mikrosekund před $EPOCHSECONDS
(na mém hostiteli).
Poznámka: Zdá se, že to souvisí s nějakou chybou , výsledek se může mezi různými hostiteli nebo na stejném hostiteli po restartu hodně lišit a další věci... Kupodivu jsem je mohl reprodukovat na mnoha různých hostitelích (Intel Core, Intel Xeon, Amd64..), ale ne na raspberry pi! ? (Stejné vydání Debian bash v5.0.3(1), jiná verze jádra.
Správně: To není chyba! Míchání time()
a gettimeofday()
je chyba!
Vyhněte se tedy použití obou současně !!!
3. O printf "..%06.0f"
Poznámka:Používám %06.0f
místo %d
abyste zajistili $NSEC
být interpretován jako desetinné číslo (s plovoucí desetinnou čárkou), (zabránit osmičkové interpretaci, pokud proměnná začíná 0
).
Porovnejte:
printf "nn.%06.0f\n" 012345
nn.012345
printf "nn.%06.0f\n" 098765
nn.098765
a
printf "nn.%d\n" 012345
nn.5349
printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0
Ukázkový běh
Malý test:
počkejte do další sekundy a poté vytiskněte aktuální čas v mikrosekundách
while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
IFS=. read ESEC NSEC <<< $EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done
Tento test můžete ukončit stisknutím Return
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