简体   繁体   English

在Perl中是否有一个等效的“ tail -f”?

[英]Is there an equivalent of `tail -f` in Perl?

I'm writing a script that listens for changes to a log file and acts appropriately. 我正在编写一个脚本,侦听日志文件的更改并采取适当的措施。 At the moment I'm using open my $fh, "tail -f $logfile |"; 目前,我正在使用open my $fh, "tail -f $logfile |"; but ideally I don't want to use system calls. 但理想情况下,我不想使用系统调用。

I've tried File::Tail but it has a minimum interval of 1 second (I've tried passing less but it defaults to 1 second, even if I pass 0). 我已经尝试过File :: Tail,但是它的最小间隔为1秒(我尝试了传递的时间更少,但是即使我传递了0,它也默认为1秒)。 I've checked the source for it and it seems to be using sleep() which takes an integer. 我已经检查了它的来源,它似乎正在使用sleep(),它需要一个整数。 Before I try to write my own, are there any other options? 在尝试编写自己的书之前,还有其他选择吗?

Thanks. 谢谢。

  1. Did you know that tail -f also uses a 1-second sleep by default? 您是否知道tail -f默认还使用1秒睡眠? It's true! 这是真的! (At least for GNU tail...) (至少对于GNU尾巴...)
  2. File::Tail actually uses Time::HiRes 's sleep function, which means that the sleep time parameter isn't an integer; File::Tail实际上使用Time :: HiRessleep函数,这意味着sleep time参数不是整数; you can set it to any fractional number of seconds that your system can deal with. 您可以将其设置为系统可以处理的任意秒数。

There's a lot of good stuff in the documentation, including an answer to this exact question. 文档中有很多不错的东西,包括对此确切问题的答案。 From perlfaq5 's answer to How do I do a "tail -f" in perl? perlfaq5的答案到如何在perl中执行“ tail -f”?


First try 第一次尝试

seek(GWFILE, 0, 1);

The statement seek(GWFILE, 0, 1) doesn't change the current position, but it does clear the end-of-file condition on the handle, so that the next makes Perl try again to read something. 语句seek(GWFILE,0,1)不会更改当前位置,但是它确实清除了句柄上的文件结束条件,因此下一个条件使Perl再次尝试读取某些内容。

If that doesn't work (it relies on features of your stdio implementation), then you need something more like this: 如果这不起作用(它依赖于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
}

If this still doesn't work, look into the clearerr method from IO::Handle, which resets the error and end-of-file states on the handle. 如果仍然无法解决问题,请查看IO :: Handle的clearerr方法,该方法将重置句柄上的错误和文件结束状态。

There's also a File::Tail module from CPAN. 还有来自CPAN的File :: Tail模块。

CPAN具有File::ChangeNotify

In my opinion there is nothing wrong with using tail -f pipe like you already do. 我认为使用tail -f管道没有任何问题,就像您已经做过的那样。 In many situations going for language purity like "no system calls" is counterproductive. 在许多情况下,追求纯净语言(例如“无系统调用”)会适得其反。

Also, I've seen problems with File::Tail in long-running processes. 另外,在长时间运行的进程中,我还发现File::Tail出现问题。 Unfortunately I cannot corroborate this claim with any hard evidence since it happened quite some time ago, I did not debug the problems, replacing the use of File::Tail with a tail -F pipe instead. 不幸的是,我无法用任何确凿的证据来证实这一主张,因为它发生在很早以前,我没有调试问题,而是使用tail -F管道代替了File::Tail使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM