前回終了した時点からログファイルの読み取りを再開する

前回終了した時点からログファイルの読み取りを再開する

一定期間後に継続的に更新される(新しい行が追加される)ログ ファイルがあります。

10 分ごとにファイルからエラー メッセージのみを取得しています。

最初は、パターン「ERROR FOUND」に一致するすべての行を新しいファイルに取得しました。awk

しかし、10 分後にはログ ファイルに新しい行が追加されているため、ログ ファイルを中断したところから読みたいのですが、最初からやり直したくはありません。

これに最適なコードまたはスクリプトを提案してくれる人はいますか?

答え1

次のようにファイル記述子でファイルを開くと、

exec 3< /path/to/log/file

その後、次のように処理できます。

awk '...' <&3

その後、fd 3 はawkそれを残した場所を指します。

10分後、同じシェル呼び出しから、これを実行できます。

awk '...' <&3

新しいデータを処理するためにコマンドを再度実行します。

以前いた位置を保存して、別のシェル呼び出しから読み取りを再開できるようにするには、 でksh93次のようにします。

#! /usr/bin/env ksh93
file=/path/to/some-file
offset_file=$file.offset

exec 3< "$file"
[ -f "$offset_file" ] && exec 3<#(($(<"$offset_file")))

awk '...' <&3

echo "$(3<#((CUR)))" > "$offset_file"

またはzshの場合:

#! /usr/bin/env zsh

zmodload zsh/system
file=/path/to/some-file
offset_file=$file.offset

exec 3< $file
[ -f "$offset_file" ] && sysseek -u 3 "$(<$offset_file)"

awk '...' <&3

echo $((systell(3))) > $offset_file

答え2

私はステファンの回答が気に入ったので、ファイル全体を何度も読み返さないので、ここに追加します。バッシュ(Linux の場合) 彼の解決策と同等です (bash には組み込み機能seektell機能もありません)。コメントを使用したかったのですが、私の評判が低すぎます。

LASTPOS=/tmp/saved_pos

exec 3< "$1"
test -f "$LASTPOS" && STARTPOS=$(($(<$LASTPOS)+1))
tail -c "+${STARTPOS:-1}" <&3 | grep "ERROR FOUND"
grep '^pos:' /proc/self/fdinfo/3 | cut -f2 > "$LASTPOS"

awkまた、通常はより高速であるため、コマンドを に置き換えました。さらに処理が必要な場合は、grep出力をコマンドにパイプすることができます。awk

答え3

wc -lとを試してみるといいでしょうtail。bash
を使用している場合は、これが機能するはずです:

#!/bin/bash
LASTLNFILE=/tmp/lastline     # replace with a suitable path
test -f $LASTLNFILE && LASTLN=$(<$LASTLNFILE)
CURLN=$(wc -l $1 | cut -d' ' -f1)

if ((CURLN-LASTLN > 0)); then
  tail -n $((CURLN-LASTLN)) $1
fi
echo $CURLN > $LASTLNFILE

PS これを awk プログラムの前にフィルターとして使用します (例: 「newlines.sh」という名前を付けた場合):

./newlines.sh <log_file> | awk -f <your_awk_program>`

上記のスクリプトは、やらないこれを書いた直後に、スクリプトの実行中にログ ファイルが更新されるたびに競合状態が発生する可能性があることに気付きました。

純粋な AWK アプローチが望ましいです。

#!/bin/awk

BEGIN { 
  lastlinefile = "/tmp/lastlinefile"
  getline lastline < lastlinefile
}

NR > lastline && /ERROR FOUND/ {
  # do your stuff...
  print
}

END { print NR > lastlinefile }

関連情報