我在RotatingFileHandler
linux 系统上使用标准的 python (2.5.2) 日志记录模块,特别是 . 我的应用程序同时支持命令行界面和 Web 服务界面。我想让两者都写入同一个日志文件。但是,当日志文件轮换时,新文件具有644
权限并归 Web 服务器用户所有,这会阻止命令行用户对其进行写入。我可以在日志配置或日志初始化期间指定新的日志文件应该是组可写的吗?
我查看了mode
设置(r
/ w
/ a
),但它似乎不支持任何文件权限。
我在RotatingFileHandler
linux 系统上使用标准的 python (2.5.2) 日志记录模块,特别是 . 我的应用程序同时支持命令行界面和 Web 服务界面。我想让两者都写入同一个日志文件。但是,当日志文件轮换时,新文件具有644
权限并归 Web 服务器用户所有,这会阻止命令行用户对其进行写入。我可以在日志配置或日志初始化期间指定新的日志文件应该是组可写的吗?
我查看了mode
设置(r
/ w
/ a
),但它似乎不支持任何文件权限。
这是一个稍微好一点的解决方案。这会覆盖所使用的 _open 方法。在创建之前设置 umask,然后将其恢复为原来的状态。
class GroupWriteRotatingFileHandler(logging.handlers.RotatingFileHandler):
def _open(self):
prevumask=os.umask(0o002)
#os.fdopen(os.open('/path/to/file', os.O_WRONLY, 0600))
rtv=logging.handlers.RotatingFileHandler._open(self)
os.umask(prevumask)
return rtv
我求助于扫描 logging.handlers 模块,但看不到任何指定不同文件权限模式的方法。所以,我现在有一个基于将 RotatingFileHandler 扩展为自定义处理程序的解决方案。一旦我找到了一些很好的参考来创建一个,这相当轻松。自定义处理程序的代码如下。
class GroupWriteRotatingFileHandler(handlers.RotatingFileHandler):
def doRollover(self):
"""
Override base class method to make the new log file group writable.
"""
# Rotate the file first.
handlers.RotatingFileHandler.doRollover(self)
# Add group write to the current permissions.
currMode = os.stat(self.baseFilename).st_mode
os.chmod(self.baseFilename, currMode | stat.S_IWGRP)
我还发现,要从日志配置文件中引用自定义处理程序,我必须将我的模块绑定到日志命名空间。做起来很简单,但很烦人。
from mynamespace.logging import custom_handlers
logging.custom_handlers = custom_handlers
这是一个简单的解决方案,效果很好:
import os
class GroupWriteRotatingFileHandler(handlers.RotatingFileHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
os.chmod(self.baseFilename, 0o0777) # You can change whatever permission you want here.
# you can also change the group of the file:
os.chown(self.baseFilename, uid, gid) # pass the user_id and group_id you want to set
这是基于rob解决方案的 Django 完整解决方案。在my_module
:
import logging
import logging.handlers
import os
在日志记录配置期间发生的class=
情况在日志记录模块的命名空间中进行评估,默认情况下,它没有与处理程序的绑定。所以我们必须在扩展它之前明确地把它放进去。请参阅此 SO 文章
logging.handlers = logging.handlers
正是这个神奇的咒语让我永远找到了——我简直不敢相信它做了什么!最后,Jon 的类将正确加载。
class GroupWriteRotatingFileHandler(logging.handlers.RotatingFileHandler):
def _open(self):
prevumask = os.umask(0o002)
rtv = logging.handlers.RotatingFileHandler._open(self)
os.umask(prevumask)
return rtv
要将其用于 Django,请在设置文件中添加以下 this
from my_module import GroupWriteRotatingFileHandler
logging.handlers.GroupWriteRotatingFileHandler = GroupWriteRotatingFileHandler
然后在LOGGING['handlers']['file']
你有
'class': 'logging.handlers.GroupWriteRotatingFileHandler'
James Gardner 编写了一个只旋转文件的处理程序,而不是创建或删除它们: http ://packages.python.org/logrotate/index.html
看起来def _open(self):
与umask(0o000)
获得-rw-rw-rw-
.
os.chmod(self.baseFilename, 0o0777)
ValueError: Unable to configure handler 'some_handler': [Errno 1] Operation not permitted:
如果日志文件拥有与正在运行的进程不同的所有权,则失败root:root
,例如testuser
.
from logging import handlers
import logging
import os
class GroupWriteRotatingFileHandler(handlers.RotatingFileHandler):
def _open(self):
prevumask = os.umask(0o000) # -rw-rw-rw-
rtv = logging.handlers.RotatingFileHandler._open(self)
os.umask(prevumask)
return rtv
LOGGING = {
'handlers': {
'db_handler': {
'level': 'DEBUG',
'class': 'log.GroupWriteRotatingFileHandler',
'filename': PATH_TO_LOGS + '/db.log',
'maxBytes': maxBytes,
'backupCount': backupCount,
'formatter': 'standard',
},
日志文件:
logs]# ls -lrt
-rw-rw-rw- 1 root root 71 Apr 1 16:02 db.log
logs]# ls -lrt
total 0
-rw-rw-rw- 1 testuser testuser 0 Apr 1 16:20 db.log
$ chgrp loggroup logdir
$ chmod g+w logdir
$ chmod g+s logdir
$ usermod -a -G loggroup myuser
$ umask 0002
我认为这里描述的是一种反模式——不同的进程不应该将数据写入同一个文件。
上面的解决方案都不适合我,在不同的情况下会导致不同的权限问题。
作为临时解决方法,我在日志文件名中添加了一个随机后缀,因此每个进程在启动时都会获得一个唯一的文件名。
解决这个问题的正确方法 - 有一个集中的日志处理程序(日志服务器),例如 rsyslog。