基于CherryPy的Python服务部署为systemd后日志无法轮转的问题
systemd环境下Python日志轮转失效的原因与解决方案
核心原因分析
- 时区环境差异:交互shell/screen启动的进程会加载用户目录下的
.bashrc、.profile等配置,通常会显式设置TZ时区变量;而systemd启动的系统服务默认不加载用户shell配置,仅使用系统全局时区(由/etc/localtime定义)。
这是最高发的诱因:如果你平时用的时区是Asia/Shanghai,但系统全局时区是UTC,那么systemd下的进程认知的“午夜”是UTC的0点(即北京时间早上8点)。你以为跨了现实中的午夜,但进程实际还要再过8小时才会触发轮转,表现为“不轮转”。 - 运行用户与环境变量缺失:你提供的单元文件没有指定
User/Group,默认会用root身份启动服务,而非平时使用的ubuntu用户。脚本依赖的HOME、PYTHONPATH等用户级环境变量会指向root的主目录(/root),可能导致配置加载异常、时区配置读取错误,间接影响轮转逻辑。 - 轮转触发条件未满足:Python原生的
TimedRotatingFileHandler只有在有新日志写入时,才会检查是否到达轮转时间阈值。如果服务跨午夜的时段恰好没有任何日志输出,轮转动作会被推迟到下一次写日志时才执行,长时间无日志时就会看起来像“从未轮转”。
对应解决方法
- 统一时区配置:二选一即可:
- 在单元文件的
[Service]段添加显式时区配置:Environment=TZ=你的时区标识(比如Asia/Shanghai),直接给进程指定时区,不依赖系统全局配置。 - 修改系统全局时区:执行
timedatectl set-timezone 你的时区标识,统一所有系统服务的时区。
验证方法:可以在
[Service]段临时添加ExecStartPre=/usr/bin/date,启动服务后用journalctl -u 你的服务名查看输出的时间,和交互shell下的date结果对比,确认时区是否一致。 - 在单元文件的
- 显式指定运行用户:在
[Service]段添加配置,让服务和平时screen下用同一个用户运行:
避免用户环境变量、权限的差异问题。User=ubuntu Group=ubuntu Environment=HOME=/home/ubuntu - 适配轮转触发逻辑:
如果确认跨午夜后有新日志仍不轮转,且时区、用户都没问题,可以测试手动触发一条日志,看是否会立即轮转。如果需要不依赖日志写入的定期轮转,可以替换为第三方的ConcurrentLogHandler,它的内置后台线程会主动按时间检查轮转。 - 完善单元文件配置:补充必要的运行规则,避免其他异常:
Restart=on-failure StandardOutput=journal StandardError=journal
修复后的完整单元文件示例
[Unit] Description=RCS API Server After=multi-user.target [Service] Type=simple User=ubuntu Group=ubuntu WorkingDirectory=/home/ubuntu/rcs-sender/ Environment=TZ=Asia/Shanghai ExecStart=/usr/bin/python3 /home/ubuntu/rcs-sender/rcs_api_server.py Restart=on-failure StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
内容的提问来源于stack exchange,提问作者Lukasz
相关产品推荐
相关产品推荐

