无法在gunicorn守护进程模式下让Flask的日志记录工作
我正在用gunicorn和Nginx运行一个Flask网页应用。我把gunicorn设置成了daemon
模式。我配置了gunicorn和nginx,让它们把访问记录和错误记录到文件里。但是,我就是无法把Flask的日志记录到文件中。
我用一个脚本文件来启动我的应用,使用gunicorn:
#!/bin/bash
export VIRTUAL_ENV="/to/virtual/path"
export PATH="$VIRTUAL_ENV/bin:$PATH"
source "$VIRTUAL_ENV/bin/activate"
NAME="hello"
NUM_WORKERS=1
exec gunicorn hello:app \
--name $NAME \
--workers $NUM_WORKERS \
--log-level=debug \
--daemon \
--pid $VIRTUAL_ENV/logs/pid_gunicorn \
--access-logfile $VIRTUAL_ENV/logs/access_gunicorn.log \
--error-logfile $VIRTUAL_ENV/logs/error_gunicorn.log
在我的Flask应用中,我按照文档的要求添加了日志记录:
app.debug = False
...
if __name__ == '__main__':
if app.debug != True:
import logging
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler("flask.log", maxBytes=10000, backupCount=1)
handler.setLevel(logging.DEBUG)
app.logger.addHandler(handler)
app.logger.debug("test!!")
app.run()
我还在其他地方加了app.logger.debug
。
当我不加--daemon
启动gunicorn
时,日志文件正常工作。但是一旦我加上--daemon
,就没有日志生成了。
我试过用print
,但它也只在不加--daemon
时有效。
我搜索了一段时间,发现似乎gunicorn不支持应用日志记录。但我以为记录到文件应该没问题吧?
有没有人知道在我的设置下,如何才能把日志记录到文件里呢?
3 个回答
为了满足你的需求,请把 --capture-output 设置为 True。这样可以把你的应用输出转发到错误日志文件里。
我遇到的另一个问题是,在守护进程模式下,输出到标准输出和标准错误的内容都没有地方去。这在 gunicorn 在 Docker 容器里运行时特别烦人。
在Python中,运行一个后台进程的推荐方法是使用像Supervisord这样的工具,别再用bash了,直接用Python吧。你有没有考虑过用nginx作为代理呢?Gunicorn可以处理WSGI(Web服务器网关接口)。我记得从1.3.13版本开始就可以用了。虽然它主要是为了处理websocket,但即使你在用http协议,它也能正常工作。
类似这样的代码:
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/example.log;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
所以,你实际上并没有设置任何日志记录。让我来解释一下。
gunicorn的第一个参数是你的应用程序,比如说 gunicorn hello:app
。当你启动gunicorn时,它会使用普通的Python导入方式,基本上就是 from hello import app
。
在你的文件hello.py中,你设置了日志记录。但是,你把那段代码放在了 if __name__ == "__main__":
这个块里。如果你执行 python hello.py
,那是可以工作的。但这并不是gunicorn在做的事情。你的服务并没有执行那段代码(你应该注意到这一点——毕竟,你的开发服务器也没有在运行……)
把日志记录的设置放在文件的顶部,放在if块外面。你也可以选择让gunicorn使用 capture-output
,这样它就会处理将你的应用输出写入日志文件。这可能更接近你想要的效果。如果你使用了你现有的日志配置,gunicorn会运行多个独立的进程,它们都会试图写入同一个磁盘文件。
我不太明白你说的“日志记录工作得很好”是什么意思——是说它写入了一个文件吗?我预期的是,如果没有使用 --daemon 参数,gunicorn会在前台运行,它的输出会显示在你的终端上(但不会写入磁盘,除非你把脚本的输出重定向到磁盘?或者是用systemd启动的?)