1

ログファイルを読み込んで処理し、Postgres データベースにロードするプロジェクトに取り組んでいます。これらのログ ファイルは月ごとに区切られています。つまり、スクリプトに特定の月を指定すると、ディレクトリ (実際には各サーバーのディレクトリであり、8 つのサーバーがあります) を通過し、ファイルを取得してアップロードします。このコードは、それらをデータベースにロードするものです。

sub insert_n_gridftp_usage {
eval {
    $sth = $dbh->prepare("INSERT into $stats_table VALUES ($epoch, '$servername', $currentnumhash{'RETR'}, $currentbyteshash{'RETR'}, $currentnumhash{'STOR'}, $currentbyteshash{'STOR'}, $currentnumhash{'ERET'}, $currentbyteshash{'ERET'}, $currentnumhash{'ESTO'}, $currentbyteshash{'ESTO'}, $currentnumhash{'LIST'}, $currentbyteshash{'LIST'}, $currentnumhash{'NLST'}, $currentbyteshash{'NLST'}, $currentnumhash{'MLSD'}, $currentbyteshash{'MLSD'}, $currentnum, $currentbytes);") || die; 
    $sth->execute;
    $dbh->commit;
} or
do {
    $stats_fails++;
    eval { $dbh->rollback };
}   

}

テーブルには、重複するレコードが読み込まれないようにする一意のインデックス制約があります。このステートメントで重複が発生すると、stderr で次のエラーが発生します。

DBD::Pg::st execute failed: ERROR:  duplicate key value violates unique constraint "transfer_unique"DETAIL:  Key (starttime, endtime, file)=(1366822840, 1366822840, /dev/null) already exists. at ./database_load_script.pl line 196, <LOGFILE> line 1332302.

LOGFILE は私の変数で、単語行の後の番号は私の変数 $linenum です。このエラー文字列をコードのどこにも設定しませんでした。では、この文字列はどこから来ているのでしょうか。この文字列を変更して、読み取り元のファイルも指すようにすることはできますか? (ファイル名の変数があります)。どんな助けでも大歓迎です。

ありがとう。

4

1 に答える 1

2

クエリが失敗したときに出力される内容を実際に変更できます。現在、あなたはやっています:

$sth = $dbh->prepare("...") || die;

これは、dieがデフォルトの引数である の値を取っていることを意味します$!。ただし、カスタム文字列を に渡すこともできdieます。代わりに、標準エラーに出力されます。その文字列が二重引用符で囲まれている場合、他の文字列と同様に変数を補間できます。引数について知っておくべきもう 1 つのことdieは、それらが魔法のようなものであるということです。末尾に改行がない場合die、コードと、たまたま読み取り元のファイルの両方で、エラーの位置に関する情報が追加されます。時間; 引数の末尾に改行を含めるとdie、これは発生しません。

したがって、ファイル名が変数$filenameに含まれていると仮定すると、次のようにすることができます。

$sth = $dbh->prepare('...') || die "$! at $filename line $linenum\n";

次のようなエラーが発生します。

DBD::Pg::st_execute failed: ERROR: [...] at /path/to/logfile line 12345
于 2013-07-30T14:25:14.450 に答える