本文约 3,230 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:看不到报错,不代表没报错
WordPress 层面关闭调试后,很多错误只存在于服务器日志里:502 是 PHP-FPM 挂了、504 是执行超时、403 是权限或 SELinux、内存耗尽则是 PHP fatal。
这些都不会在浏览器里显示原因。会看日志,是从”重启试试”进阶到”定位修复”的分水岭。
原理分析:三层日志各记什么
| 日志 | 记录内容 | 典型用途 |
|---|---|---|
| Nginx access.log | 每条请求:IP、URL、状态码、耗时 | 看访问量、扫描行为、异常请求 |
| Nginx error.log | Nginx 层错误:连接失败、超时、权限 | 502/504 定位 |
| PHP-FPM error.log | PHP 进程错误:启动失败、达到最大子进程 | 进程池耗尽 |
| PHP-FPM slow.log | 执行超过阈值的请求及堆栈 | 慢查询、慢插件定位 |
| MySQL error.log | 数据库错误、崩溃、启动失败 | 数据库故障 |
保姆级实操
一、确认日志位置
# Nginx
nginx -V 2>&1 | grep -o 'error-log-path=[^ ]*'
ls /var/log/nginx/
# PHP-FPM
php-fpm8.2 -i | grep -i error_log
ls /var/log/php8.2-fpm.log
# 或者直接看 systemd 日志
journalctl -u php8.2-fpm -n 100 --no-pager
journalctl -u nginx -n 100 --no-pager
二、开启 PHP-FPM 错误与慢日志
/etc/php/8.2/fpm/pool.d/www.conf:
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php8.2-fpm/site-error.log
slowlog = /var/log/php8.2-fpm/site-slow.log
request_slowlog_timeout = 5s
catch_workers_output = yes
catch_workers_output = yes 很关键:它把 worker 进程的 stdout/stderr 也收进主日志,否则部分 PHP 错误会丢失。
sudo systemctl restart php8.2-fpm
三、常用查看命令
# 实时跟踪错误日志
tail -f /var/log/nginx/error.log
# 只看最近 200 条并按时间过滤
tail -n 200 /var/log/nginx/error.log | grep '2026/10/10'
# 统计 502 数量
grep -c ' 502 ' /var/log/nginx/access.log
# 找出最慢的请求(需配置 $request_time 日志格式)
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -20
# 找被频繁访问的异常 URL
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
四、从日志特征判断故障类型
| 日志特征 | 故障 | 处理 |
|---|---|---|
connect() to unix:/run/php/php8.2-fpm.sock failed (111: Connection refused) |
PHP-FPM 没启动 | 启动服务,看启动失败原因 |
upstream timed out (110: Connection timed out) while reading response header |
PHP 执行超时 | 调 fastcgi_read_timeout 与 max_execution_time |
server reached pm.max_children setting |
进程池耗尽 | 调大 max_children 或加缓存 |
recv() failed (104: Connection reset by peer) |
PHP 进程崩溃 | 看 PHP-FPM 日志的 fatal error |
open() "/xxx" failed (13: Permission denied) |
文件权限或 SELinux | 检查属主与上下文 |
FastCGI sent in stderr: "PHP message: PHP Fatal error: Allowed memory size exhausted" |
PHP 内存不足 | 调 memory_limit 或定位内存泄漏插件 |
大量 POST /wp-login.php 且 200 但无结果 |
暴力破解 | 加登录保护、封 IP |
五、配置访问日志格式(含耗时)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log main;
$upstream_response_time 能直接看出是 PHP 慢还是 Nginx 慢。
六、日志轮转
Ubuntu/Debian 默认已配 logrotate,检查:
cat /etc/logrotate.d/nginx
cat /etc/logrotate.d/php8.2-fpm
自定义 PHP 日志的话要自己加配置, otherwise 日志会无限增长。
常见踩坑与失败案例
- 日志里什么都没有 —— 可能 Nginx 用了默认站点配置,日志写到了
/var/log/nginx/error.log之外的文件。用nginx -T | grep error_log全量查看。 - 案例:某站每天凌晨 502,白天正常。查 error.log 发现是每日备份脚本执行时 PHP 进程被占满,同时触发
pm.max_children。解决办法是把备份改到低峰并提高进程数。 - 磁盘被日志写满 —— 没有 logrotate 或轮转后没压缩。用
df -h与du -sh /var/log/* | sort -rh | head排查。 - 慢日志没生成 ——
request_slowlog_timeout设成了 0(关闭),或者 slowlog 路径 PHP-FPM 无写权限。 - ** SELinux 阻止写日志** —— 错误日志里出现
permission denied但文件权限正常,用ausearch -m AVC确认。
总结
看日志的能力可以拆成三步:知道日志在哪(nginx -V / php-fpm -i / journalctl)、会过滤(grep 状态码、按耗时排序、统计高频 URL)、能对应故障类型(上面那张特征表基本覆盖了 90% 场景)。建议给自己的服务器做一份”日志速查表”文档,把路径和常用命令记下来,出事故时不用现查。另外,日志轮转一定要配,否则排查工具本身会变成故障源。
