php自身不支持错误日志轮转,依赖logrotate或web服务器实现;需正确配置权限、信号(如usr2)及postrotate重载逻辑,容器中则由运行时日志驱动控制。

PHP 错误日志轮转靠的是系统工具,不是 PHP 自己
PHP 本身不支持日志文件自动切割或按大小/时间轮转。它只负责往一个 error_log 文件里追加写入。轮转这件事,得交给 logrotate(Linux 主流方案)或者 Web 服务器(如 Nginx/Apache)的配置来兜底。
常见错误现象:error_log 越滚越大,某天发现占了 20GB,tail -f 卡死,磁盘报警才想起这事。
- 如果你用
error_log = /var/log/php/error.log,那这个路径必须对php-fpm进程用户(比如www-data或nginx)可写 -
logrotate默认不读 PHP 配置,你得单独给它写规则,且要确保postrotate里 reloadphp-fpm或发信号(否则 PHP 还会继续往旧文件句柄写) - 不要把
error_log设成syslog后又指望logrotate去切——它切不了/dev/log
logrotate 配置 PHP 日志的关键三步
假设你的 PHP 错误日志路径是 /var/log/php/error.log,对应配置文件一般放在 /etc/logrotate.d/php:
/var/log/php/error.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 www-data www-data
sharedscripts
postrotate
if [ -f /var/run/php/php8.1-fpm.pid ]; then
kill -USR2 `cat /var/run/php/php8.1-fpm.pid`
fi
endscript
}
注意点:
立即学习“PHP免费学习笔记(深入)”;
-
sharedscripts和postrotate必须配对,否则每次轮转都触发 reload(可能造成短时不可用) -
kill -USR2是 php-fpm 的平滑重开日志文件信号;不同版本 pid 路径不同,比如php7.4-fpm.pid或php-fpm.pid,得看实际路径 -
create 644 www-data www-data权限必须匹配 php-fpm worker 用户,否则新日志写不进去,错误会静默丢弃
Apache/Nginx 下 PHP 日志走 Web 服务器时怎么轮转
如果 PHP 错误日志被设为 error_log = syslog,或者你根本没配 error_log、靠 Apache 的 ErrorLog 或 Nginx 的 error_log 统一收拢,那轮转逻辑就完全在 Web 服务侧:
- Apache:靠
rotatelogs或系统logrotate切error_log,但 PHP 的error_log()调用仍走 Apache 的日志管道,无需额外干预 - Nginx:若用
fastcgi_param PHP_VALUE "error_log=/var/log/nginx/php-error.log";动态指定,那这个/var/log/nginx/php-error.log就得进logrotate规则,且postrotate里 reload nginx(不是 php-fpm) - 混用风险:Web 服务器日志和 PHP 自定义
error_log同时开启,容易重复记录或权限冲突
为什么 error_log 写到 stdout 容器里不轮转
Docker 或 k8s 环境下,常把 error_log = /proc/self/fd/1 或直接 stdout,这时日志由容器运行时接管(如 docker logs)。轮转行为取决于宿主机的 dockerd 配置:
-
--log-opt max-size=10m --log-opt max-file=5才生效,PHP 层面任何配置都无效 - 别在容器里装
logrotate去切/proc/self/fd/1—— 这是个符号链接,指向管道,logrotate无法 rename 或 truncate - 如果用
error_log = /dev/stdout,确保 php-fpm 不启daemonize = yes,否则 stdout 会被关闭
轮转真正的复杂点不在 PHP 配置,而在信号传递是否完整、权限是否闭环、以及 stdout/stderr 在不同部署模型下的语义差异。漏掉任意一环,日志就停在某个大文件里不动了。











