# 日志切割(logrotate) ## 场景 `/var/log` 被应用日志撑满,根分区 100%,或者需要一个服务只保留 14 天日志。 ## 前置条件 - 应用把日志写在固定路径 - 应用支持重新打开日志文件(或者接受 `copytruncate`) - 有 root 权限 ## 配置 ```bash cat >/etc/logrotate.d/myapp <<'EOF' /opt/myapp/logs/*.log { daily rotate 14 missingok notifempty compress delaycompress copytruncate dateext dateformat -%Y%m%d create 0640 appuser appuser } EOF ``` - `copytruncate`:复制后清空原文件,适合不重启的应用 - `create`:重新创建文件时给对权限,否则应用写不进去 ## 验证 ```bash logrotate -d /etc/logrotate.d/myapp # 只演练,不执行 logrotate -f /etc/logrotate.d/myapp # 强制执行一次 ls -lh /opt/myapp/logs/ ``` `-d` 的输出里能看到哪些文件会被处理、为什么被跳过。 ## 回滚 ```bash rm /etc/logrotate.d/myapp ``` 已切割出来的历史文件手动清理。 ## 坑 - **`copytruncate` 会丢一小段日志**(复制和清空之间的写入),要求严格就别用,改用 `postrotate` 发信号。 - `create` 的属主写错,应用重启后写不了日志。 - 全局 `/etc/logrotate.conf` 里可能已经有 `weekly`,单文件没写周期会继承默认值。 - `missingok` 和 `notifempty` 建议都加,不然空日志或临时不存在的路径会报错。 - 日志切割不解决磁盘满,先 `du -sh /var/log/*` 看看是谁大。 - 容器里的日志不走 logrotate,用 docker 的日志驱动限制。