搜索全站
报错排查 8 分钟阅读

WP_DEBUG 正确用法:开启调试日志定位 WordPress 隐藏错误

WP_DEBUG 不只是"开关",用错了会把路径泄露给访客。本文讲清 WP_DEBUG、WP_DEBUG_LOG、WP_DEBUG_DISPLAY、SAVEQUERIES 四个常量的正确组合,生产环境如何安全地只记录不显示,日志文件的权限与轮转处理,以及如何从日志定位具体插件与代码行。

U
UFO_PF 2017-03-06 · 阅读 8 分钟
WP 报错排查
阅读提示
本文约 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 插件。

常见踩坑与失败案例

  1. 只写 define('WP_DEBUG', true); —— 错误直接显示在页面上,等于把路径暴露给所有人。
  2. 日志文件 Web 可访问 —— 见过太多站点 https://xxx.com/wp-content/debug.log 能直接下载,里面全是敏感信息。
  3. 案例:某站开启调试后忘记关闭,两个月后 debug.log 涨到 8GB,磁盘写满导致数据库崩溃。开启调试必须同时配 logrotate,并且排查完立即关闭。
  4. 日志写不进去 —— wp-content 属主不是 Web 服务用户,或 SELinux 上下文不对。用 ls -la 确认属主。
  5. WP_DEBUG_LOG 路径版本兼容 —— WordPress 5.1 以下版本传字符串无效,会写进默认位置 wp-content/debug.log。
  6. 调试信息出现在 REST API / AJAX 响应里 —— 这会破坏 JSON 结构导致前台功能异常,所以 WP_DEBUG_DISPLAY 必须关。

总结

调试的正确姿势是”记而不显”:WP_DEBUG 与 WP_DEBUG_LOG 打开,WP_DEBUG_DISPLAY 关闭,日志禁止外部访问并配轮转。排查完立刻关闭调试、清空日志。这套流程既能拿到完整的错误信息(文件名 + 行号,直接定位到插件),又不会给访客和攻击者递情报。养成”先看日志再猜”的习惯,能省下大量瞎试的时间。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。