监视和读取文件中的新行?

时间:2018-09-09 16:14:40

标签: perl anyevent

程序使用AnyEvent事件循环。该程序应读取换行,有时(很少)出现在本地文件系统上的文本文件中。据我了解,无法使用AnyEvent :: io。我该建议从文件中读取新行吗?

1 个答案:

答案 0 :(得分:3)

一种方法是使用跟踪和报告文件系统对象事件的工具“监视”文件。

基于模块文档中的提要,使用Linux::Inotify2的示例

use warnings;
use strict;
use feature 'say';

use AnyEvent;
use Linux::Inotify2;

my $file = shift @ARGV || 'growing.txt';
die "Usage: $0 file-to-watch\n" if not $file;

say '';
open my $fh, '<', $file  or die "Can't open $file: $!";
print while <$fh>;

my $inotify = Linux::Inotify2->new or die "Can't create inotify object: $!";

$inotify->watch( $file, IN_MODIFY, sub {
    my $e = shift;
    if ($e->IN_MODIFY) {
        print while <$fh>;
    }
});

my $inotify_w = AnyEvent->io (
    fh => $inotify->fileno, poll => 'r', cb => sub { $inotify->poll }
);

1 while $inotify->poll;

该监视器可以与许多主要事件处理工具一起使用。本示例使用AnyEvent

首先创建文件growing.txt,大概包含一些内容。然后启动程序,并在打印其行时将其放在后台(watcher.pl &)中。然后添加到文件

echo "new line\nanother" >> growing.txt

观察者打印

new line
another

请参阅this post以获得更多信息和一些一般性评论,并研究系统中模块的文档和man inotify

要与其他操作一起执行此操作,可以将其置于分支过程中,并在父项出现更改时(通过pipesocketpair或文件)将更改发送给父项。在处理过程中发生的任何事件仍会被检测到,并在控件返回后作为新事件传递。

父级可以通过无阻塞IO::Select::can_read或用户信号的信号处理程序(通过循环)执行其其他工作来处理何时读取的问题。孩子写到其管道末端后发送的SIGUSR1

这是一个不太简单的概述。也有现成的解决方案。 AnyEvent生态系统中的一些选项是AnyEvent::Fork和朋友,AnyEvent::Subprocess具有“代理”机制,AnyEvent::Handle监视该管道何时可以读取。

所有这些都需要一个事件循环,在这种情况下,所有工作都在处理程序(回调)中完成。然后,主要工作可以在“空闲观察者”中完成,但是这可能会让人有些费解,在这种特殊情况下,概述的儿童管理手动方法可能会变得更加清晰。

最合适的监视器管理取决于程序的详细信息。


如果以更改索引节点的方式更改了文件,则上面的代码将无法检测到该错误。使用ziprsync等许多常用工具可能会发生这种情况。为了防止这种情况的发生以及可能的文件消失,您可以使用其他标志来检测这些事件。

$inotify->watch( $file, 
    IN_MODIFY |IN_ATTRIB | IN_MOVE_SELF | IN_DELETE_SELF,  
    sub {
        my $e = shift;
        my $name = $e->fullname;
        if ($e->IN_MODIFY) {
            print while <$fh>;
        }
        if ($e->IN_ATTRIB)      { say "$name meatadata changed" }
        if ($e->IN_MOVE_SELF)   { say "$name was moved" }
        if ($e->IN_DELETE_SELF) { say "$name was deleted" }
});

对于inode更改,将触发IN_ATTRIB

然后,您可能需要重新打开文件(也许首先找到它)。一个单独的目录监视器在这里将非常有帮助。所有这些也可以通过单独使用目录监视器来完成。