Django与fcgi - 日志问题

7 投票
3 回答
2508 浏览
提问于 2025-04-15 13:16

我有一个用Django搭建的网站。前端使用lighttpd,并通过fcgi来托管Django。

我启动fcgi进程的方式如下:

python2.6 /<snip>/manage.py runfcgi maxrequests=10 host=127.0.0.1 port=8000 pidfile=django.pid

为了记录日志,我定义了一个RotatingFileHandler,具体如下:

file_handler = RotatingFileHandler(filename, maxBytes=10*1024*1024, backupCount=5,encoding='utf-8')

日志记录是正常工作的。不过,看起来这些日志文件在还没达到10Kb的时候就开始轮换了,更别提10Mb了。我猜每个fcgi实例只处理10个请求,然后就会重新启动。每次fcgi重新启动时,都会创建一个新文件。我确认fcgi会在一段时间后(虽然不太好判断具体时间,但通常在一分钟内)以新的进程ID启动。

有没有办法解决这个问题呢?我希望所有的fcgi实例都能记录到同一个文件,直到这个文件达到大小限制,这时才进行日志文件的轮换。

3 个回答

0

看起来你使用的是默认的文件打开模式“追加”("a"),而不是“写入”("w")。这样的话,如果一个进程重新启动,它应该会在已有的文件后面继续添加内容,当文件大小达到限制时就会换个文件。所以我不太确定你看到的情况是不是因为CGI进程重新启动造成的。(当然,这里假设文件名在进程重新启动时保持不变)。

虽然日志记录的工具是线程安全的,但它并不能处理多个进程同时访问同一个文件的问题,因为在标准库中没有统一的解决办法。我通常的建议是设置一个单独的守护进程,这个进程实现一个套接字服务器,通过它来记录接收到的事件到文件中。其他进程只需要实现一个SocketHandler来和这个日志守护进程通信。这样所有的事件就能正确地序列化到磁盘上。Python的文档中有一个可用的套接字服务器,可以作为这个需求的基础。

2

如果我是你,我会换成一个叫做 TimedRotatingFileHandler 的东西。我很惊讶基于文件大小的轮换文件处理器会出现这个问题,因为它应该不受哪些进程在生成日志条目的影响。不过,时间轮换的版本(虽然不能完全按照你想要的参数来控制)应该能解决这个问题。或者,你也可以自己写一个更可靠的轮换文件处理器(你可以参考标准库的源代码),确保不同的进程不会造成问题(因为它们本来就不应该有问题)。

6

正如Alex所说,记录日志是线程安全的,但标准的日志处理器不能安全地从多个进程同时写入一个文件。

ConcurrentLogHandler使用文件锁定的方式,允许多个进程同时进行日志记录。

撰写回答