
ubuntu 升级后,php-FPM 将错误日志通过 stderr 发送给 nginx 时不再自动添加换行符,导致多条 Error_log() 输出被合并为一行;根本原因是 PHP 8+ 默认不再为 error_log() 的 stderr 输出追加 n,需显式添加。
ubuntu 升级后,php-fpm 将错误日志通过 stderr 发送给 nginx 时不再自动添加换行符,导致多条 `error_log()` 输出被合并为一行;根本原因是 php 8+ 默认不再为 `error_log()` 的 stderr 输出追加 `n`,需显式添加。
在旧版 PHP(如 7.1)中,error_log() 函数向 stderr 输出时会隐式补上换行符(n),因此每调用一次 error_log($msg),Nginx 的 error log 中就呈现为独立的一行(或逻辑上可区分的段落)。但自 PHP 7.4 起,该行为已被修正;PHP 8.0 及更高版本严格遵循 POSIX 标准:error_log() 向 stderr 写入时不再自动追加换行符——这意味着开发者必须显式控制换行。
你的日志代码如下:
$logger->error('.'); $logger->error('..................................................[ Developer Version ]'); $logger->error('.');
而底层实现为:
error_log($pf . $msg); // ❌ 缺少 "n"
这导致所有消息被连续写入 stderr 缓冲区,PHP-FPM 将其作为单个字符串传递给 Nginx,最终在 Nginx error log 中表现为无换行的“粘连日志”。
立即学习“PHP免费学习笔记(深入)”;
✅ 正确做法是:在每次 error_log() 调用末尾显式添加 n:
error_log($pf . $msg . "n"); // ✅ 强制换行
⚠️ 注意事项:
- 不要依赖 PHP_EOL —— 它在不同系统下可能为 rn(windows),而 Nginx 的 error log 解析器期望 unix 风格的 n;
- 若使用 Monolog 等日志库,请检查其 Handler 配置(如 ErrorLogHandler)是否已适配 PHP 8 行为;必要时自定义 Formatter 或包装 error_log() 调用;
- 该问题仅影响通过 error_log() 写入 stderr 的场景(即 error_log($message) 或 error_log($message, 0)),不影响写入文件(error_log($message, 3, $file))或 syslog 的行为;
- Nginx 本身不处理 stderr 内容的格式化,它只是原样封装并写入自己的 error log,因此换行责任完全在 PHP 层。
? 验证修复效果:
修改后重启 PHP-FPM(sudo systemctl restart php8.0-fpm)和 Nginx(sudo systemctl restart nginx),触发日志输出,观察 /var/log/nginx/error.log 是否恢复清晰分段:
2022/03/10 08:15:22 [error] 51201#51201: *3 FastCGI sent in stderr: "PHP message: . PHP message: ..................................................[ Developer Version ] PHP message: ." while reading response header from upstream, ...
总结:这不是 Nginx 或系统配置问题,而是 PHP 运行时行为变更带来的兼容性调整。保持日志可读性的关键,在于主动管理输出边界——永远为 error_log() 到 stderr 的每条消息显式结束换行。