无法在gunicorn守护进程模式下让Flask的日志记录工作

9 投票
3 回答
4421 浏览
提问于 2025-04-18 14:55

我正在用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 个回答

0

为了满足你的需求,请把 --capture-output 设置为 True。这样可以把你的应用输出转发到错误日志文件里。

我遇到的另一个问题是,在守护进程模式下,输出到标准输出和标准错误的内容都没有地方去。这在 gunicorn 在 Docker 容器里运行时特别烦人。

0

在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;
    }
}
2

所以,你实际上并没有设置任何日志记录。让我来解释一下。

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启动的?)

撰写回答