我正在使用Perl来读取可能在任何时候被截断的日志文件。如果发生这种情况,我想再次开始读取文件,但默认的Perl行为似乎要等到文件指针赶上。例如,如果我运行以下内容:
perl -e 'open FILE, "test"; while (1) { $line = <FILE>; print "$line"; }'
然后执行:
for i in 1 2 3; do echo $i >> test; done
:>test
for i in 4 5 6 7; do echo $i >> test; done
我得到的输出是:
1
2
3
7
但如果我要做同样的事情,用以下代码替换Perl代码:
tail -f test
然后(忽略尾部输出到stderr)我得到了我想要的输出,即:
1
2
3
4
5
6
7
显然,我不能只使用tail,因为我想对线路本身进行一些处理。我曾经想过的一个想法就是将两者结合起来:
tail -f test | perl -e 'while (1) { $line = <STDIN>; print "$line"; }'
适用于我的Linux开发机器,但遗憾的是不适用于Solaris目标平台。
有什么想法吗?
根据要求,使用File :: Tail的示例如下:
perl -e 'use File::Tail; $file = File::Tail->new("test"); while (defined($line=$file->read)) { print "$line"; }'
如果我像以前一样将数据输入测试,我得到的输出就是:
7
显然不是那么理想。我已经尝试调整File :: Tail将等待的maxinterval,如下所示:
perl -e 'use File::Tail; $file = File::Tail->new(name => "test", maxinterval => 1); while (defined($line=$file->read)) { print "$line"; }'
但在这种情况下,过快地将数据输入测试文件,如下所示:
for i in 1 2 3; do echo $i >> test; done; :>test; for i in 4 5 6 7; do echo $i >> test; done
结果只是:
4
5
6
7
不幸的是,对于我们(非常繁忙的)应用程序来说,这是一个现实的场景。为了便于比较,Linux tail似乎正确处理了这种数据输入速度,所以很明显它可以完成(尽管公平,可能不是在Perl ....?)
答案 0 :(得分:2)
Linux tail
command使用inotify机制来监控文件的更改,而无需重复轮询它以获取更新。这使它能够快速可靠地响应文件中的任何更改。
要在Perl中实现类似功能,您可以使用CPAN中的Linux::Inotify2模块。不幸的是,正如名称所示,此模块仅适用于Linux,因此它无法帮助您将脚本移植到Solaris。
您可能可以使用FAM模块来代替SGI::FAM;如果没有可用的本机文件更改通知机制,它仍然可以在内部回退到轮询,但至少它应该提供一个相当好的和经过测试的文件轮询实现。
答案 1 :(得分:1)
听起来您希望在Perl中模仿tail
。
如果您有权访问CPAN,则可以使用File::Tail
。
它是纯Perl(不是XS),因此如果没有CPAN访问权限,您可以看到它是如何实现的in the source。
另外,请参阅PerlFAQ5(“我如何在perl中执行tail -f?”)