ログの回転を実行して、ファイルから定期的に新しい行を取得します。

ログの回転を実行して、ファイルから定期的に新しい行を取得します。

私はかなり簡単な方法を探しています(開発は必要ありません。Pythonで書くことができますが、すでに持っているものがあればいいです)。

ログファイルがあります(私の場合はrsyslogdで書かれています)。分析の目的で、私は1分ごとに読んで、私のhttpサーバーのページビュー数などの最後の瞬間の指標を計算したいと思います。私の要求2つ:

1) 最後にファイルを読んだ後に追加された行だけを見たいです。 (最後の1分程度しか必要ありません。ファイルが大きすぎて1分ごとに読み直してフィルタリングできません。)

2)1日に1回ファイルを録音します。ログの回転後に最初にまだ読み取られていない古いファイルのすべての行と新しいファイルのすべての行が必要です。

今それを求める人は私だけのようです。他の人はどうしますか?

答え1

your-filterそのデータがstdinから読み取られたとします。

while your-filter; do
  sleep 60
done < file.log

たとえば、your-filterデータを読み取るだけでデータを書き込もうとしないとします。lseek

/dev/fd/nログローテーションの問題を解決するには、Linux(実際のファイルへのシンボリックリンクである他のほとんどのシステムとは異なり)で、、、、、ksh(POSIX以外のものなど、最も賢いシェルを除くほとんどのPOSIXシェル)を使用しますbash。 :zshdashyashposh-ef

while your-filter; do
  if [ file.log -ef /dev/stdin ]; then
    sleep 60
  else
    exec < file.log
  fi
done < file.log

ログが回転したときに古いyour-filter接続と新しい接続を1回呼び出すには、2回呼び出されます。

while 
  if [ file.log -ef /dev/stdin ]; then
    your-filter
  else
    exec 3<&0 < file.log
    (cat <&3; cat) | your-filter &&
      exec 3<&-
  fi
do
  sleep 60
done < file.log

これで、ログの循環中に古い file.log の名前が変更されましたが、新しい file.log がfile.log生成されなかった場合があります。exec < file.logこの場合、上記の操作は失敗します。その後、次を使用してこの問題を解決できます。

while 
  if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then
    your-filter
  else
    (cat; cat <&3) | your-filter &&
      exec <&3 3<&-
  fi
do
  sleep 60
done < file.log

したがって、新しいファイルが表示されるまで古いファイルを読み続けます。

commandexec失敗時にシェルがシャットダウンするのを防ぐ必要があります(POSIXが要求するように)。モードzshになっているbash場合とない場合は必要ありませんsh

これで、ループ内で60秒間寝てyour-filter実行するのに数秒かかることがあります。your-filter毎分平均1回の実行が重要な場合はkshbashまたはを使用してzsh次のように変更できます。

t=$SECONDS
while 
  if [ file.log -ef /dev/stdin ] || ! command exec 3< file.log; then
    your-filter
  else
    (cat; cat <&3) | your-filter &&
      exec <&3 3<&-
  fi
do
  t=$(($t + 60))
  sleep "$((t - SECONDS))"
done < file.log

ksh93と浮動小数点引数を許可するzsh場合はsleep実行できますtypeset -F SECONDS

関連情報