有状态的尾巴(仅显示上次执行的新行)

Posted

技术标签:

【中文标题】有状态的尾巴(仅显示上次执行的新行)【英文标题】:Stateful tail (only shows the new lines from the last execution) 【发布时间】:2010-09-19 21:08:23 【问题描述】:

我希望能够查看自上次查询以来向文件中添加了多少行,而无需再次读取整个文件。

类似:

ptail my_file | fgrep "[ERROR]" | wc -l 

最好使用简单的 Perl 解决方案,因为我无法轻松访问编译器。

【问题讨论】:

【参考方案1】:

since 正是这样做的,尽管它是在 C 中。

【讨论】:

【参考方案2】:

也许这个 Perl 包可以帮助你:

File::Tail::Multi

从 MultiTail 派生,这个 perl 库可以很容易地使用完整的正则表达式跟踪文件的动态列表和匹配/排除行,甚至在本地维护它们的状态。

示例使用 File::Tail::Multi;

$tail1=File::Tail::Multi->new (  OutputPrefix => "f", 
                                 Debug => "$True", 
                                 Files => ["/var/adm/messages"]
                              );
while(1) 
    $tail1->read;
    #
    $tail1->print;
    sleep 10;

$tail1=File::Tail::Multi->new : 创建新的 ptail 对象 Files => 尾文件 /var/adm/messages OutputPrefix => 在对象属性“LineArray”中每行的开头添加文件名 $tail1->read : 从文件中读取所有行 $tail1->print : 打印对象属性“LineArray”中的所有行;

【讨论】:

那是 得到 成为 perl 的答案! 这里状态保持不变,但仅在程序的一次执行中。我希望在程序执行期间保存状态。【参考方案3】:

虽然它出于其他目的消耗了这些行,但我之前已经编写了基本上这样做的代码。

您需要做的就是在尾部完成后记录每个文件的字节偏移量(使用tell)和inode(使用stat)。下次针对文件运行时,首先再次检查 inode(使用 stat)。如果 inode 已更改或文件小于记录的偏移量,则它是不同的文件(删除并重新创建,日志已旋转等),因此您应该从头开始显示;否则,寻找记录的偏移量并从那里显示。

【讨论】:

【参考方案4】:

我实现了一个纯 Perl 版本的最小版本:

#! /usr/bin/perl
# Perl clone of since(1)
# http://welz.org.za/projects/since
#

use strict;
use warnings;

use Fcntl qw/ SEEK_SET O_RDWR O_CREAT /;
use NDBM_File;

my $state_file = "$ENVHOME/.psince";

my %states;
tie(%states, 'NDBM_File', $state_file, O_CREAT | O_RDWR, 0660)
        or die("cannot tie state to $state_file : $!");

while (my $filename = shift) 
        if (! -r $filename) 
                # Ignore
                next;
        
        my @file_stats = stat($filename);
        my $device = $file_stats[0];
        my $inode = $file_stats[1];
        my $size = $file_stats[7];
        my $state_key = $device . "/" .$inode;
        print STDERR "state_key=$state_key\n";

        if (! open(FILE, $filename) ) 
                print STDERR "cannot open $filename : $!";
                next;
        

        # Reverting to the last cursor position
        my $offset = $states$state_key || 0;
        if ($offset <= $size) 
                sysseek(FILE, $offset, SEEK_SET);
         else 
                # file was truncated, restarting from the beginning
                $offset = 0;
        

        # Reading until the end
        my $buffer;
        while ((my $read_count = sysread(FILE, $buffer, 4096)) > 0) 
                $offset += $read_count;
                print $buffer;
        
        # Nothing to read
        close(FILE);
        $states$state_key = $offset;


# Sync the states
untie(%states);

@Dave:这几乎就像你的算法,只是我不使用 tell,而是使用内部维护的计数器。

【讨论】:

以上是关于有状态的尾巴(仅显示上次执行的新行)的主要内容,如果未能解决你的问题,请参考以下文章

如何在另一个网站显示 OBIEE 报告的上次刷新状态?

标题或状态行中的“上次修改”时间

仅在手机上呈现带有状态的 div

使用后台线程时有效显示文件状态

windows10开机显示“你的设备处于脱机状态 请使用上次在此设备上使用的密码登录” 我用不正确

linux-网络状态