在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?
Posted
技术标签:
【中文标题】在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?【英文标题】:How, in Perl, can I watch for file changes, without polling but with timeout? 【发布时间】:2021-07-03 13:56:53 【问题描述】:我正在使用File::ChangeNotify
,它允许 (a) 非阻塞检查更改,或 (b) 阻塞等待更改。我真正想要的是介于两者之间的东西:阻塞并等待更改,但在指定的超时后返回。我不想投票,也不能永远阻止。
如果$watcher->wait_for_events
方法有这样的超时参数就好了,但似乎没有;也许实现跨平台太难了。有什么建议吗?
【问题讨论】:
【参考方案1】:处理超时的简单方法是alarm 函数。像这样的:
my $timeout = 10;
eval
local $SIGALRM = sub die "alarm\n" ;
alarm $timeout;
$watcher->wait_for_events;
alarm 0;
;
if ($@)
die unless $@ eq "alarm\n"; # propagate unexpected errors
# timed out handling here
【讨论】:
并不是说这是特定于 unix 的,而 File::ChangeNotify 是可移植的。未知的是 OP 和未来读者的要求。【参考方案2】:你可以把它放到 Perl 可以找到的地方,File::ChangeNotify
会捡起它并使用它。
package File::ChangeNotify::Watcher::WithTimeOut;
use strict;
use warnings;
use namespace::autoclean;
use Time::HiRes qw( sleep );
use Moo;
has watcher => ( is => 'rw' );
has sleep_cycles => ( is => 'rw' );
has timeout => ( is => 'rw' );
sub BUILD
my ($self, $args) = @_;
$self->sleep_cycles( delete $args->sleep_cycles );
$self->timeout( delete $args->timeout || 0 );
$self->watcher( File::ChangeNotify::Watcher::Default->new( %$args ) );
sub wait_for_events
my $self = shift;
my $cycles = $self->sleep_cycles || -1;
my $timeout = $self->timeout + time;
while ( $cycles-- != 0 )
my @events = $self->watcher->_interesting_events;
return @events if @events;
return @events if $self->timeout && time >= $timeout;
sleep $self->watcher->sleep_interval;
__PACKAGE__->meta->make_immutable;
1;
然后您可以指定timeout
或sleep_cycles
参数,当timeout
过期或观察者已睡sleep_cycles
次sleep_interval
秒时,这些参数将控制权返回给调用者。
use lib qw(./lib);
use File::ChangeNotify;
use Data::Dumper;
my $watcher = File::ChangeNotify->instantiate_watcher (
directories => [ 'C:/Users/holli/testnotify' ],
filter => qr/\.(?:pm|conf|yml)$/,
sleep_interval => 1,
# sleep_cycles => 10,
timeout => 5,
);
while ( 1 )
my @events = $watcher->wait_for_events;
print Dumper( \@events );
【讨论】:
这至少对 OP 没有帮助。为此,为了帮助 OP,需要一个模块来提供一种异步检查文件更改的机制。它也需要是可取消的。但如果存在这样的模块,OP 可以直接使用它。 @ikegami 现在有一个模块 =) 好多了。 OP 说“我不想投票”,但我相信这只是将对象而不是系统极化。它应该更便宜,尽管它缺乏投票的响应能力。 好吧,如果 OP 不想轮询,那么他们必须一起使用另一个模块。默认观察者做同样的事情: while (1) 检查更新;睡觉以上是关于在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?的主要内容,如果未能解决你的问题,请参考以下文章