38

我在RotatingFileHandlerlinux 系统上使用标准的 python (2.5.2) 日志记录模块,特别是 . 我的应用程序同时支持命令行界面和 Web 服务界面。我想让两者都写入同一个日志文件。但是,当日志文件轮换时,新文件具有644权限并归 Web 服务器用户所有,这会阻止命令行用户对其进行写入。我可以在日志配置或日志初始化期间指定新的日志文件应该是组可写的吗?

我查看了mode设置(r/ w/ a),但它似乎不支持任何文件权限。

4

8 回答 8

31

这是一个稍微好一点的解决方案。这会覆盖所使用的 _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
于 2011-07-21T16:16:39.973 回答
23

我求助于扫描 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

我发现有用的参考资料: 绑定自定义处理程序创建自定义处理程序

于 2009-09-10T21:29:32.670 回答
3

这是一个简单的解决方案,效果很好:

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 

于 2019-11-07T03:31:35.770 回答
2

这是基于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'
于 2018-08-02T00:03:38.950 回答
1

James Gardner 编写了一个只旋转文件的处理程序,而不是创建或删除它们: http ://packages.python.org/logrotate/index.html

于 2012-08-07T19:01:29.150 回答
0

看起来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

于 2020-04-01T20:26:35.927 回答
0
$ chgrp loggroup logdir
$ chmod g+w logdir
$ chmod g+s logdir
$ usermod -a -G loggroup myuser
$ umask 0002
于 2016-05-30T07:19:02.443 回答
0

我认为这里描述的是一种反模式——不同的进程不应该将数据写入同一个文件。

上面的解决方案都不适合我,在不同的情况下会导致不同的权限问题。

作为临时解决方法,我在日志文件名中添加了一个随机后缀,因此每个进程在启动时都会获得一个唯一的文件名。

解决这个问题的正确方法 - 有一个集中的日志处理程序(日志服务器),例如 rsyslog。

于 2021-04-08T23:05:11.917 回答