Đuôi -f, chèn ngắt dòng sau khi đăng nhập không hoạt động trong 3 giây?


14

Khi thực hiện a tail -f error.log, làm thế nào để chèn lập trình ngắt dòng sau khi không có gì được thêm vào tệp trong 3 giây?

(rõ ràng, một khi một dòng ngắt được thêm vào, không nên thêm dòng ngắt nào khác cho đến khi (các) dòng văn bản khác được thêm vào tệp nhật ký)

Chẳng hạn, những dòng này được gắn vào error.log:

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

Đây sẽ là đầu ra trong giao diện điều khiển:

foo
bar
boo

2far
2foo
2bar
2boo

2far

Bạn có thể có thể điều chỉnh chức năng của tôi trong Askubfox.com/a/993821/158442 hoặc sử dụng tsđể thêm dấu thời gian vào đầu ra và xử lý dấu thời gian
muru

1
Đáng nói là nếu bạn đang thực hiện nó một cách tương tác, bạn có thể nhấn phím enter một vài lần. :)
tự đại diện

Câu trả lời:


12

Bạn luôn có thể triển khai tail -f(cũng ở đây, trừ khi bạn không chú ý đến seek(), giống tail -n +1 -fnhư chúng tôi đang bán toàn bộ tệp) bằng tay 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

Hoặc tail -fthực hiện theo đuôi và sử dụng perlđể chèn dòng mới nếu không có đầu vào trong 3 giây:

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

Những người cho rằng bản thân đầu ra không bị chậm lại (như khi đầu ra đi vào một ống không được đọc tích cực).


Phải mất một thời gian dài tôi mới hiểu được tại sao cái thứ hai thực sự hoạt động :)
hobbs 23/218

Tôi đã thử cái đầu tiên và nó đã in TẤT CẢ các tập tin trước đó, vì vậy nó không tối ưu. Cái thứ hai hoạt động như một lá bùa. Tôi đã thêm "đuôi -n 0 -f $ 1 |" tùy chọn (-n 0) để tránh hiển thị các dòng tệp cũ.
Cedric

Câu hỏi nhỏ: Làm cách nào tôi có thể sửa đổi giải pháp thứ hai để hiển thị thêm một dòng dấu gạch ngang (-------) sau 10 giây? (Tôi đã thử nhiều cách, nhưng không thể làm bất cứ điều gì hoạt động)
Cedric

1
@Cedric, xem chỉnh sửa cho điểm đầu tiên của bạn. Yêu cầu thứ hai của bạn sẽ dễ dàng hơn với cách tiếp cận đầu tiên.
Stéphane Chazelas

8

bash+ dategiải pháp:

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)

Trong Bash, bạn có thể sử dụng $SECONDSđể đếm khoảng thời gian. Tôi nghĩ đó là số giây kể từ khi vỏ bắt đầu, không quan trọng khi lấy chênh lệch.
ilkkachu

@ilkkachu, read -thoặc $TMOUT. $SECONDSbị phá vỡ trong bashmksh. time bash -c 'while ((SECONDS < 3)); do :; done'sẽ kéo dài trong khoảng từ 2 đến 3 giây. Tốt hơn nên sử dụng zsh hoặc ksh93 thay vào đây (với typeset -F SECONDS)
Stéphane Chazelas

@ StéphaneChazelas, tôi không nghĩ nó khác với việc sử dụng date +%s. Cả hai đều cho thời gian tính bằng giây đầy đủ, có tác dụng là khoảng thời gian từ 1.9 đến 4.0 trông giống như 3 giây đầy đủ, mặc dù nó thực sự là 2.1. Thật khó để giải quyết vấn đề đó nếu tất cả những gì bạn không thể truy cập vào giây. Nhưng vâng, có lẽ họ nên ngủ ở đây thay vì bận rộn, và sau đó read -tcũng có thể được sử dụng. Ngay cả khi bạn ngủ bằng tay, time bash -c 'while [[ $SECONDS -lt 3 ]]; do sleep 1; done'hoạt động tốt.
ilkkachu

1
ksh93 và zsh đều ổn với điều đó (zsh không sử dụng). Ngay cả với số nguyên $ GIÂY, cài đặt SECONDS=0đảm bảo $SECONDSsẽ đạt 1 trong đúng 1 giây. Đó không phải là trường hợp bashnhư nó sử dụng time()để theo dõi $SECONDSthay vì gettimeofday(). Tôi đã báo cáo lỗi cho mksh, zsh và bash một thời gian trước, chỉ zsh đã được sửa. (điểm tốt về vấn đề là giống nhau date +%s). Lưu ý rằng đây không phải là một bận rộn ở đây, vì chúng ta đang đọc từ đầu ra của tail -fmột đường ống.
Stéphane Chazelas

+1 và Bash có một "phím tắt" bằng cách sử dụng tích hợp printfđể mô phỏng datemà không cần các công cụ bên ngoài hoặc thay thế lệnh : printf -v t '%(%s)T' -1.
David Foerster

6

Pythongiải pháp (với đối số khoảng cách thời gian động ):

tailing_by_time.py kịch bản:

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

Sử dụng:

tail -f error.log | python tailing_by_time.py 3
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.