1

ログ ファイル内の特定の単語に一致し、結果をデータベースに保存する Perl プログラムを作成しました。問題は、このプログラムは小さなファイルでは正常に動作しますが、ファイル サイズが 2 GB まででは動作しないことです。サイズやプログラムを変更する必要がありますか?

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);
4

2 に答える 2

5

ここにはいくつかのことがあります-最初に、ファイルハンドル用に3つの引数を開くように変更することをお勧めします-ここで推論します

open( my $fileHandle, '<', '/root/temp.log' ) or die "blah" ;

次に、ファイル全体を配列に読み込んでいます。大きなファイルの場合、これは大量のRAMを消費します。代わりに、1行ずつ読み取り、処理します。

while(<$fileHandle>){
    #contents of your foreach loop
}
于 2012-07-09T13:12:14.080 に答える
3

あなたのプログラムについていくつかコメントがあります。

  • 常に use strictプログラムの開始時に、最初の使用時にuse warningsを使用して変数を宣言しますmy

  • 常に字句ファイルハンドルとの3パラメータ形式を使用しopen常にオープンコールのステータスを確認します

  • filehandleを使用してファイルを開いていますFILEが、閉じていますLOG

  • ステートメントwhileはファイルの最初の行を読み取り、それを破棄します

  • @test = <FILE>ファイルの残りすべてをアレイに読み込もうとします。これがあなたの問題を引き起こしているものです

  • データベースに一度接続し、残りのコードには同じデータベースハンドルを使用する必要があります

  • prepareステートメントをプレースホルダーとともに使用し、実際の値を次のように渡す必要がありますexecute

  • あなたはレコードとレコードのため$count_stopにインクリメントしていますinterim-update$count_interimstop

  • コアモジュールは、肥大化のない方法をTime::Piece提供しますstrftimePOSIX

これらのアイデアを示すためのプログラムの変更は次のとおりです。私はそれをテストするためにログファイルとデータベースを設定していませんが、それは私には問題なく見え、コンパイルします。

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';
于 2012-07-09T16:41:09.167 に答える