tail -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键。:)
通配符'18

Answers:


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 -f拖尾,perl如果3秒钟内没有输入,则用于插入换行符:

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

这些假定输出本身不会降低速度(例如,当输出进入未主动读取的管道时)。


我花了很长时间才弄清楚第二个为什么真正起作用:)
hobbs '18

我尝试过第一个,它会事先打印所有文件,因此不是最佳选择。第二个作品就像一种魅力。我添加了“ tail -n 0 -f $ 1 |” 选项(-n 0),以避免显示文件的旧行。
Cedric

小问题:如何修改第二个解决方案以在10秒后显示额外的破折号(-------)?(我已经尝试了多种方法,但无法完成任何工作)
Cedric

1
@Cedric,请首先编辑。使用第一种方法,您的第二个要求会更容易。
斯特凡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或者$TMOUT$SECONDS被打破bashmkshtime bash -c 'while ((SECONDS < 3)); do :; done'将持续2到3秒。最好使用的zsh或ksh93的,而不是在这里(含typeset -F SECONDS
斯特凡Chazelas

@StéphaneChazelas,我认为这与使用没有什么不同date +%s。两者都给出了整秒的时间,这的确使从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通过管道读取输出。
斯蒂芬·查泽拉斯

+1和Bash使用内置的“快捷方式”进行printf仿真,date而无需外部工具或命令替代:printf -v t '%(%s)T' -1
David Foerster '18

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.