importosimportsysimportreimportpyinotify
DIRMASK=pyinotify.IN_MODIFY|pyinotify.IN_ATTRIB|pyinotify.IN_MOVE_SELF|pyinotify.IN_CREATEclassHandler(pyinotify.ProcessEvent):def __init__(self, filename):
self._fh=None
self._path=filename
super(Handler, self).__init__()defmy_init(self):try:
self._fh= open(self._path, ‘r‘)exceptIOError as e:
sys.stderr.write(‘open file failed, %s‘ %e)else:
self._fh.seek(0,2)defprocess_IN_CREATE(self, event):
path=self._pathif path inos.path.join(event.path, event.name):if hasattr(self, ‘fh‘):
self._fh.close()try:
self._fh= open(self._path, ‘r‘)exceptIOError as e:
sys.stderr.write(‘open file failed, %s‘ %e)else:
self._fh.seek(0,2)for r inself._fh.readlines():#sys.stdout.write(r)
process_line(r)defprocess_IN_MODIFY(self, event):
path=self._pathif path not inos.path.join(event.path, event.name):return
if notself._fh.closed:for r inself._fh.readlines():#sys.stdout.write(r)
process_line(r)defprocess_IN_MOVE_SELF(self, event):
path=self._pathif path inos.path.join(event.path, event.name):
sys.stderr.write(‘monitor file move‘)defprocess_IN_ATTRIB(self, event):pass
classTailer(object):def __init__(self, filename):
super(Tailer, self).__init__()
self._path=filename
self._notifier=None
self._init()def __del__(self):
self._notifier.stop()def_init(self):
path=self._path
index= path.rfind(‘/‘)
wm=pyinotify.WatchManager()
wm.add_watch(path[:index], DIRMASK)
handler=Handler(path)
self._notifier=pyinotify.Notifier(wm, handler)defrun(self):
self.read_last_10240_word()whileTrue:
self._notifier.process_events()ifself._notifier.check_events():
self._notifier.read_events()defread_last_10240_word(self):
with open(self._path,‘rb‘) as f:
f.seek(-10240,2)for l inf.readlines():#print(l.decode())
process_line(l.decode())defprocess_line(line_str):pass
#matcher = re.search(r‘\d{4}-\d{2}-\d{2}.*?- (DEBUG|INFO|WARNING|ERROR|CRITICAL) -[\s\S]*?(File ".*?.py", line \d*)‘, line_str)
matcher = re.search(r‘\d{4}-\d{2}-\d{2}.*?- (DEBUG|INFO|WARNING|ERROR|CRITICAL)‘, line_str)if notmatcher:print(line_str)else:
log_level_str= matcher.group(1)if log_level_str == ‘DEBUG‘:print(‘\033[0;32m%s\033[0m‘ %line_str)elif log_level_str == ‘INFO‘:print(‘\033[0;96m%s\033[0m‘ %line_str)elif log_level_str == ‘WARNING‘:print(‘\033[0;33m%s\033[0m‘ %line_str)elif log_level_str == ‘ERROR‘:print(‘\033[0;35m%s\033[0m‘ %line_str)elif log_level_str == ‘CRITICAL‘:print(‘\033[0;31m%s\033[0m‘ %line_str)if __name__ == ‘__main__‘:if len(sys.argv[1:]) != 1:print(‘Usage: python tail.py ‘)
sys.exit(0)
path= sys.argv[1]
Tailer(path).run()