pythonlogging.handlers.RotatingFileHandler是否允许创建组可写日志文件?

发布于 2024-08-04 14:26:25 字数 330 浏览 11 评论 0原文

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

我已经研究了 mode 设置 (r/w/a),但似乎没有支持任何文件权限。

I'm using the standard python (2.5.2) logging module, specifically the RotatingFileHandler, on a linux system. My application supports both a command-line interface and a web-service interface. I would like to have both write to the same log file. However, when the log file gets rotated, the new file has 644 permissions and is owned by the web server user which prevents the command-line user from writing to it. Can I specify that new log files should be group-writable in the logging configuration or during logging initialization?

I have looked into the mode setting (r/w/a), but it doesn't seem to support any file permissions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

柳若烟 2024-08-11 14:26:25

这是一个稍微好一点的解决方案。这会覆盖所使用的 _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

Here is a slightly better solution. this overrides the _open method that is used. setting the umask before creating then returning it back to what it was.

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
━╋う一瞬間旳綻放 2024-08-11 14:26:25

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

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

I resorted to scanning the logging.handlers module and was unable to see any way to specify a different file permissions mode. So, I have a solution now based on extending the RotatingFileHandler as a custom handler. It was fairly painless, once I found some nice references to creating one. The code for the custom handler is below.

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)

I also discovered that to reference the custom handler from a logging config file, I had to bind my module to the logging namespace. Simple to do, but annoying.

from mynamespace.logging import custom_handlers
logging.custom_handlers = custom_handlers

References I found useful:
binding custom handlers and
creating custom handlers

忘你却要生生世世 2024-08-11 14:26:25

这是一个运行良好的简单解决方案:

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 

Here is a simple solution worked fine:

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 

流星番茄 2024-08-11 14:26:25

这是基于 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 中使用它,请在设置文件中添加以下内容

from my_module import GroupWriteRotatingFileHandler
logging.handlers.GroupWriteRotatingFileHandler = GroupWriteRotatingFileHandler

然后在 LOGGING['handlers']['file'] 中添加

'class': 'logging.handlers.GroupWriteRotatingFileHandler'

Here's a complete solution for Django based on rob's solution. in my_module :

import logging
import logging.handlers
import os

The class= that happens during the logging configuration is evaluated in the namespace of the logging module, and by default this does not have a binding to handlers. So we have to put it in explicitly before we can extend it. See this SO article

logging.handlers = logging.handlers

It's this magical incantation that took me forever to find - I couldn't believe it did anything! Finally, Jon's class will load without errors.

class GroupWriteRotatingFileHandler(logging.handlers.RotatingFileHandler):    
    def _open(self):
        prevumask = os.umask(0o002)
        rtv = logging.handlers.RotatingFileHandler._open(self)
        os.umask(prevumask)
        return rtv

To use this for Django add the following this in the settings file

from my_module import GroupWriteRotatingFileHandler
logging.handlers.GroupWriteRotatingFileHandler = GroupWriteRotatingFileHandler

And then in LOGGING['handlers']['file'] you have

'class': 'logging.handlers.GroupWriteRotatingFileHandler'
最冷一天 2024-08-11 14:26:25

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

James Gardner has written a handler that only rotates files, not creating or deleting them:
http://packages.python.org/logrotate/index.html

嘦怹 2024-08-11 14:26:25
$ chgrp loggroup logdir
$ chmod g+w logdir
$ chmod g+s logdir
$ usermod -a -G loggroup myuser
$ umask 0002
$ chgrp loggroup logdir
$ chmod g+w logdir
$ chmod g+s logdir
$ usermod -a -G loggroup myuser
$ umask 0002
聚集的泪 2024-08-11 14:26:25

看来 def _open(self):umask(0o000) 配合使用,获得了 -rw-rw-rw- 的所有权限。

os.chmod(self.baseFilename, 0o0777) 失败,并出现 ValueError: 无法配置处理程序“some_handler”: [Errno 1] 不允许操作: 如果日志文件具有所有权与正在运行的进程不同的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

It looks that def _open(self): worked with umask(0o000) to get all the permissions of -rw-rw-rw-.

os.chmod(self.baseFilename, 0o0777) failed with ValueError: Unable to configure handler 'some_handler': [Errno 1] Operation not permitted: if the log file has ownership of root:root that's different from running process's, such as 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',
        },

Log files:

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

凉宸 2024-08-11 14:26:25

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

上面的解决方案都不适合我,在不同的场景中导致不同的权限问题。

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

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

I think what described here is an anti-pattern - different processes should not write data into the same file.

And non of the solutions above worked for me, causing different permissions issues in different scenarios.

As a temp workaround I've added a random suffix into the log filename so each process will get a unique filename on a startup.

The proper way to solve this issue - have a centralized log handler (log server), e.g. rsyslog.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文