-f, แทรกตัวแบ่งบรรทัดหลังจากบันทึกไม่ได้ใช้งานเป็นเวลา 3 วินาที?


14

เมื่อทำ a tail -f error.log, วิธีแทรกเส้นแบ่งโดยทางโปรแกรมหลังจากไม่มีสิ่งใดถูกผนวกเข้ากับไฟล์เป็นเวลา 3 วินาที?

(เห็นได้ชัดว่าเมื่อมีการเพิ่มตัวแบ่งบรรทัดหนึ่งบรรทัดไม่ควรเพิ่มตัวแบ่งบรรทัดอื่น ๆ จนกว่าจะมีการเพิ่มบรรทัดข้อความอื่น ๆ ลงในไฟล์บันทึก)

ตัวอย่างเช่นบรรทัดเหล่านี้ถูกผนวกเข้ากับ error.log:

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

นี่จะเป็นผลลัพธ์ในคอนโซล:

foo
bar
boo

2far
2foo
2bar
2boo

2far

คุณสามารถปรับฟังก์ชั่นของฉันได้ที่askubuntu.com/a/993821/158442หรือใช้tsเพื่อเพิ่มการประทับเวลาในเอาต์พุตและประมวลผลการประทับเวลา
muru

1
น่าจะพูดถึงว่าถ้าคุณทำมันแบบโต้ตอบคุณสามารถกดปุ่ม Enter หลายครั้ง :)
ไวด์การ์ด

คำตอบ:


12

คุณสามารถนำไปใช้งานได้tail -f(ที่นี่เว้นแต่คุณจะไม่แสดงseek()ความคิดเห็นเช่นเดียวtail -n +1 -fกับที่เราทิ้งไฟล์ทั้งหมด) ด้วยมือperlเช่น:

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

หรือปล่อยให้tail -ftailing และใช้perlเพื่อแทรก newlines หากไม่มีการป้อนข้อมูลเป็นเวลา 3 วินาที:

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

สิ่งเหล่านั้นสมมติว่าเอาต์พุตไม่ได้ถูกทำให้ช้าลง (เช่นเมื่อเอาต์พุตไปยังไพพ์ที่ไม่ได้อ่านอย่างกระตือรือร้น)


ผมใช้เวลานานที่จะคิดออกว่าทำไมคนที่สองใช้งานได้จริง :)
ฮอบส์

ฉันได้ลองใช้ไฟล์แรกแล้วมันจะพิมพ์ไฟล์ทั้งหมดก่อนถึงมือจึงไม่เหมาะ คนที่สองทำงานเหมือนจับใจ ฉันได้เพิ่ม "tail -n 0 -f $ 1 |" ตัวเลือก (-n 0) เพื่อหลีกเลี่ยงการแสดงบรรทัดไฟล์เก่า
เซดริก

คำถามเล็ก ๆ : ฉันจะแก้ไขวิธีที่สองเพื่อแสดงเส้นประเพิ่มเติม (-------) หลังจาก 10 วินาทีได้อย่างไร (ฉันได้ลองหลายวิธีแล้ว แต่ไม่สามารถทำงานอะไรได้)
Cedric

1
@Cedric ดูการแก้ไขสำหรับจุดแรกของคุณ ความต้องการที่สองของคุณจะง่ายขึ้นด้วยวิธีแรก
Stéphane Chazelas

8

bash+ dateทางออก:

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 คุณสามารถใช้$SECONDSเพื่อนับช่วงเวลา ฉันคิดว่ามันเป็นจำนวนวินาทีตั้งแต่กระสุนเริ่มขึ้นไม่ใช่ว่ามันสำคัญสำหรับการสร้างความแตกต่าง
ilkkachu

@ilkkachu หรือหรือread -t เสียในและ. จะมีอายุประมาณ 2 ถึง 3 วินาที ดีกว่าที่จะใช้ zsh หรือ ksh93 แทนที่นี่ (พร้อม)$TMOUT$SECONDSbashmkshtime bash -c 'while ((SECONDS < 3)); do :; done'typeset -F SECONDS
Stéphane Chazelas

@ date +%sStéphaneChazelasผมไม่คิดว่ามันแตกต่างกว่าการใช้ ทั้งคู่ให้เวลาเป็นวินาทีเต็มซึ่งมีผลต่อช่วงเวลาตั้งแต่ 1.9 ถึง 4.0 ดูเหมือน 3 วินาทีเต็มแม้ว่าจะเป็น 2.1 จริงๆ เป็นการยากที่จะแก้ไขหากคุณไม่สามารถเข้าถึงเศษส่วนวินาทีได้ แต่ใช่พวกเขาน่าจะนอนที่นี่แทนที่จะยุ่งอยู่แล้วจากนั้นก็read -tสามารถใช้งานได้เช่นกัน แม้ว่าคุณจะนอนด้วยตนเองtime bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'ทำงานได้ดี
ilkkachu

1
ksh93 และ zsh ใช้ได้กับสิ่งนั้น (zsh ไม่ใช้) แม้จะมีจำนวน $ SECONDS จำนวนเต็มการตั้งค่ายังSECONDS=0ช่วยให้มั่นใจว่า$SECONDSจะถึง 1 ใน 1 วินาที นั่นไม่ใช่กรณีที่มีการbashที่จะใช้time()ในการติดตามแทน$SECONDS gettimeofday()ฉันรายงานข้อผิดพลาดไปยัง mksh, zsh และ bash เมื่อไม่นานมานี้ zsh เท่านั้นที่ได้รับการแก้ไข (จุดดีเกี่ยวกับปัญหาเหมือนกันกับdate +%s) โปรดทราบว่านี่ไม่ใช่งานยุ่งที่นี่เนื่องจากเรากำลังอ่านจากเอาต์พุตของtail -fไปป์
Stéphane Chazelas

1 และทุบตีมี "ทางลัด" ที่ใช้ในตัวprintfที่จะเลียนแบบไม่มีเครื่องมือภายนอกหรือแทนคำสั่ง:date printf -v t '%(%s)T' -1
David Foerster

6

Pythonโซลูชัน (พร้อมอาร์กิวเมนต์ช่องว่างเวลาแบบไดนามิก):

tailing_by_time.py สคริปต์:

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

การใช้งาน:

tail -f error.log | python tailing_by_time.py 3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.