我使用以下代码来跟踪ssh登录:
readline()
我注意到这个剧本在几天后突然停止工作。我没有收到任何错误,它没有终止,它只是停止工作,好像echo 'test' >> auth.log.1
永远不会返回。
所以我执行了一个auth.log
,这确实最终被脚本处理了,因为前一段时间auth.log.1
被重命名为{{1}}
如何跟踪何时发生这种日志轮换并进行相应调整?
答案 0 :(得分:5)
使用e4c5的答案我最终得到了这段代码,这也解决了每秒多次调用readline()
的问题。
在第一次调用期间,它会跳到文件末尾并等待修改。移动文件后,它会重新打开文件并读取整个内容,然后开始等待。
import os
import time
import traceback
import threading
import inotify.adapters
logfile = b'/var/log/auth.log'
#logfile = b'logfile.log'
##################################################################
def process(line, history=False):
if history:
print '=', line.strip('\n')
else:
print '>', line.strip('\n')
##################################################################
from_beginning = False
notifier = inotify.adapters.Inotify()
while True:
try:
#------------------------- check
if not os.path.exists(logfile):
print 'logfile does not exist'
time.sleep(1)
continue
print 'opening and starting to watch', logfile
#------------------------- open
file = open(logfile, 'r')
if from_beginning:
for line in file.readlines():
process(line, history=True)
else:
file.seek(0,2)
from_beginning = True
#------------------------- watch
notifier.add_watch(logfile)
try:
for event in notifier.event_gen():
if event is not None:
(header, type_names, watch_path, filename) = event
if set(type_names) & set(['IN_MOVE_SELF']): # moved
print 'logfile moved'
notifier.remove_watch(logfile)
file.close()
time.sleep(1)
break
elif set(type_names) & set(['IN_MODIFY']): # modified
for line in file.readlines():
process(line, history=False)
except (KeyboardInterrupt, SystemExit):
raise
except:
notifier.remove_watch(logfile)
file.close()
time.sleep(1)
#-------------------------
except (KeyboardInterrupt, SystemExit):
break
except inotify.calls.InotifyError:
time.sleep(1)
except IOError:
time.sleep(1)
except:
traceback.print_exc()
time.sleep(1)
##################################################################
答案 1 :(得分:2)
最好使用inotify,您不希望继续轮询文件系统,以询问在循环的每次迭代过程中是否有变化。这是浪费了很多IO。发生更改时,inotify
会通知您。手册中有一个示例,显示了它与日志文件的用法。
答案 2 :(得分:1)
你可以查看文件的inode。
import os
inode = os.stat('/var/log/auth.log').st_ino
当inode更改时,文件已旋转。
答案 3 :(得分:1)
显然,我只有在> = 50的声誉时才能发表评论。
@ daniel-f有一个很棒的例子!我遇到的唯一情况是,当我正在读取的创建循环日志文件的服务重新启动时,它将删除旧文件并创建新文件。
这会导致“通知程序”失去对日志文件的可见性(因为它有所不同)。
由于服务每60秒写入一次日志文件,因此我对for循环进行了快速修改,如下所示:
last_pull = datetime.datetime.now()
while True:
...
...
for event in notifier.event_gen():
if event is not None:
last_pull = datetime.datetime.now()
(header, type_names, watch_path, filename) = event
if set(type_names) & set(['IN_MOVE_SELF']): # moved
notifier.remove_watch(file_watcher.intput_logfile)
file.close()
time.sleep(1)
break
elif set(type_names) & set(['IN_MODIFY']): # modified
lines = file.readlines()
for line in lines:
process(line, file_watcher, history=False)
else:
if (datetime.datetime.now() - last_pull).total_seconds() >= time_to_refresh:
last_pull = datetime.datetime.now()
notifier.remove_watch(file_watcher.intput_logfile)
file.close()
break
这将在75秒后重新监视文件而不进行更新。