2008-10-29 5 views
5

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

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

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

Решения в простом Perl будет предпочитаемым, так как я не имею легкий доступ к компилятору.

ответ

2

Хотя он потребляет линии для других целей, я написал код, который делает это раньше.

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

2

since делает именно, что хотя в С.

+0

Возможно, вы только что отредактировали свой вопрос. – Axeman 2008-10-30 05:22:46

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 => Tail файл/вар/ADM/сообщения
  • OutputPrefix => Prepend имя файла начале каждой строки атрибута объекта «звуковая колонка "
  • $tail1->read: Читать все строки из файлов
  • $tail1->print: печать всей строки в атрибуте объекта« LineArray »;
+0

Это * получил *, чтобы быть ответом perl! – Axeman 2008-10-30 05:29:00

2

Я реализовал минимальную версию чистой версии 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); 

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