监视和读取文件中的新行?
Monitoring and reading new lines in a file?
该程序使用 AnyEvent 事件循环。该程序应该读取有时(很少)出现在本地文件系统上的文本文件中的新行。据我了解,AnyEvent::io 不能使用。从文件中读取新行有什么建议?
一种方法是 "watch" 使用跟踪和报告文件系统事件的工具 objects 文件 objects。
使用 Linux::Inotify2 的示例,基于模块文档中的概要
use warnings;
use strict;
use feature 'say';
use AnyEvent;
use Linux::Inotify2;
my $file = shift @ARGV || 'growing.txt';
die "Usage: [=10=] 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
请参阅 了解更多内容和一些一般性评论,并在您的系统上研究模块的文档和 man inotify
。
要与其他事情一起执行此操作,您可以将其放入分叉进程中,并在 parent 出现更改时将其发送到 parent(通过 pipe
、socketpair
或文件) .在处理过程中发生的任何事件仍会被检测到,并在控制 returns.
后作为新事件传递
parent 可以处理 何时 阅读的问题,方法是使用 non-blocking IO::Select::can_read
循环执行其他工作,或者使用 child 在写入其管道端后发送的用户信号 (SIGUSR1
) 的信号处理程序。
这是一个不太简单的大纲。也有现成的解决方案。 AnyEvent
生态系统中的一些选项是 AnyEvent::Fork and friends, AnyEvent::Subprocess with its "delegates" mechanism, AnyEvent::Handle 以观察该管道何时可以读取。
所有这些也需要一个事件循环,在这种情况下,所有工作都在处理程序(回调)中完成。然后主要工作可以在 "idle watcher," 中完成,例如,但这可能会有点令人费解,在这种特殊情况下,child 管理的概述手动方法可能最终会更加清晰。
最合适的监视器管理取决于你程序的细节。
如果文件以更改 inode 的方式更改,上面的代码将无法检测到。许多常用工具都可能发生这种情况,例如 zip
、rsync
等。为了防止这种情况以及可能的文件消失,您可以使用其他标志来检测这些事件。
$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
。
那么您可能需要 re-open 文件(也许首先要找到它)。一个单独的目录监视器在这里会很有帮助。所有这些也可以单独使用目录监视器来完成。
该程序使用 AnyEvent 事件循环。该程序应该读取有时(很少)出现在本地文件系统上的文本文件中的新行。据我了解,AnyEvent::io 不能使用。从文件中读取新行有什么建议?
一种方法是 "watch" 使用跟踪和报告文件系统事件的工具 objects 文件 objects。
使用 Linux::Inotify2 的示例,基于模块文档中的概要
use warnings;
use strict;
use feature 'say';
use AnyEvent;
use Linux::Inotify2;
my $file = shift @ARGV || 'growing.txt';
die "Usage: [=10=] 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
请参阅 man inotify
。
要与其他事情一起执行此操作,您可以将其放入分叉进程中,并在 parent 出现更改时将其发送到 parent(通过 pipe
、socketpair
或文件) .在处理过程中发生的任何事件仍会被检测到,并在控制 returns.
parent 可以处理 何时 阅读的问题,方法是使用 non-blocking IO::Select::can_read
循环执行其他工作,或者使用 child 在写入其管道端后发送的用户信号 (SIGUSR1
) 的信号处理程序。
这是一个不太简单的大纲。也有现成的解决方案。 AnyEvent
生态系统中的一些选项是 AnyEvent::Fork and friends, AnyEvent::Subprocess with its "delegates" mechanism, AnyEvent::Handle 以观察该管道何时可以读取。
所有这些也需要一个事件循环,在这种情况下,所有工作都在处理程序(回调)中完成。然后主要工作可以在 "idle watcher," 中完成,例如,但这可能会有点令人费解,在这种特殊情况下,child 管理的概述手动方法可能最终会更加清晰。
最合适的监视器管理取决于你程序的细节。
如果文件以更改 inode 的方式更改,上面的代码将无法检测到。许多常用工具都可能发生这种情况,例如 zip
、rsync
等。为了防止这种情况以及可能的文件消失,您可以使用其他标志来检测这些事件。
$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
。
那么您可能需要 re-open 文件(也许首先要找到它)。一个单独的目录监视器在这里会很有帮助。所有这些也可以单独使用目录监视器来完成。