把日志写好:输出规范与轮转清理实用指南
写代码时,我们常常只顾着把功能跑通,却忘了给程序留下一双”眼睛”——日志。等到线上出问题、脚本半夜崩了、cron 任务静默失败时,才后悔当初没有把日志写规范。本文结合我在 Termux 和服务器上的实际经验,聊聊日志的输出规范与轮转清理,让日志真正成为排查问题的利器,而不是又一处磁盘杀手。
日志应该记什么
一个常见的误区是”日志越多越好”。实际上,大量无意义的信息只会让真正的问题淹没在噪音里。好的日志至少应该包含四要素:
- 时间戳:精确到秒,最好带时区。跨时区排查问题时,没有时区的时间戳几乎等于没有。
- 级别:error、warning、info 等,方便快速过滤。
- 事件来源:是哪个模块、哪个函数产生的?多服务协作时,来源信息是定位的第一步。
- 上下文:本次操作的对象、关键参数、结果。比如”删除文件失败”远不如”删除 /data/tmp/a.log 失败:Permission denied”有用。
把这些要素写全,日志的价值就翻了几倍。
日志级别:什么时候用什么
级别是日志的”红绿灯”,级别混乱的日志比没有日志更糟。我习惯这样约定:
- error:程序无法继续执行、需要人工介入的错误。例如连接数据库失败、配置文件解析失败。
- warning:不影响本次运行,但值得警惕的情况。例如磁盘剩余空间不足 10%、重试后成功。
- info:关键流程的节点信息。任务开始、结束、耗时、处理了多少条数据。
- debug:只有调试时才需要打开的细节,默认不输出。
用 Python 内置的 logging 模块就能轻松实现分级输出:
1 | |
生产环境把 level 设为 INFO,需要排查时临时切到 DEBUG,一套配置足矣。
日志轮转:让日志不无限膨胀
日志如果不清理,最终会吃掉整个磁盘。这就是轮转(rotation)存在的意义:按大小或时间把日志切分成多个文件,旧的自动压缩或删除。日志轮转有两个经典做法:
一是按大小轮转。Python 的 RotatingFileHandler 可以控制在日志超过 1MB 时自动滚动,并保留最近 5 份:
1 | |
二是交给系统工具 logrotate。Linux 下几乎零成本,配置也直观:
1 | |
这段配置表示每天轮转一次,保留 7 份历史,旧日志压缩存档,文件不存在或为空时跳过,并用 copytruncate 避免中断正在写入的进程。在 Termux 里如果没装 logrotate,也可以写一个 cron 脚本手动轮转,原理相同。
在 Termux 里落地
手机上跑的服务同样需要日志管理。我常用的做法是:所有脚本统一把日志写到 ~/logs/ 目录,文件名带日期,再配合一个简单的清理脚本,保留最近 30 天:
1 | |
把这一行写进 cron 定时执行,日志就不会无限膨胀。另外,跑长任务的脚本建议用 nohup 加 >> 重定向,避免日志和 stdout 混在一起:
1 | |
这样即使 Termux 被切到后台,任务日志也能完整保存。
总结
日志是程序的记忆,也是一份可以复盘的财富。规范输出、合理分级、及时轮转,这三件事花不了多少时间,却能让你的排查效率提升一个量级。趁现在,给手头的脚本补上时间戳、级别和上下文,再配一个轮转策略——下次故障来时,你会感谢今天的自己。