Использование простой замены для logdump
#! /usr/bin/perl
use warnings;
use strict;
open my $fh, ">", "log" or die "$0: open: $!";
select $fh;
$| = 1; # disable buffering
for (1 .. 10) {
print $fh "message $_\n" or warn "$0: print: $!";
sleep rand 5;
}
и скелет для extract
ниже, чтобы получить необходимую обработку. Когда logfile
встречает конец файла, logfile.eof()
имеет значение true. Вызов logfile.clear()
сбрасывает все состояние ошибки, а затем мы спим и пытаемся снова.
#include <iostream>
#include <fstream>
#include <cerrno>
#include <cstring>
#include <unistd.h>
int main(int argc, char *argv[])
{
const char *path;
if (argc == 2) path = argv[1];
else if (argc == 1) path = "log";
else {
std::cerr << "Usage: " << argv[0] << " [ log-file ]\n";
return 1;
}
std::ifstream logfile(path);
std::string line;
next_line: while (std::getline(logfile, line))
std::cout << argv[0] << ": extracted [" << line << "]\n";
if (logfile.eof()) {
sleep(3);
logfile.clear();
goto next_line;
}
else {
std::cerr << argv[0] << ": " << path << ": " << std::strerror(errno) << '\n';
return 1;
}
return 0;
}
Это не так интересно, как смотреть его вживую, но на выходе получается
./extract: extracted [message 1]
./extract: extracted [message 2]
./extract: extracted [message 3]
./extract: extracted [message 4]
./extract: extracted [message 5]
./extract: extracted [message 6]
./extract: extracted [message 7]
./extract: extracted [message 8]
./extract: extracted [message 9]
./extract: extracted [message 10]
^C
Я оставил прерывание на выходе, чтобы подчеркнуть, что это бесконечный цикл.
Используйте Perl в качестве языка склеивания, чтобы extract
получал строки из журнала с помощью tail
:
#! /usr/bin/perl
use warnings;
use strict;
die "Usage: $0 [ log-file ]\n" if @ARGV > 1;
my $path = @ARGV ? shift : "log";
open my $fh, "-|", "tail", "-c", "+1", "-f", $path
or die "$0: could not start tail: $!";
while (<$fh>) {
chomp;
print "$0: extracted [$_]\n";
}
Наконец, если вы настаиваете на том, чтобы выполнять тяжелую работу самостоятельно, есть связанных с Perl FAQ :
Как мне сделать tail -f в Perl?
Первая попытка
seek(GWFILE, 0, 1);
Оператор seek(GWFILE, 0, 1)
не меняет текущую позицию, но он очищает условие конца файла на дескрипторе, поэтому следующий <GWFILE>
заставляет Perl снова пытаться что-то прочитать.
Если это не сработает (зависит от особенностей вашей реализации stdio), тогда вам нужно что-то похожее на это:
for (;;) {
for ($curpos = tell(GWFILE); <GWFILE>; $curpos = tell(GWFILE)) {
# search for some stuff and put it into files
}
# sleep for a while
seek(GWFILE, $curpos, 0); # seek to where we had been
}
Если это все еще не работает, посмотрите на метод clearerr
из IO::Handle
, который сбрасывает ошибки и состояния конца файла в дескрипторе.
Также есть модуль File::Tail
от CPAN.