Perl 持续从文本文件读入数据的有效方法
我们在FTP端点上有一个脚本,用于监视FTP守护进程输出的FTP日志。 目前我们所做的是让一个perl脚本在文件上运行tail-F,并将每一行发送到一个远程MySQL数据库,根据记录类型使用稍微不同的列内容 该数据库具有用于tarball名称/内容以及所述包的FTP用户操作的表;下载、删除VSFTPd日志以及其他所有内容 我认为这特别糟糕,但我不确定有什么更好 替换的目标仍然是尽可能快地将日志文件内容输入数据库。我正在考虑做一些事情,比如制作一个FIFO/pipe文件来代替FTP日志文件,这样我就可以周期性地读取一次,确保我不会在两次中读取相同的内容。假设VSFTPd能很好地解决这个问题(我想不会的,欢迎光临!) FTP守护进程是VSFTPd,我至少相当肯定它们的日志功能范围是:xfer风格的日志、VSFTPd风格的日志,或者两者都有,或者根本没有日志Perl 持续从文本文件读入数据的有效方法,perl,logging,ftp,Perl,Logging,Ftp,我们在FTP端点上有一个脚本,用于监视FTP守护进程输出的FTP日志。 目前我们所做的是让一个perl脚本在文件上运行tail-F,并将每一行发送到一个远程MySQL数据库,根据记录类型使用稍微不同的列内容 该数据库具有用于tarball名称/内容以及所述包的FTP用户操作的表;下载、删除VSFTPd日志以及其他所有内容 我认为这特别糟糕,但我不确定有什么更好 替换的目标仍然是尽可能快地将日志文件内容输入数据库。我正在考虑做一些事情,比如制作一个FIFO/pipe文件来代替FTP日志文件,这样我
问题是,如果有的话,还有什么比我们正在做的更好呢?您应该研究inotify(假设您使用的是一个不错的基于posix的操作系统),这样您就可以在日志文件更新时运行perl脚本。如果这一级别的IO导致问题,您可以始终将日志文件保存在RAMdisk上,以便IO非常快 这将帮助您设置:
老实说,我不认为你现在所做的有什么错
tail-f
非常有效。它唯一真正的问题是,如果您的watcher脚本死掉,它就会失去状态(这是一个用旋转日志文件来解决的半困难问题)。CPAN上还有一个很好的模块,它可以将您从shellout中解救出来,并提供一些很好的自定义功能
使用FIFO作为日志可以工作(只要vsftpd在任何时候都不尝试取消链接并重新创建日志文件,它可能会这样做),但我发现它有一个主要问题。如果没有人从FIFO的另一端读取数据(例如,如果脚本崩溃或从未启动),那么很快,所有对FIFO的写入都将开始阻塞。我还没有测试过这一点,但很可能日志文件写入块会导致整个服务器挂起。这不是一个很好的场景。您可以将文件作为管道中的文件打开
open(my $file, '-|', '/ftp/file/path');
while (<$file>) {
# you know the rest
}
open(我的$file'-|','/ftp/file/path');
而(){
#其余的你都知道
}
Tail可以做到这一点,加上启发式睡眠和良好的错误处理和恢复
编辑:再想一想,如果您能够管理一个真正的系统管道,它会更好。如果没有,则需要找到放入数据库的最后一个内容,并旋转文件,直到在进程启动时找到放入数据库的最后一个内容。要做到这一点并非易事,如果您无法确定从何处中断,则可能无法做到。您在读取不断更新的文件时遇到的问题是,即使到达文件末尾,您仍希望继续读取。解决方法是重新查找文件中的当前位置: 查找文件句柄,0,1 下面是我做这类事情的代码:
open(FILEHANDLE,'<', '/var/log/file') || die 'Could not open log file';
seek(FILEHANDLE, 0, 2) || die 'Could not seek to end of log file';
for (;;) {
while (<FILEHANDLE>) {
if ( $_ =~ /monitor status down/ ) {
print "Gone down\n";
}
}
sleep 1;
seek FILEHANDLE, 0, 1; # clear eof
}
open(FILEHANDLE,'这不是什么“定时警报”,因为添加到日志文件的操作非常频繁。比方说……至少每5秒一次,每秒多次,其他几次每秒多次。这更多的是关于如何最好地主动获取内容并将其发送到某个地方。此外,高效且只需一次给定的条目。Perl模块和CPAN是我最好的朋友。轻视当我指向Net::FTP时,我们从perl脚本中发出FTP命令……;顺便说一句,你的代表疯了。太棒了。社区成员应该渴望和你一样有帮助。