Хвост с состоянием (показывает только новые строки из последнего выполнения) - PullRequest
5 голосов
/ 29 октября 2008

Я хочу видеть, сколько строк было добавлено в файл с момента последнего запроса, без повторного чтения всего файла.

Что-то вроде:

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

Было бы предпочтительнее решение на простом Perl, поскольку у меня нет простого доступа к компилятору.

Ответы [ 4 ]

2 голосов
/ 30 октября 2008

Я реализовал минимальную версию чистой версии 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 = "$ENV{HOME}/.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);

@ Дейв: Это почти как твой алгоритм, за исключением того, что я не использую скажи , а только внутренний счетчик.

2 голосов
/ 29 октября 2008

Может быть, этот пакет Perl может помочь вам:

File :: Tail :: Мульти

Созданная из 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";
2 голосов
/ 30 октября 2008

Несмотря на то, что он использовал строки для других целей, я написал код, который по существу делает это раньше.

Все, что вам нужно сделать, это записать смещение байтов (с рассказать ) и индекс (с stat ) для каждого файла после завершения хвоста. В следующий раз, когда он запустится с файлом, сначала проверьте inode (с stat ) еще раз. Если индекс изменен или файл меньше записанного смещения, то это другой файл (удаленный и воссозданный, журнал был повернут и т. Д.), Поэтому вы должны показать его с самого начала; в противном случае ищет записанного смещения и отображает его оттуда.

2 голосов
/ 29 октября 2008

, поскольку делает именно это, хотя и в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...