3

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

4

2 回答 2

2

Linuxtail命令使用inotify机制来监视对文件的更改,而无需反复轮询文件以获取更新。这使其能够快速可靠地响应文件中的任何更改。

要在 Perl 中实现类似的功能,您可以使用 CPAN 中的Linux::Inotify2模块。不幸的是,顾名思义,这个模块只能在 Linux 上运行,所以它不能帮助您将脚本移植到 Solaris。

也许可以将FAMSGI::FAM模块一起使用;如果没有可用的本机文件更改通知机制,它可能仍会在内部退回到轮询,但至少它应该提供一个相当好的和经过测试的文件轮询实现。

于 2013-03-27T14:28:32.267 回答
1

听起来您希望tail在 Perl 中进行模拟。

  • 如果您有权访问 CPAN,则可以使用File::Tail.

    它是纯 Perl(不是 XS),因此如果没有 CPAN 访问权限,您可以看到它是如何在源代码中实现的。

  • 另请参阅PerlFAQ5(“如何在 perl 中执行 tail -f?”)

于 2013-03-27T13:11:57.643 回答