Strawberry Perl 5.38.0.1输入文件流实时监控失效问题咨询
Perl 5.38实时读取文件更新失效的解决方法
问题原因
Perl 5.38调整了文件句柄的EOF处理逻辑:当读取到文件末尾(<$IN_STREAM>返回undef)后,后续的读取操作会直接返回undef,不会再重新检查文件是否有新增内容。而旧版本(5.32)中,即使到达EOF,后续读取仍会尝试从文件获取新数据,这导致了脚本行为差异。
解决方案
方法1:重置文件句柄的EOF标记
在检测到EOF后,通过seek操作重置文件句柄的EOF状态,让后续读取能重新检查文件内容:
#!/usr/bin/perl use strict; use warnings; open(my $IN_STREAM, '<', 'file_in.txt') or die "Fail to open file_in.txt: $!"; while (1) { my $line = <$IN_STREAM>; if (defined $line) { print $line; } else { # 移动到当前位置,重置EOF标记 seek($IN_STREAM, 0, 1); sleep(1); } }
方法2:使用专门的文件跟踪模块File::Tail
File::Tail模块专为实时监控文件更新设计,能自动处理文件缓冲、EOF检测和内容新增读取,稳定性更高。先通过Strawberry Perl的cpanm安装模块:
cpanm File::Tail
然后编写脚本:
#!/usr/bin/perl use strict; use warnings; use File::Tail; # 初始化文件跟踪,maxinterval设置最长检查间隔(秒) my $file_tail = File::Tail->new(name => 'file_in.txt', maxinterval => 1); while (my $line = $file_tail->read) { print $line; }
方法3:手动监控文件大小变化
通过定期检查文件大小,当文件变大时,读取新增的内容片段:
#!/usr/bin/perl use strict; use warnings; use Fcntl qw(:seek); my $filename = 'file_in.txt'; open(my $fh, '<', $filename) or die "Can't open $filename: $!"; my $current_size = -s $filename; while (1) { my $new_size = -s $filename; if ($new_size > $current_size) { # 定位到上次读取的末尾位置 seek($fh, $current_size, SEEK_SET); # 读取新增内容 while (my $line = <$fh>) { print $line; } $current_size = $new_size; } sleep(1); }
内容的提问来源于stack exchange,提问作者Jean-Marc
相关产品推荐
相关产品推荐

