我编写了一个Perl程序,它将匹配日志文件中的某些单词并将结果存储在数据库中。问题是这个程序适用于小文件但不适用于文件大小~2GB。是否需要更改尺寸或程序?
use POSIX qw(strftime);
# load module
use DBI;
open( FILE, "/root/temp.log" ) or die "Unable to open logfile:$!\n";
$count_start = 0;
$count_interim = 0;
$count_stop = 0;
while (<FILE>) {
@test = <FILE>;
foreach $line (@test) {
if ( $line =~ m/server start/ ) {
#print "yes\n";
$count_start++;
}
elsif ( $line =~ m/server interim-update/ ) {
$count_stop++;
}
elsif ( $line =~ m/server stop/ ) {
$count_interim++;
}
}
print "$count_start\n";
print "$count_stop\n";
print "$count_interim\n";
$now_string = strftime "%b %e %H:%M:%S", localtime;
print $now_string;
# connect
my $dbh = DBI->connect( "DBI:Pg:dbname=postgres;host=localhost",
"postgres", "postgres", { 'RaiseError' => 1 } );
# execute INSERT query
my $rows = $dbh->do(
"insert into radcount (acc,bcc,dcc) Values ('$count_start','$count_stop','$count_interim')"
);
print "$rows row(s) affected\n";
# clean up
$dbh->disconnect();
}
close(LOG);
答案 0 :(得分:5)
这里有一些事情 - 首先,我建议您更改为三个arg打开文件句柄 - 推理here
open( my $fileHandle, '<', '/root/temp.log' ) or die "blah" ;
其次你将整个文件读入一个数组 - 有一个大文件,这会占用很多内存。而是逐行阅读并处理它:
while(<$fileHandle>){
#contents of your foreach loop
}
答案 1 :(得分:3)
我对您的计划有一些评论。
在程序开始时始终 use strict
和use warnings
,并在首次使用时使用my
声明变量
始终使用词法文件句柄和open
的三参数格式,始终检查公开呼叫的状态
您正在使用文件句柄FILE
打开文件,但关闭LOG
您的while
语句会读取文件的第一行并将其丢弃
@test = <FILE>
尝试将其余文件的所有读入数组。这就是造成问题的原因
您应该连接到数据库一次,并为其余代码使用相同的数据库句柄
您应该将prepare
语句与占位符一起使用,并使用execute
您正在为$count_stop
记录增加interim-update
,为$count_interim
记录增加stop
核心模块Time::Piece
提供strftime
方法,但没有POSIX
以下是对您的计划进行修改以展示这些想法。我没有设置日志文件和数据库来测试它,但它看起来很好,并且编译。
use strict;
use warnings;
use Time::Piece;
use DBI;
open my $log, '<', '/root/temp.log' or die "Unable to open log file: $!";
my ($count_start, $count_interim, $count_stop) = (0, 0, 0);
while (<$log>) {
if ( /server start/ ) {
$count_start++;
}
elsif ( /server interim-update/ ) {
$count_interim++;
}
elsif ( /server stop/ ) {
$count_stop++;
}
}
print <<END;
Start: $count_start
Interim: $count_interim
Stop: $count_stop
END
print localtime->strftime("%b %e %H:%M:%S"), "\n";
my $dbh = DBI->connect(
"DBI:Pg:dbname=postgres;host=localhost", "postgres", "postgres",
{ 'RaiseError' => 1 } );
my $insert = $dbh->prepare('INSERT INTO radcount (acc, bcc, dcc) VALUES (?, ?, ?)');
my $rows = $insert->execute($count_start, $count_stop, $count_interim);
printf "%d %s affected\n", $rows, $rows == 1 ? 'row' : 'rows';