ログ監視 Python watchdog(ログローテーション未完成)
アプリケーションのログファイルを監視するシステムをつくる。
上の2つをがっちゃんこしたやつを作った。ファイルの変更監視はwatchdog、読み取りはふつうのIO。
※ うーん、ログローテーション対応が微妙かも
from watchdog.observers import Observerfrom watchdog.events import FileSystemEventHandlerimport timeimport osfrom stat import *class FileWatchHandler(FileSystemEventHandler):def __init__(self, path):self.path = os.path.realpath(path)self.fp = Noneself.fpos = Noneself.init()filesize = os.stat(self.path)[ST_SIZE]self.fp.seek(filesize) # ファイル末尾self.fpos = filesizedef init(self):fp = self.fpif fp:fp.close()fp = open(self.path, 'r')self.fp = fpself.fpos = Nonedef on_created(self, event):if event.src_path == self.path:print('reset')self.init()def on_modified(self, event):if event.src_path == self.path:print('modified')self.tail_f()def tail_f(self):if self.fpos:self.fp.seek(self.fpos)while True:self.fpos = self.fp.tell()line = self.fp.readline()if not line:breakself.analyze(line)def analyze(self, line):# TODO:print('!', line)def close(self):self.fp.close()path = 'test.txt'handler = FileWatchHandler(path)observer = Observer()observer.schedule(handler, os.path.dirname(os.path.realpath(path)))observer.start()try:observer.join()except KeyboardInterrupt:passobserver.stop()handler.close()print('closed')
※ ちょっと修正してみたけど、やっぱり微妙
def tail_f(self):filesize = os.stat(self.path)[ST_SIZE]if self.fpos:if self.fpos <= filesize:self.fp.seek(self.fpos)else:self.init()while True:self.fpos = self.fp.tell()line = self.fp.readline()if not line:breakself.analyze(line)
(ログローテーションはともかく、)あとはanalyze関数に新しくappendされた行が入ってくるので、それぞれ解析すればOK。
ログは定期的に分割されて別ファイルに移動、新しいログが入ってきたら新規ファイルになるので、
on_created
で開き直し(実はseekだけすればいいのかな?)。
このとき、作成と同時に内容が書き込まれるとon_modified
が落としちゃったのでファイル末尾への移動は入れてない。
それからリネームでファイルがやってきても動かない(on_moved
でいけるけど)。
observer.join
って、join
だし別スレッドの終了待ちだと思うので、これでいいかな、と思ったけど公式サンプル(GitHub - gorakhargosh/watchdog: Python library and shell utilities to monitor filesystem events.)は違う...。まあプロセス死んだらなんにせよ止まると願って。
末尾追従動作がけっこう面倒くさいので、すなおにtail -f
をPopenすればよかったかな...
diffもそのうち使うかも? 今回は関係ないけど