使用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() 为真。调用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: 提取 [消息 1]
./extract: 提取 [消息 2]
./extract: 提取 [消息 3]
./extract: 提取 [消息 4]
./extract: 提取 [消息 5]
./extract: 提取 [消息 6]
./extract: 提取 [消息 7]
./extract: 提取 [消息 8]
./extract: 提取 [消息 9]
./extract: 提取 [消息 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";
}
最后,如果你坚持自己做繁重的工作,有一个related Perl FAQ:
如何在 perl 中执行 tail -f?
第一次尝试
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
}
如果这仍然不起作用,请查看 IO::Handle 中的 clearerr 方法,该方法会重置句柄上的错误和文件结束状态。
还有一个来自 CPAN 的 File::Tail 模块。