Python 脚本的日志怎么做才不会把磁盘写满
一、别用 print 当日志
`print` 没有级别、没有时间戳、不能重定向。用标准库 `logging`:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
log = logging.getLogger(__name__)
log.info("started")
二、按大小切割
`RotatingFileHandler` 是最省心的方案:
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
"/var/log/myapp/app.log",
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5, # 最多保留 5 个历史文件
encoding="utf-8",
)
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s"))
log = logging.getLogger("app")
log.addHandler(handler)
log.setLevel(logging.INFO)
这样最多占用 60 MB(6 个文件 × 10 MB),不会无限增长。
三、按天切割
如果需要按日期归档,用 `TimedRotatingFileHandler`:
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(
"/var/log/myapp/app.log",
when="midnight",
interval=1,
backupCount=7, # 保留 7 天
encoding="utf-8",
)
注意 `when="midnight"` 是按**服务器本地时区**切的。如果服务跑在 UTC 而你在东八区,切割时间会差 8 小时。要么统一时区,要么用 `utc=True` 并自己换算。
四、systemd 服务的日志
如果服务由 systemd 管理,可以直接让 systemd 接管:
StandardOutput=append:/var/log/myapp/app.log
StandardError=append:/var/log/myapp/app.log
但这样没有切割。两种做法:
1. 用 `logrotate` 定期切
2. 让 Python 自己写文件并切割(上面两种 Handler),systemd 只接 stderr
我更倾向第二种,因为切割策略和业务逻辑在同一个地方,不容易漏配。
五、logrotate 配置示例
如果选择交给 logrotate:
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0640 root root
postrotate
systemctl reload myapp 2>/dev/null || true
endscript
}
`delaycompress` 让最新一个归档不压缩,方便直接看。
六、别把敏感信息写进日志
这是最容易忽略的。日志里绝对不能出现:
• 密码、API key、token
• 完整 cookie
• 用户身份证、手机号全号
脱敏写法:
def mask(s, keep=4):
if not s or len(s) <= keep * 2:
return "***"
return s[:keep] + "*" * (len(s) - keep * 2) + s[-keep:]
log.info("token=%s", mask(token))
七、日志级别别全开
生产环境用 `INFO`,排查时临时改 `DEBUG`。全开 `DEBUG` 会让日志量涨几十倍,还可能把敏感数据打出来。
小结
日志三件事:**会切割、能查、不泄密**。用 `RotatingFileHandler` 解决第一个,用统一格式和时间戳解决第二个,脱敏函数解决第三个。
- 点赞
- 收藏
- 关注作者
评论(0)