Python 3.x 收到信号后,在python3中旋转(重新打开)文件

Python 3.x 收到信号后,在python3中旋转(重新打开)文件,python-3.x,logging,signals,logrotate,Python 3.x,Logging,Signals,Logrotate,我有一个简单的脚本,它记录到一个日志文件。这是我脚本的核心: with open('/var/log/mail/mail.log', 'a', buffering=1) as f: for line in sys.stdin: f.write(line) 正在写入的文件/var/log/mail/mail.log必须通过logrotate定期旋转。此时,当logrotate旋转文件时,我的脚本没有意识到它,并继续写入旧的(现在重命名的)文件 logrotate可以在文件

我有一个简单的脚本,它记录到一个日志文件。这是我脚本的核心:

with open('/var/log/mail/mail.log', 'a', buffering=1) as f:
    for line in sys.stdin:
        f.write(line)
正在写入的文件
/var/log/mail/mail.log
必须通过
logrotate
定期旋转。此时,当
logrotate
旋转文件时,我的脚本没有意识到它,并继续写入旧的(现在重命名的)文件

logrotate
可以在文件旋转后执行命令。通常,当
rsyslog
正在记录时,命令为:

postrotate
    invoke-rc.d rsyslog rotate > /dev/null
endscript
但在我的例子中,我需要向脚本发送一些信号,并在脚本中处理这些信号

另外,我事先不知道我的脚本是如何运行的


如何最好地实现这一点?

作为解决方案,您可以查看打开的日志文件的inode是否与路径相同。如果没有,请重新打开该文件。这只适用于Unix

import os, sys, stat

logfile = '/var/log/mail/mail.log'

while True:
    with open(logfile, 'a', buffering=1) as f:
        f_ino = os.stat(logfile)[stat.ST_INO]
        f_dev = os.stat(logfile)[stat.ST_DEV]
        for line in sys.stdin:
            f.write(line)
            try:
                if os.stat(logfile)[stat.ST_INO] != f_ino or 
                   os.stat(logfile)[stat.ST_DEV] != f_dev:
                     break
            except OSError: # Was IOError with python < 3.4
                pass
            
导入操作系统、系统、状态
logfile='/var/log/mail/mail.log'
尽管如此:
打开(日志文件'a',缓冲=1)为f时:
f_ino=os.stat(日志文件)[stat.ST_ino]
f_dev=os.stat(日志文件)[stat.ST_dev]
对于sys.stdin中的行:
f、 写(行)
尝试:
如果os.stat(日志文件)[stat.ST_INO]!=菲诺
os.stat(日志文件)[stat.ST_DEV]!=f_dev:
打破
除了OSError:#是python<3.4的IOError吗
通过
不需要关闭文件,因为它是由
上下文管理器通过
处理的

try..except
块用于捕获系统函数
os.stat
的任何错误。可能是在文件更改期间,函数返回一个
OSError
(例如
FileNotFoundError
)。在这种情况下,它将通过异常并重试检查inode是否已更改。如果我们省略这个
try