tail -f, günlük 3 saniye boşta kaldıktan sonra satır sonu ekle?


14

A yaparken tail -f error.log, 3 saniye boyunca dosyaya hiçbir şey eklenmedikten sonra programlı olarak satır sonu nasıl eklenir?

(açıkçası, bir satır sonu eklendiğinde, günlük dosyasına başka metin satırları eklenene kadar başka satır sonu eklenmemelidir)

Örneğin, bu satırlar error.log dosyasına eklenir:

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

Bu konsoldaki çıktı olacaktır:

foo
bar
boo

2far
2foo
2bar
2boo

2far

Muhtemelen fonksiyonumu askubuntu.com/a/993821/158442 adresinden uyarlayabilir veya tsçıktıya zaman damgası eklemek ve zaman damgalarını işlemek için kullanabilirsiniz
muru

1
Etkileşimli olarak yapıyorsanız, enter tuşuna sadece birkaç kez basabileceğinizi belirtmek gerekir. :)
Wildcard

Yanıtlar:


12

Her zaman uygulayabileceği tail -f(siz yorumsuz sürece, burada da seek(), daha fazla gibi tail -n +1 -fbiz bütün dosya terk ediyorsun gibi) ile elle perlörneğin:

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

Veya 3 saniye boyunca herhangi bir girdi yoksa tail -fkuyruklamayı yapın ve perlyeni satırları eklemek için kullanın :

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

Bunlar çıktının kendisinin yavaşlamadığını varsayarlar (çıkış aktif olarak okunmayan bir boruya gittiğinde olduğu gibi).


İkincisinin neden işe yaradığını anlamak uzun zaman aldı :)
ocaklar

İlkini denedim ve TÜM dosyaları elden önce yazdırdı, bu yüzden optimal değil. İkincisi bir cazibe gibi çalışır. Ben ekledim "kuyruk -n 0 -f $ 1 |" seçeneği (-n 0) eski dosya satırlarının görüntülenmesini önler.
Cedric

Küçük soru: 10 saniye sonra ikinci çözümü ek tire çizgisi (-------) görüntülemek için nasıl değiştirebilirim? (Birden çok yol denedim, ama hiçbir şey işe yaramaz)
Cedric

1
@Cedric, ilk noktanız için düzenlemeye bakın. İkinci yaklaşımınız ilk yaklaşımla daha kolay olacaktır.
Stéphane Chazelas

8

bash+ dateçözüm:

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)

Bash'te $SECONDSzaman aralıklarını saymak için kullanabilirsiniz . Bence kabuk başladığından bu yana geçen saniye sayısı, bir fark alırken önemli değil.
ilkkachu

@ilkkachu veya read -tveya $TMOUT. $SECONDSkırılmış bashve mksh. time bash -c 'while ((SECONDS < 3)); do :; done'2 ila 3 saniye sürecek. Burada zsh veya typeset -F SECONDS
ksh93

@ StéphaneChazelas, kullanmaktan farklı olduğunu düşünmüyorum date +%s. Her ikisi de tam saniye olarak zaman verir, yani 1,9 ila 4,0 aralığının gerçekten 2,1 olmasına rağmen 3 tam saniye gibi görünmesi etkisi vardır. Kesirli saniyelere erişemiyorsanız, bunun etrafında çalışmak zor. Ama evet, muhtemelen meşgul olmak yerine burada uyumalılar ve sonra read -tda kullanılabilirler. Elle uysanız bile, time bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'gayet iyi çalışıyor.
ilkkachu

1
ksh93 ve zsh ile sorun yok (zsh eskiden değil). $ SECONDS tamsayı ile bile, ayar tam 1 saniyede 1'e ulaşmasını SECONDS=0sağlar $SECONDS. Bunun yerine izlemek bashiçin kullandığı durum böyle değildir . Bir süre önce mksh, zsh ve bash hatalarını bildirdim, sadece zsh düzeltildi. (konunun aynı olmasıyla ilgili iyi bir nokta ). Burada borunun çıkışından okuduğumuz için burada bir meşgul döngüsü olmadığını unutmayın . time()$SECONDSgettimeofday()date +%stail -f
Stéphane Chazelas

1 ve Bash bir "kısa yol" kullanarak vardır yerleşik printftaklit dateharici araçlara veya komut ikamesi olmadan: printf -v t '%(%s)T' -1.
David Foerster

6

Pythonçözüm (dinamik zaman boşluğu argümanı ile):

tailing_by_time.py senaryo:

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

Kullanımı:

tail -f error.log | python tailing_by_time.py 3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.