You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 3.2.14应用日志未轮转问题排查求助

Django日志未轮转的原因分析及解决办法

核心问题:Gunicorn多进程的文件句柄冲突

你的Gunicorn开了9个工作进程,每个worker都会单独初始化Django的日志配置,这就导致多个进程同时攥着同一个日志文件的句柄。当TimedRotatingFileHandler尝试轮转日志时,只有一个进程能完成文件重命名,但其他进程还在往旧的文件句柄里写数据——结果就是新日志文件没生成,旧文件一直变大,看起来完全没轮转。这绝对和Gunicorn的多进程有关,是这类部署场景下的常见坑。

其他可能的诱因

  • 日志目录权限不够:logs目录的权限得让ubuntu用户(Gunicorn运行用户)能创建、重命名文件。比如目录属于www-data组但没开组写入权限,或者ubuntu用户根本没权限操作这个目录,轮转操作直接失败,自然看不到效果。
    • 查权限用命令:ls -ld logs/,确保权限是类似drwxrwxr-x ubuntu www-data这种,让ubuntu有读写权限。
  • 轮转周期设置太长:你配置的interval=30+when="D"是30天才轮转一次,要是部署时间还没到30天,自然不会触发。测试的话可以改成when="M"(按分钟轮转),等几分钟看效果。
  • 缺省backupCount参数:虽然这个参数只是控制保留旧日志的数量,默认0是不删除旧日志,但如果没设置,部分场景下可能影响轮转文件的生成逻辑,建议加上试试。

针对性解决办法

1. 用系统级logrotate管理(最推荐)

放弃Django自带的轮转逻辑,用Linux系统的logrotate来管日志,彻底规避多进程冲突问题:

  • 创建配置文件/etc/logrotate.d/django-app,内容如下:
    /path/to/your/app/logs/app /path/to/your/app/logs/groups {
        daily
        rotate 30
        missingok
        notifempty
        compress
        delaycompress
        create 660 ubuntu www-data
        sharedscripts
        postrotate
            # 给Gunicorn发USR1信号,让所有worker重新打开日志文件
            pkill -USR1 gunicorn
        endscript
    }
    
  • 手动测试执行:logrotate -f /etc/logrotate.d/django-app,看看日志会不会轮转。

2. 用多进程安全的日志Handler

安装concurrent-log-handler包,它专门解决多进程下的日志轮转问题:

  • 安装命令:pip install concurrent-log-handler
  • 修改Django的LOGGING配置里的handler:
    "app": {
        "level": "INFO",
        "class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
        "formatter": "elegant",
        "filename": os.path.join("logs", "app"),
        "maxBytes": 10485760,  # 单个日志文件最大10MB
        "backupCount": 30,     # 保留30个旧日志
        "encoding": "utf-8",
    },
    "groups": {
        "level": "INFO",
        "class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
        "formatter": "elegant",
        "filename": os.path.join("logs", "groups"),
        "maxBytes": 10485760,
        "backupCount": 30,
        "encoding": "utf-8",
    },
    

3. 调整Gunicorn启动参数

别用--preload参数,因为--preload会在fork worker之前就加载Django,导致所有worker共享同一个日志文件句柄,加剧冲突。确保Gunicorn是每个worker单独加载Django和日志配置。

内容的提问来源于stack exchange,提问作者Diego Carabajal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:13:20