本文约 2,972 字,预计阅读 8 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:白屏的时候,错误就藏在日志里
WordPress 白屏(WSOD)最折磨人的地方是”什么都没显示”。其实 PHP 早就报错了,只是默认被隐藏了。
打开 WP_DEBUG,错误信息就会出现——但如果配置不当,这些信息会直接显示在页面上,把服务器绝对路径、数据库结构暴露给所有访客,这比白屏更糟。
原理分析:四个常量的分工
define('WP_DEBUG', true); // 总开关:是否进入调试模式
define('WP_DEBUG_LOG', true); // 是否把错误写入 wp-content/debug.log
define('WP_DEBUG_DISPLAY', false); // 是否在页面上显示错误
define('SAVEQUERIES', true); // 是否记录每条 SQL 及其耗时(很耗性能)
还有两个补充常量:
define('SCRIPT_DEBUG', true); // 加载未压缩的 CSS/JS(开发用)
define('WP_ENVIRONMENT_TYPE', 'staging'); // 声明环境类型:local/development/staging/production
生产环境的正确组合是:WP_DEBUG = true + WP_DEBUG_LOG = true + WP_DEBUG_DISPLAY = false。这样错误只进日志,不显示给访客。
保姆级实操
第一步:修改 wp-config.php
放在 /* 好了!请不要再继续编辑 */ 之前:
// 生产环境推荐:记录但不显示
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);
@ini_set('log_errors', 1);
@ini_set('error_log', dirname(__FILE__) . '/wp-content/debug.log');
如果你想指定日志路径(推荐放到 Web 根目录之外):
define('WP_DEBUG_LOG', '/var/log/wordpress/mimangfei-debug.log');
WordPress 5.1 之后 WP_DEBUG_LOG 支持字符串路径,之前只支持布尔值。
第二步:设置文件权限
touch wp-content/debug.log
chown www-data:www-data wp-content/debug.log
chmod 660 wp-content/debug.log
第三步:阻止外部访问日志
Apache(.htaccess):
<Files debug.log>
Order allow,deny
Deny from all
</Files>
Nginx:
location ~* /debug\.log$ { deny all; }
这一步绝对不能省——debug.log 里全是路径、SQL 和插件名,是攻击者的情报来源。
第四步:复现问题并查看日志
tail -f wp-content/debug.log
典型输出:
[10-Oct-2026 14:02:31 UTC] PHP Fatal error: Uncaught Error: Call to undefined function xyz() in /var/www/site/wp-content/plugins/bad-plugin/bad-plugin.php:42
这条信息直接告诉你:插件 bad-plugin 第 42 行调用了不存在的函数。处理方式就是去后台(或用 wp plugin deactivate bad-plugin --skip-plugins)禁用它。
第五步:日志轮转(防止撑爆磁盘)
sudo vim /etc/logrotate.d/wordpress-debug
/var/www/site/wp-content/debug.log {
weekly
rotate 4
size 20M
compress
missingok
notifempty
create 660 www-data www-data
}
调试结束后记得把 WP_DEBUG 改回 false 并清空日志。
第六步:SAVEQUERIES 定位慢查询(仅临时使用)
define('SAVEQUERIES', true);
然后在代码里输出:
if (current_user_can('administrator') && defined('SAVEQUERIES') && SAVEQUERIES) {
global $wpdb;
echo '<pre>';
foreach ($wpdb->queries as $q) {
printf("%.3fs %s\n", $q[1], $q[0]);
}
echo '</pre>';
}
生产环境不要长期开启 SAVEQUERIES,每条 SQL 都记录会明显增加内存和耗时。日常查慢查询更推荐 Query Monitor 插件。
常见踩坑与失败案例
- 只写
define('WP_DEBUG', true);—— 错误直接显示在页面上,等于把路径暴露给所有人。 - 日志文件 Web 可访问 —— 见过太多站点
https://xxx.com/wp-content/debug.log能直接下载,里面全是敏感信息。 - 案例:某站开启调试后忘记关闭,两个月后
debug.log涨到 8GB,磁盘写满导致数据库崩溃。开启调试必须同时配 logrotate,并且排查完立即关闭。 - 日志写不进去 ——
wp-content属主不是 Web 服务用户,或 SELinux 上下文不对。用ls -la确认属主。 WP_DEBUG_LOG路径版本兼容 —— WordPress 5.1 以下版本传字符串无效,会写进默认位置wp-content/debug.log。- 调试信息出现在 REST API / AJAX 响应里 —— 这会破坏 JSON 结构导致前台功能异常,所以
WP_DEBUG_DISPLAY必须关。
总结
调试的正确姿势是”记而不显”:WP_DEBUG 与 WP_DEBUG_LOG 打开,WP_DEBUG_DISPLAY 关闭,日志禁止外部访问并配轮转。排查完立刻关闭调试、清空日志。这套流程既能拿到完整的错误信息(文件名 + 行号,直接定位到插件),又不会给访客和攻击者递情报。养成”先看日志再猜”的习惯,能省下大量瞎试的时间。
