日志量过大不直接拖慢FrankenPHP,但会引发磁盘I/O拥塞、inode耗尽等连锁问题;根本解法是停用Caddy内置轮转,改用logrotate配合copytruncate和create实现安全轮转。

日志量过大本身不直接拖慢 FrankenPHP 请求处理,但会引发磁盘 I/O 拥塞、inode 耗尽、归档卡顿甚至触发 OOM(尤其在小容量 SSD 或容器中),最终表现为请求延迟上升、write 系统调用阻塞、df -i 显示 100% inode 使用率。根本解法不是“压缩日志内容”,而是切断无限追加写入的源头,交由 logrotate 原子接管。
为什么不能靠 Caddy 的 log roll 参数切分
Caddy v2.8+ 确实支持 log 指令里的 roll(如 roll 100MB),但它只做简单文件重命名,不压缩、不归档、不清理旧文件,更关键的是:没有 copytruncate 或句柄刷新机制。高并发下 Caddy 写入时若正在 rename,可能丢日志或触发 EBUSY 错误;且无法执行 postrotate 来通知进程重新打开文件描述符——FrankenPHP 不响应 USR1,Caddy 也不支持安全 reload 日志句柄。
- 现象:
access.log突然停止增长,但access.log.1为空或不更新 - 风险:日志静默丢失,排查无依据
- 替代方案:必须弃用 Caddy 层日志轮转,回归系统级
logrotate
logrotate 配置必须含 copytruncate 和 create
copytruncate 是 FrankenPHP 场景下的刚需——它先复制当前日志内容到归档文件,再清空原文件,确保 Caddy 进程持续向同一 inode 写入,不中断、不报错;create 则保证新日志文件权限正确,避免因 www-data 无法写入导致后续日志丢失。
- 路径示例(Debian/Ubuntu):
/var/log/frankenphp/*.log,需与 Caddyfile 中log指令指定的路径完全一致 - 权限设置:
create 644 www-data www-data(CentOS/RHEL 改为apache或nginx) - 保留策略:
rotate 7(保留 7 天)比默认30更稳妥,防止小磁盘撑爆 - 触发条件可改按大小:
size 50M替代daily,更适合流量不均的业务
验证 logrotate 是否真正生效
配置完别只信 ls -lh 看到 .log.1 就算成功。要确认三点:原日志是否清空、新日志权限是否正确、Caddy 是否仍在写入。
立即学习“PHP免费学习笔记(深入)”;
- 手动触发并观察:
sudo logrotate -f /etc/logrotate.d/frankenphp && ls -l /var/log/frankenphp/,应看到access.log大小归零,access.log.1有内容,且属主是www-data - 实时监控写入:
sudo tail -f /var/log/frankenphp/access.log,触发一次请求,确认新日志行立即出现 - 检查 inode 使用:
df -i /var/log,若之前接近 100%,轮转后应明显回落
最容易被忽略的是日志路径一致性:Caddyfile 里写的 log /var/log/frankenphp/access.log,logrotate 配置就必须匹配这个完整路径,少一个斜杠或拼错单词都会导致轮转失效——而错误不会报在终端,只会安静地让日志继续疯长。



















