複数のログファイルから同時時刻に実行している箇所を抽出-多重実行を洗い出せ
cronなどでプログラムを実行している場合、意図しないタイミングでプログラムが実行される事が稀にあります。
原因は、実行したプログラムの遅延やサーバーをコピーことが原因など様々です。
ヒューマンエラーは起きうるもので、理想は自動化などでカバーする事が良いですが、全てのプロセスがうまい具合に自動化されることはまずあり得ません。
この場合、如何に早く原因と実行タイミングを求めるかが重要になるので、その時に実際に書いたスクリプトを公開します。
Python3で複数ログを統一化するスクリプトを作成した
複数のログファイルを読み込み、1つのファイルとして認識した後、重複をチェックするプログラムを作成しました。
(pip installは割愛)
import re
from datetime import datetime as dt
def extract_date(s):
#date_pattern = re.compile('[0-9]{2}\/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Aep|Oct|Nov|Dec)\/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}')
date_pattern = re.compile('20[0-9]{2}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}')
result = date_pattern.search(s)
if result:
#txt = retrunMonth(result.group(0))
txt = result.group(0)
return dt.strptime(txt, '%Y-%m-%d %H:%M:%S.%f')
else:
return False
def retrunMonth(date):
words = date.split("/")
if words[1] == 'Jan':
return date.replace(words[1], '1')
elif words[1] == 'Feb':
return date.replace(words[1], '2')
elif words[1] == 'Mar':
return date.replace(words[1], '3')
elif words[1] == 'Apr':
return date.replace(words[1], '4')
elif words[1] == 'May':
return date.replace(words[1], '5')
elif words[1] == 'Jun':
return date.replace(words[1], '6')
elif words[1] == 'Jul':
return date.replace(words[1], '7')
elif words[1] == 'Aug':
return date.replace(words[1], '8')
elif words[1] == 'Aep':
return date.replace(words[1], '9')
elif words[1] == 'Oct':
return date.replace(words[1], '10')
elif words[1] == 'Nov':
return date.replace(words[1], '11')
elif words[1] == 'Dec':
return date.replace(words[1], '12')
else:
return date
if __name__ == '__main__':
import sys
filename = sys.argv[1]
f = open(filename)
text = f.read()
f.close()
arr=[]
for line in text.splitlines():
result = extract_date(line)
if result:
arr.append([result, line])
arr.sort()
mae =''
mae2 =''
counta=0
for a in arr:
strs = a[0].strftime("%Y-%m-%d %H:%M:%S.%f") + ' : ' + a[1]
f = False
if mae == a[0]:
strs = '-----重複-----' + strs
f = True
mae = a[0]
searchText = str(strs)
searchLine = searchText.find('{検索文字}')
if searchLine:
if f:
counta = counta +1
print()
print('###################################################################################################################ここから###################################################################################################################')
print(mae2)
print(strs)
print('###################################################################################################################ここまで###################################################################################################################')
mae2 = '-----対象-----' + strs.replace('-----重複-----','')
print('全部で' + str(counta) + '件重複')
使い方は、引数に読み込ませたいファイルを格納しているフォルダを指定します。
コメントアウトは、rsyslogのように 月が3文字で表記される場合「returnMonth」で変換することができます。
最後の「searchText」は、特手のファンクションで起きているなどある程度の影響箇所がわかっている場合に文字列検索することで、さらに絞り込みを行います。
問題点としては、比較を2つの行しか行なっておらず、3つ以上重複に対応していないことでしょうか。
しょぼいコードだけど、短時間で洗い出す事が重要
上のコードは、ロクにエラーチェックもしていないしょぼいコードですが、短時間で問題を洗い出しからコードの作り込みを行い、特定する事ができました。
(実際には1時間も経過していない)
このコードを公開した理由は、しょぼいコードだけど原因特定に向けて最短で動く事ができた教訓を記録するものであり、スクリプト言語の実装の速さを証明するためです。
なお、最近ではAWS CloudWatch Logsなどがあるので、障害調査はより簡単になります。
まだ、クラウドへ移行していないシステムも多いので、ログから影響調査を行いたい場合のためのここに記録しておきます。
Awesome post! Keep up the great work! 🙂