
ログファイルを出力する2つのスクリプトを実行しています。これらのログをタイムスタンプで並べ替え、生成時に単一のファイルにマージする3番目のスクリプトを作成したいと思います。ファイルを常に上書きせずにこれを行うための良い方法はありますか?
答え1
2つ以上のファイルをtailすると、tail -f
コマンドはデータを1行ずつ表示し、データソースが変更されるたびにファイル名を出力します。この機能を使用すると、後続のタイムスタンプのある行が別のファイルで表示されるまで、各行を保持して、タイムスタンプに基づいてテールからインターリーブされた出力をマージするスクリプトを作成できます。
たとえば、私のシステムで同じ行開始タイムスタンプ形式(たとえば)を持つ2つの標準ログファイル(および/var/log/messages
)を使用すると、次のことができます。/var/log/cron
Jun 9 02:55:01
tail -f /var/log/messages /var/log/cron |
awk '
BEGIN { num[0] = 0; num[1] = 0; }
/^==> /{
file = $2; aa = file~/messages/?0:1; bb = 1-aa;
aanum = num[aa]; bbnum = num[bb];
next }
/^$/{ next }
{ "date --date \"" $1 " " $2 " " $3 "\" +%s" | getline date
lines[aa,aanum] = $0
dates[aa,aanum++] = date
maxes[aa] = date
minmax = maxes[aa]
if(maxes[bb]<minmax)minmax = maxes[bb]
i = 0; j = 0;
while(1){
aaok = (i<aanum && dates[aa,i]<=minmax)
bbok = (j<bbnum && dates[bb,j]<=minmax)
if(aaok && bbok){
if(dates[aa,i]<=dates[bb,j]){
print lines[aa,i]; dates[aa,i++] = ""
}else{
print lines[bb,j]; dates[bb,j++] = ""
}
}else if(aaok){
print lines[aa,i]; dates[aa,i++] = ""
}else if(bbok){
print lines[bb,j]; dates[bb,j++] = ""
}else break
}
i = 0
for(j = 0; j<aanum;j++)
if(dates[aa,j]!=""){
dates[aa,i] = dates[aa,j]; lines[aa,i++] = lines[aa,j]
}
aanum = num[aa] = i
i = 0
for(j = 0; j<bbnum;j++)
if(dates[bb,j]!=""){
dates[bb,i] = dates[bb,j]; lines[bb,i++] = lines[bb,j]
}
bbnum = num[bb] = i
}'
awkは、ファイルの先頭が最後から始まることを確認すると、2つのファイルを切り替えます==>
。各ファイルごとに1つずつ4つの配列にデータを格納し、ランダムに呼び出され、aa
0bb
と1に番号が付けられます。dates
エポック以降の秒単位のタイムスタンプを保存し、lines
入力ログ行を保存し、num
行数とmaxes
最も高い日付をファイルに保存します。最初の2つの配列は、ファイル(0または1)と予約された行数に基づいて2次元で索引付けされます。
各ログ行を読み取ると、タイムスタンプが秒に変換され、最後に新しいエントリに保存され、その行も保存されdates
ます。 2つの現在の日付の最小値はに設定されますminmax
。この最小値に達するまで、保存されたデータ全体をタイムスタンプ順にスキャンして印刷します。印刷された項目が消去され、whileループが終了すると、配列が圧縮されて消去された項目が削除されます。
答え2
ログファイルのタイムスタンプソースは同じで、各ログはログエントリが作成されたときに時系列で記録され、タイムスタンプに従って次のように簡単に操作できます。
tail -qF log1 log2 > summarylog
これらの仮定があなたの状況に合わない場合は、質問を更新して説明と例を提供してください。