在 open() 中处理 logrotate
Handling logrotate in open()
我正在使用以下函数逐行跟踪和处理日志文件:
def tail(f):
f.seek(0,2)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
with open("/var/log/some.log") as f:
for line in tail(f):
...
logrotate 旋转文件时,该函数卡在最后一行。我想 logrotate 会移动文件并创建一个新文件,让程序仍在等待旧文件的行。
处理此问题的好方法是什么 - 发生旋转时重新打开文件?
通常的标准方法是告诉 logrotate 将 HUP 信号发送到处理日志的 service/program。
在 logrotate 配置中,这是通过 postrotate 脚本完成的:
postrotate
/usr/bin/killall -HUP your_process
endscript
然后在您的 python 程序中,您必须处理信号 HUP。您在 python's signal doc 中有一个示例。您需要处理 signal.SIGHUP
另一种不太标准的方法是将 inode 编号与(可能)新的 inode 编号进行比较。如果这些数字不同,那么您就知道该文件已更改,您需要重新打开它。
我试过类似的方法,它似乎有效:
import os
import time
logname = "logfile"
logfile = open(logname, "r")
def tail(f):
f.seek(0,2)
inode = os.fstat(f.fileno()).st_ino
while True:
line = f.readline()
if not line:
time.sleep(0.1)
if os.stat(logname).st_ino != inode:
f.close()
f = open(logname, 'r')
inode = os.fstat(f.fileno()).st_ino
continue
yield line
for line in tail(logfile):
...
我正在使用以下函数逐行跟踪和处理日志文件:
def tail(f):
f.seek(0,2)
while True:
line = f.readline()
if not line:
time.sleep(0.1)
continue
yield line
with open("/var/log/some.log") as f:
for line in tail(f):
...
logrotate 旋转文件时,该函数卡在最后一行。我想 logrotate 会移动文件并创建一个新文件,让程序仍在等待旧文件的行。
处理此问题的好方法是什么 - 发生旋转时重新打开文件?
通常的标准方法是告诉 logrotate 将 HUP 信号发送到处理日志的 service/program。
在 logrotate 配置中,这是通过 postrotate 脚本完成的:
postrotate
/usr/bin/killall -HUP your_process
endscript
然后在您的 python 程序中,您必须处理信号 HUP。您在 python's signal doc 中有一个示例。您需要处理 signal.SIGHUP
另一种不太标准的方法是将 inode 编号与(可能)新的 inode 编号进行比较。如果这些数字不同,那么您就知道该文件已更改,您需要重新打开它。
我试过类似的方法,它似乎有效:
import os
import time
logname = "logfile"
logfile = open(logname, "r")
def tail(f):
f.seek(0,2)
inode = os.fstat(f.fileno()).st_ino
while True:
line = f.readline()
if not line:
time.sleep(0.1)
if os.stat(logname).st_ino != inode:
f.close()
f = open(logname, 'r')
inode = os.fstat(f.fileno()).st_ino
continue
yield line
for line in tail(logfile):
...