我从外部服务器获取数据流(文本格式),并希望逐行将其传递给脚本。该文件以连续方式附加。哪个是执行此操作的理想方法。使用Perl的IO :: Socket方法会做什么?最终,这些数据必须通过PHP程序(可重用)并最终登陆MySQL数据库。
问题是如何打开文件,不断更新?
答案 0 :(得分:24)
在Perl中,您可以使用seek
和tell
来读取不断增长的文件。它可能看起来像这样(从perldoc -f seek
大量借用)
open(FH,'<',$the_file) || handle_error(); # typical open call
for (;;) {
while (<FH>) {
# ... process $_ and do something with it ...
}
# eof reached on FH, but wait a second and maybe there will be more output
sleep 1;
seek FH, 0, 1; # this clears the eof flag on FH
}
答案 1 :(得分:9)
在perl中有几个模块可以更轻松地拖尾文件。 IO::Tail和 File::Tail一个使用回调,另一个使用阻塞读取,因此它取决于哪个更适合您的需求。可能还有其他拖尾模块,但这些是我想到的两个。
IO::Tail - 按照文件/流的尾部
use IO::Tail;
my $tail = IO::Tail->new();
$tail->add('test.log', \&callback);
$tail->check();
$tail->loop();
File::Tail - 用于从不断更新的文件中读取的Perl扩展
use File::Tail;
my $file = File::Tail->new("/some/log/file");
while (defined(my $line= $file->read)) {
print $line;
}
答案 2 :(得分:2)
也许named pipe可以帮到你?
答案 3 :(得分:1)
您谈论打开文件,并询问IO::Socket
。这些并不是完全相同的东西,即使在内心深处你将要读取文件描述符的数据。
如果可以从命名管道或FIFO访问远程流,则可以将其作为普通文件打开。当没有任何可用时它将阻塞,并在有数据需要耗尽时返回。如果发件人跑得太远,你可能会,或者可能不需要File::Tail
来解决不丢失数据的问题。
另一方面,如果你直接打开另一台服务器的套接字(似乎更有可能),IO::Socket
开箱即用,因为没有getline
方法可用。您必须逐块读取和缓冲,然后通过中间握笔逐行进行填充。
您可以将套接字描述符拉出到IO::Handle
,然后使用getline()
。类似的东西:
my $sock = IO::Socket::INET->new(
PeerAddr => '172.0.0.1',
PeerPort => 1337,
Proto => 'tcp'
) or die $!;
my $io = new IO::Handle;
$io->fdopen(fileno($sock),"r") or die $!;
while (defined( my $data = $io->getline() )) {
chomp $data;
# do something
}
您可能必须执行握手才能开始接收数据包,但这是另一回事。
答案 4 :(得分:0)
在python中它很简单:
f = open('teste.txt', 'r')
for line in f: # read all lines already in the file
print line.strip()
# keep waiting forever for more lines.
while True:
line = f.readline() # just read more
if line: # if you got something...
print 'got data:', line.strip()
time.sleep(1) # wait a second to not fry the CPU needlessy
答案 5 :(得分:0)
阅读全部罚款以寻求最终的解决方案是性能不明智的。如果在Linux下发生这种情况,我建议只重命名日志文件。然后,您可以扫描重命名文件中的所有entite,而原始文件中的那些将再次填充。扫描完所有重命名的文件后 - 删除它。或者随心所欲地移动。通过这种方式,您可以获得类似logrotate的内容,但可以扫描新到达的数据。