读取可能在Perl中截断的文件

时间:2013-03-27 12:44:53

标签: perl file-io truncate

我正在使用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 ....?)

2 个答案:

答案 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?”)