什么时候需要按天切割日志
Flask 应用如果长期运行,日志文件会持续增长,单个日志文件过大不仅影响读写效率,也不方便按时间维度排查问题。按天切割日志可以让每天的错误、请求、调试信息各自归档,配合定期删除旧文件,能控制磁盘占用。适合日志量稳定、需要保留一段时间(如 30 天)的场景,比如中小型 API 服务、后台定时任务等。
核心实现:TimedRotatingFileHandler 的配置
判断日志切割是否按天执行,关键看 TimedRotatingFileHandler 的 when 参数设置为 'midnight' 或 'd' 且 interval=1。'midnight' 会在每天午夜零点切割,而 'd' 则从应用启动时计算间隔。实际生产环境中,建议使用 'midnight',避免因应用重启导致切割时间错乱。检查时,观察次日是否生成新文件,旧文件文件名是否带上日期后缀,如 app.log.2025-01-01。
实现按天切割并删除旧日志,核心是配置 TimedRotatingFileHandler 的 backupCount 参数。例如 backupCount=30 表示保留最近 30 天日志,超出部分自动删除。务必在日志配置中设置延迟写入(delay=True)避免文件句柄竞争。同时建议结合 logging.getLogger(__name__) 获取 logger,避免全局日志器冲突。示例:handler = TimedRotatingFileHandler('app.log', when='midnight', interval=1, backupCount=30, encoding='utf-8')。
风险与边界条件
backupCount 删除逻辑依赖于日志文件名中的日期后缀,如果自定义 suffix 格式需保持兼容。默认后缀为 %Y-%m-%d,若修改需同步调整计算逻辑。注意:若应用长时间未运行,恢复后 handler 可能误删当前日期前几天的日志。建议在开机自启脚本中检查日志目录,避免日志文件缺失导致程序异常。另外,多进程环境下需使用 QueueHandler 和 QueueListener,否则日志可能混乱。
一个典型坑是 TimedRotatingFileHandler 在 Windows 下对已打开日志文件无法重命名,导致切割失败。解决方案:设置 delay=True,或使用 RotatingFileHandler 配合自定义切割器。另一个坑是 backupCount 设置为 0 时不会自动删除旧日志,需明确设置正数。此外,若日志路径包含中文或特殊字符,需处理编码问题。检查方法:查看日志目录文件数量是否超过 backupCount+1,确认旧日志是否被移除。
部署后的检查步骤
配置完成后,建议先手动验证。可以临时调整系统时间(测试环境)触发切割,观察日志文件名变化。正常时,每天应有一个新的主日志文件,旧文件有日期后缀。文件总数应为 backupCount + 1(当前日志 + 历史文件),超出部分会被自动删除。使用命令 ls -lt /path/to/logs/ 按时间排序查看,确认最早日期的文件已消失。如果日志写入量很小,切割依然会在午夜触发,不必担心文件大小未达阈值。
如果发现切割未执行或删除失效,先检查 when 和 backupCount 参数是否正确,再看日志目录是否有写权限,以及是否存在其他进程占用日志文件句柄。多进程场景下,务必引入 QueueHandler,否则每个进程各自切割会产生重复或缺失。
总结
按天切割并删除旧日志依赖 TimedRotatingFileHandler 的正确参数,重点是 when='midnight'、backupCount 正数、delay=True。Windows 和多进程环境需要额外处理。验证时关注文件数量和日期后缀。如果遇到异常,通常可以从文件句柄竞争、参数设置、目录权限三个方向排查。