徐々にファイルを読む

徐々にファイルを読む

最後に読んだ後、更新されたファイルの一部を読む必要があります。つまり、最後に 2016-07-26T01:30 にファイルを読み込み、100 個のレコードがファイルで更新される 2016-07-26T02:30 に再度実行するには、Get を読み取る必要があります。これは100レコードの完全なファイルです。

ファイル形式は次のとおりです。

[2016-07-26T16:26:31.953-04:00] [AnalyticProviderServices0] [ERROR] [] [oracle.EPMOHPS] [tid: 17] [userId: <anonymous>] [ecid: 0000LGXnLUEComOpyg4EyW1N4iIi000002,1:28342] [APP: APS#11.1.2.0] Unable to resolve 'jdbc.EPMSystemRegistry'. Resolved 'jdbc'[[
[2016-07-26T16:26:31.954-04:00] [AnalyticProviderServices0] [WARNING] [] [oracle.EPMOHPS] [tid: 17] [userId: <anonymous>] [ecid: 0000LGXnLUEComOpyg4EyW1N4iIi000002,1:28342] [APP: APS#11.1.2.0] Failure while getting the active Essbase node for cluster [SWESSPROD1]. Runtime Provider Services Error: [Unable to resolve 'jdbc.EPMSystemRegistry'. Resolved 'jdbc']

答え1

ログファイルが実行されるたびに、ログファイルを徐々に読み取るRe-Tailまたは「retail」というコマンドラインユーティリティ(2003年以降)があります。

たとえば、これは毎時間実行されるクローンジョブに役立ちます。

Re-Tail は、実行中のファイルごとに「オフセットファイル」にステータスを保存し、最後の行番号とその行番号にテキストを保存します。

次回プログラムが実行されると、保存された行番号を見つけて内容を比較しようとします。一致するものがあれば、次の行から始めてファイルの残りの部分を出力します。ディスク上のファイルの行数が少ない場合、または行の内容が一致しない場合は、ファイルが消去または回転されたと見なされ、その場合は最初の行から始まります。

最後に、Retailは保存された行番号と内容を更新します。

ソフトウェアは次の場所にあります。http://xjack.org/retail/

私はRetailをrootとして実行するときに保存された状態を/var/lib/retailに保存するのが好きです。たとえば、1台のコンピュータでは、SSHログインのレポートを生成するために、次のコマンドラインを含むスクリプトを使用して1時間ごとに小売を実行します。

/usr/local/bin/retail -p /var/lib/retail/ /var/log/secure >"$tempfile"

頑張ってください!

答え2

ファイルを開いたままにできます。

exec 3< file
cat <&3

sleep 3600

echo After one hour, these records were added:
cat <&3

catこれは、これらの1時間を呼び出すプロセスと同じでなければなりません。


ファイルシステムでアクセス時間が有効になっていて、スクリプトがファイルを読み取る唯一のスクリプトである場合は、最後のアクセス時間以降のタイムスタンプ付きの行を読み取ることもできます。 GNUシステムでは:

awk -v last_access="$(find file -prune -printf %AFT%AT)" '
   $0 > last_access' < file

-04:00ログファイルのオフセットは現在のタイムゾーンに対応すると仮定します。


別の方法は、次のどこかに現在のファイルの場所を記録することですfile.pos

{
   if [ -e file.pos ]; then
     pos=$(cat file.pos)
   else
     pos=0
   fi
   tail -c +"$((pos+1))"
   perl -le 'print tell STDIN' > file.pos
} < file

またはksh93

{
   if [ -e file.pos ]; then
     pos=$(<file.pos)
   else
     pos=0
   fi
   cat <#((pos))
   exec <#((pos=CUR))
   echo "$pos" > file.pos
} < file

または以下を使用してzsh

zmodload zsh/system    
{
   if [ -e file.pos ]; then
     pos=$(<file.pos)
   else
     pos=0
   fi
   sysseek $pos
   cat
   echo "$((systell(0)))" > file.pos
} < file

答え3

#!/bin/bash

logfile="$1"

test -f "$logfile" || exit 1

lastline="$( basename "$logfile" )-last"

if [ -f "$lastline" ]; then
    place=$( <"$lastline" )
else
    place=1
fi

tmpfile="$( mktemp )"
trap 'rm -f "$tmpfile"' EXIT

sed -n -e "$place,\$p" -e '$=' "$logfile" |
tee "$tmpfile" |
tail -n 1 >"$lastline"

sed '$d' "$tmpfile"

この小さなスクリプトは、コマンドラインからログファイルを取得し、最後にスクリプトを使用してから追加されたすべての行を表示します。 現在、ログファイルの回転形式を理解していません。...-lastしたがって、ログが循環している場合は、現在のディレクトリに作成されたファイルを手動で削除する必要があります。

できること:

sed最初に実行すると、指定されたログファイルのすべての行を一時ファイルに出力し、最後の行の行番号を出力するために使用されます。番号はログファイルと同じ名前でサフィックスが付いています-lastless必要に応じて、スクリプトに出力が端末に送信されます。スクリプトが終了すると、一時ファイルが削除されます。

再度実行すると、現在のディレクトリのファイルから行番号を読み取り、以前と...-last同様の方法でその行番号から最後までログファイルの内容を処理します。

このスクリプト実行の間にログファイルに何も出力されない場合。ログファイルの最後の行が表示されます。

実行してください:

$ bash script.sh /var/log/system.log
[lots of output]

$ ls system*
system.log-last

$ cat system.log-last
14758

$ bash script.sh /var/log/system.log
[a few lines of output,
 with the first line being the same as the last of the previous run]

$ cat system.log-last
14768

関連情報