GNU/Linux >> Belajar Linux >  >> Linux

Mencetak waktu saat ini dalam milidetik atau nanodetik dengan printf bawaan

bash v5 dan $EPOCHREALTIME

  • EPOCHREALTIME nilai floating point dengan perincian mikro-detik

  • EPOCHSECONDS jumlah detik sejak Unix Epoch

Cara yang benar

Cukup:

IFS=. read ESEC NSEC <<<$EPOCHREALTIME
printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC

1. Tentang $EPOCHREALTIME

Harap peduli:

    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.

Jadi, jika saya meminta variabel yang sama dua kali di baris yang sama:

echo $EPOCHREALTIME...  $EPOCHREALTIME 
1572000683.886830... 1572000683.886840

atau lebih jelas:

printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
761893
761925

echo $((  -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
37

Sama di raspberry-pi saya:

printf "%s\n" ${EPOCHREALTIME#*.} ${EPOCHREALTIME#*.}
801459
801694

echo $((  -10#${EPOCHREALTIME#*.} + 10#${EPOCHREALTIME#*.} ))
246

Jadi menanyakan dua kali ini untuk membangun bagian interger dan bagian fraksional proses terpisah dapat menyebabkan masalah:(Pada baris yang sama, akses pertama ke $ EPOCHREALTIME dapat memberikan:NNN1.999995 , lalu berikutnya:NNN2.000002 . Hasilnya akan menjadi:NNN1.000002 dengan 1000000 kesalahan mikro-detik)

2. PERINGATAN! Tentang pencampuran $EPOCHSECONDS dan $EPOCHREALTIME

Menggunakan keduanya bersama-sama tidak hanya menyebabkan bug yang disebutkan pertama!

$EPOCHSECONDS gunakan panggilan ke time() yang tidak diperbarui terus-menerus, sedangkan $EPOCHREALTIME gunakan panggilan ke gettimeofday() ! Jadi hasilnya bisa sangat berbeda:

Saya menemukan jawaban ini untuk time() dan gettimeofday() mengembalikan detik yang berbeda dengan penjelasan yang bagus.

Jika saya mencoba di host saya:

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
}

(
Catatan:Saya menggunakan read -t bukannya sleep , karena sleep tidak dibangun
Nota2:Anda bisa bermain dengan argumen fungsi untuk mengubah nilai batas waktu baca (tidur)
)

Ini bisa membuat sesuatu yang kecil:

$ 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

Di mana bagian bilangan bulat dari $EPOCHREALTIME dapat meningkat lebih dari 8000 mikrodetik sebelum $EPOCHSECONDS (di host saya).

Catatan: Tampaknya ini terkait dengan beberapa bug , hasilnya bisa sangat berbeda antara host yang berbeda atau pada host yang sama setelah reboot, dan hal lainnya...Anehnya, saya dapat memperbanyaknya di banyak host berbeda (Intel Core,Intel Xeon, AMD64..) tetapi tidak pada raspberry pi! ? (Debian bash v5.0.3(1)-release yang sama), versi kernel yang berbeda.

Benar: Ini bukan bug! Mencampur time() dan gettimeofday() adalah bug!

Jadi, hindari menggunakan keduanya secara bersamaan !!!

3. Tentang printf "..%06.0f"

Catatan:Saya menggunakan %06.0f bukannya %d untuk memastikan $NSEC untuk ditafsirkan sebagai desimal (mengambang), (mencegah interpretasi oktal jika variabel dimulai dengan 0 ).

Bandingkan:

printf "nn.%06.0f\n" 012345
nn.012345

printf "nn.%06.0f\n" 098765
nn.098765

dan

printf "nn.%d\n" 012345
nn.5349

printf "nn.%d\n" 098765
-bash: printf: 098765: invalid octal number
nn.0

Contoh operasi

Tes kecil:

tunggu hingga detik berikutnya, lalu cetak waktu saat ini dengan mikrodetik

while ! read -t .$((1000000-10#${EPOCHREALTIME#*.})) foo; do
    IFS=. read ESEC NSEC <<< $EPOCHREALTIME
    printf '%(%F:%T)T.%06.0f\n' $ESEC $NSEC
done

Anda dapat mengakhiri pengujian ini dengan menekan Kembali

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

Linux
  1. Sinkronkan Waktu Server Linux dengan Server Waktu Jaringan

  2. Cara mencetak waktu saat ini (dengan milidetik) menggunakan C++ / C++11

  3. umask saat ini dari proses dengan <pid>

  1. 3 tips untuk mencetak dengan Linux

  2. Kelola NTP dengan Chrony

  3. Pertama kali dengan Linux:30 kisah instalasi

  1. Tanggal Dalam Milidetik Di Openwrt Di Arduino Yun?

  2. Proses Waktu Mulai Dengan Zona Waktu?

  3. Menggunakan warna dengan printf