ログファイルを複数回処理する場合は、最後に処理された行から始めます。

ログファイルを複数回処理する場合は、最後に処理された行から始めます。

私はWebアプリケーション用のロギングおよびレポートシステムを設計しています。
Webアプリケーションでは、一部のイベント(「ユーザーログイン」、「ユーザーが実行したタスクX」など)が発生する可能性があります。
アプリケーションがこれらのイベントをフラットログファイルに記録したいと思います。
次に、定期的に実行され、そのファイルからデータを取得し、データベーステーブルに実行されている集計レポートを維持する別のプログラムを作成したいと思います(例:「毎日のイベントXタイプのイベント数」など)。

課題の1つは、報告者が同じ行を2回処理しないようにすることです。

これらのシステムを設計したり、「処理された行追跡」などの問題を処理するUnix方式はありますか?

ログを処理する前に、ログを回転させ、各行に一意の行番号を割り当てることを検討しましたが、すべて混乱しているようです。

ありがとうございます。

ベストアンサー1

アプリケーションがログファイルを永久に開いたままにしない限り、ログを解析する前にログを回転させるのは良い考えのようです。その場合、回転は機能しません。ただし、ロギングフレームワークを作成しているので、これを処理できます。

簡単なスクリプトが必要な場合は、次のものを使用できます(ほとんどすべてのスクリプト言語で実行可能)。

#! /bin/bash

process_line() {
    # do the work here
    echo "== $1 =="
}

logfile=$1
statefile=${logfile}.state

if [ -f ${statefile} ] ; then
    processed=$(cat $statefile)
else
    processed=0
fi

curline=0
IFS='
'

while read line ; do
    if [ $curline -ge $processed ] ; then
        echo processing $line
        process_line "$line"
    fi
    curline=$(($curline+1))
done < ${logfile}

echo $curline > $statefile

デフォルトでは、入力が処理された時点を別のファイル($statefile)に保存し、その時点から1行ずつ入力を処理します(すでに処理された入力はスキップ)。

明らかに、これはより多くのエラー処理を必要とし、入力が大きい場合は最適ではありません。 (dd bs=1 skip=$already_read count=$(($size-$already_read))1行ずつ操作を実行するのではなく、バイトオフセットとルックアップを保存したり、他のプロセスでパイピング出力を使用したりすることでこれを行うことができますが、perlこの最適化が必要な場合はそれを使用します。)

実際にスクリプトが中断されると、その行は2回処理されます。最後に一度だけ実行するのではなく、各行の終わりにステータスファイルを更新して「再生」回数を制限できます。

ログを処理して循環する場合は、これらのステータスファイルに注意する必要があります。また、回転する必要があり、スクリプトは回転後に一度実行され、出力の最後の数行を処理します。

このように処理するのが容易ではない部分は、部分線です。スクリプトの実行中にアプリケーションが作成した場合、スクリプトは最後の行の一部を見ることもできます。違いがわからないため、処理済みとして記録します。 (この問題を解決するには、ほぼすべてのアプローチが必要です。)

これは、ログファイル形式でEOLマーカーを使用し、行を処理する前に確認することで回避できます。しかし、それはきれいではありません。

bashスクリプト自体で処理する代わりに、次のように使用できます(一般に置き換えます)。process_lineecho

$ ./logger /var/log/app12.log | ./analyzer --logtype=app12

./analyzerデータを入力としてインポートします。

おすすめ記事