有没有一种方法可以在不中断输出的情况下,从管道尾部命令中每分钟打印一次时间



我有一个通过ssh(例如tail -f <file>|egrep -v "lol")执行的长尾命令,通常没有太多输出,我希望确保连接是实时的,并希望每60或300秒打印一次时间。

您应该能够改变命令的顺序,并在tail -f输出中获得date

( while : ; do date; sleep 60; done )& tail -f <file>|egrep -v "lol"; kill %1

注意:您正在备份每60秒提供一次日期的进程,因此您需要在完成kill %1时终止备份作业。如果您有多个后台进程,则需要获取作业编号。我试过使用syslog,它似乎有效。如果它在你的情况下有效,请报告。

尝试:

tail -f file | perl -ne 'BEGIN{$|=1} print unless /lol/'

当然,如果你只是想打印时间戳,可以试试:

tail -f file | { while sleep 60; do date; done& grep -v lol; }

在管道末端附加一个类似的小脚本:

#!/bin/bash
while : ; do
    # Read input with timeout
    read -t 10 line
    # Output if we got anything and remember current time in "last"
    [[ $? -eq 0 ]] && last=$(date +%s) && echo $line
    # Check if we are due a timestamp and output if required
    now=$(date +%s)
    diff=$((now-last))
    [[ $diff -ge 60 ]] && last=$(date +%s) && date
done

它从stdin读取,超时时间为10秒。如果数据源源不断,它就会不断打印。每次进行某些输出时,它都会使用上次输出的时间更新变量last。然后,每次它都会检查在过去60 seonds中是否有任何输出,如果没有,则输出当前时间。

将上面的内容保存在一个名为monitor的文件中,然后使其可执行(仅一次)并运行如下:

chmod +x monitor
yourpipe ...| ... | ./monitor

它可以缩写为以牺牲一些清晰度为代价,比如这样。此外,可以通过使用内置的bash SECONDS来避免date的exec:

#!/bin/bash
last=$SECONDS
while : ; do
    read -t 10 line && [[ $? -eq 0 ]] && last=$SECONDS && echo $line
    [[ $(($SECONDS-last)) -ge 60 ]] && last=$SECONDS && date
done

或者,稍微不同的方法。。。制作一个FIFO,并将原始管道的输出发送到那里,然后跟踪它,但在后台,有一个小循环,也会每分钟向FIFO发送一次时间戳。像这样的东西(未经测试)

mkfifo FIFO
original_pipe | ... | ... > FIFO &

现在每60秒向FIFO中注入一个时间戳:

while :; do date > FIFO; sleep 60; done &

现在只跟踪FIFO

tail -F FIFO

最新更新