tail -f, masukkan line break setelah log kosong selama 3 detik?


14

Ketika melakukan a tail -f error.log, bagaimana cara memasukkan terputus secara terprogram setelah tidak ada yang ditambahkan ke file selama 3 detik?

(tentu saja, setelah satu jeda baris ditambahkan, tidak ada jeda baris lain yang harus ditambahkan sampai baris teks ditambahkan ke file log)

Misalnya, baris-baris ini ditambahkan ke error.log:

foo
bar
boo [[wait 4 seconds]]
2far
2foo
2bar
2boo [[wait 40 seconds]]
2far

Ini akan menjadi output di konsol:

foo
bar
boo

2far
2foo
2bar
2boo

2far

Anda mungkin dapat menyesuaikan fungsi saya di askubuntu.com/a/993821/158442 , atau gunakan tsuntuk menambahkan timestamping ke output dan memproses cap waktu
muru

1
Layak disebutkan bahwa jika Anda melakukannya secara interaktif, Anda bisa menekan tombol enter beberapa kali. :)
Wildcard

Jawaban:


12

Anda selalu dapat mengimplementasikan tail -f(yah di sini, kecuali Anda menghapus tanda komentar seek(), lebih seperti tail -n +1 -fsaat kita membuang seluruh file) dengan tangan perlmisalnya:

perl -e '
  $| = 1;
  # seek STDIN, 0, 2; # uncomment if you want to skip the text that is
                      # already there. Or if using the ksh93 shell, add
                      # a <((EOF)) after < your-file
  while (1) {
    if ($_ = <STDIN>) {
      print; $t = 0
    } else {
      print "\n"            if $t == 3;
      # and a line of "-"s after 10 seconds:
      print "-" x 72 . "\n" if $t == 10;
      sleep 1;
      $t++;
    }
  }' < your-file

Atau biarkan tail -ftailing dan gunakan perluntuk memasukkan baris baru jika tidak ada input selama 3 detik:

tail -f file | perl -pe 'BEGIN{$SIG{ALRM} = sub {print "\n"}} alarm 3'

Mereka menganggap bahwa output itu sendiri tidak melambat (seperti ketika output pergi ke pipa yang tidak aktif dibaca).


Butuh waktu lama untuk mencari tahu mengapa yang kedua benar-benar bekerja :)
hobbs

Saya sudah mencoba yang pertama, dan itu mencetak SEMUA file sebelumnya, sehingga tidak optimal. Yang kedua bekerja seperti pesona. Saya telah menambahkan "tail -n 0 -f $ 1 |" opsi (-n 0) untuk menghindari menampilkan baris file lama.
Cedric

Pertanyaan kecil: Bagaimana saya bisa mengubah solusi kedua untuk menampilkan garis tanda hubung tambahan (-------) setelah 10 detik? (Saya telah mencoba berbagai cara, tetapi tidak dapat membuat sesuatu berhasil)
Cedric

1
@Cedric, lihat edit untuk poin pertama Anda. Persyaratan kedua Anda akan lebih mudah dengan pendekatan pertama.
Stéphane Chazelas

8

bash+ datesolusi:

while IFS= read -r line; do        
    prev=$t         # get previous timestamp value
    t=$(date +%s)   # get current timestamp value
    [[ ! -z "$prev" ]] && [[ "$((t-prev))" -ge 3 ]] && echo ""
    echo "$line"    # print current line
done < <(tail -f error.log)

Di Bash, Anda dapat menggunakan $SECONDSuntuk menghitung interval waktu. Saya pikir ini adalah jumlah detik sejak shell dimulai, bukan itu penting ketika mengambil perbedaan.
ilkkachu

@ilkkachu, atau read -tatau $TMOUT. $SECONDSrusak bashdan mksh. time bash -c 'while ((SECONDS < 3)); do :; done'akan bertahan antara 2 dan 3 detik. Lebih baik menggunakan zsh atau ksh93 sebagai gantinya di sini (dengan typeset -F SECONDS)
Stéphane Chazelas

@ StéphaneChazelas, saya tidak berpikir itu berbeda dari menggunakan date +%s. Keduanya memberikan waktu dalam detik penuh, yang memang memiliki efek bahwa interval dari, katakanlah, 1.9 hingga 4.0 terlihat seperti 3 detik penuh, meskipun itu benar-benar 2.1. Sulit untuk menyelesaikannya jika Anda tidak dapat mengakses detik pecahan. Tapi ya, mereka mungkin sebaiknya tidur di sini alih-alih sibuk, dan kemudian read -tbisa digunakan. Bahkan jika Anda tidur secara manual, tetap time bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'bekerja dengan baik.
ilkkachu

1
ksh93 dan zsh tidak masalah dengan itu (zsh digunakan untuk tidak). Bahkan dengan integer $ DETIK, pengaturan SECONDS=0memastikan bahwa $SECONDSakan mencapai 1 tepat 1 detik. Itu tidak terjadi dengan bashseperti yang digunakan time()untuk melacak, $SECONDSbukan gettimeofday(). Saya melaporkan bug ke mksh, zsh dan bash beberapa waktu lalu, hanya zsh yang diperbaiki. (Poin bagus tentang masalah ini sama dengan date +%s). Perhatikan bahwa ini bukan kesibukan di sini, karena kita membaca dari hasil tail -flebih dari satu pipa.
Stéphane Chazelas

1 dan Bash memiliki "jalan pintas" menggunakan built-in printfuntuk meniru datetanpa alat eksternal atau substitusi perintah: printf -v t '%(%s)T' -1.
David Foerster

6

Pythonsolusi (dengan argumen kesenjangan waktu dinamis ):

tailing_by_time.py naskah:

import time, sys

t_gap = int(sys.argv[1])    # time gap argument
ts = 0
while True:
    line = sys.stdin.readline().strip()    # get/read current line from stdin
    curr_ts = time.time()                  # get current timestamp
    if ts and curr_ts - ts >= t_gap:
        print("")                          # print empty line/newline
    ts = curr_ts
    if line:
        print(line)                        # print current line if it's not empty

Pemakaian:

tail -f error.log | python tailing_by_time.py 3
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.