本文约 3,918 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:一句话的提示页,站点对所有人不可用
WordPress 5.2 之后,致命错误不再表现为白屏,而是一句「此站点遇到了技术困难」(英文为 There has been a critical error on this website.)。和旧版白屏相比,这算是进步——至少你知道出事了。但它的麻烦在于:这个页面对所有访客显示,包括管理员,后台也进不去,整站等于下线。
这类事故九成发生在启用新主题或更新主题之后,其次是插件冲突。此时最要紧的不是查原因,而是在几分钟内恢复访问。WordPress 为此准备了「恢复模式」:出错时会给管理员邮箱发一封带特殊登录链接的邮件,用该链接进入后台可以暂停出错的主题或插件。但这条链路依赖邮件能发出去,而大量站点并未配置发信,等于摆设。本文给出三条应急通道(恢复模式、数据库、文件系统),按可用性依次尝试,并说明事后如何定位根因、如何预防。
原理分析:错误发生时 WordPress 做了什么
从 WP 5.2 起,核心引入了 WP_Recovery_Mode 与 WP_Fatal_Error_Handler。致命错误发生时:
- 处理器捕获错误,向管理员邮箱发送一封含
recovery_mode登录链接的邮件(链接带一次性 token); - 前台显示技术困难提示页,HTTP 状态码为 500;
- 管理员通过链接登录后,进入「暂停」状态——出错的主题或插件被标记为暂停,站点恢复可访问,后台顶部会有醒目提示。
暂停状态记录在 wp_options 里(wpseo… 不,是 recovery_mode_* 相关的 transient/option),有效期约一天,过期后如果错误仍在,会再次进入错误状态。
如果这个机制不可用(邮件不通、链接过期、多管理员不知道该用谁的邮箱),就需要手动干预。手动干预的核心是把当前主题换回一个确定可用的默认主题,而主题信息存在两张表里:wp_options 的 template(父主题目录名)与 stylesheet(子主题目录名)。用子主题时二者不同,只改一个会造成半成品状态。
| 通道 | 适用场景 | 速度 | 风险 |
|---|---|---|---|
| 恢复模式链接 | 能收到邮件 | 最快 | 依赖邮件,约一天后失效 |
| 数据库切换 | 有 phpMyAdmin / SSH | 快 | 需知道默认主题目录名 |
| 文件系统改名 | 有 FTP | 快 | 需知道出错主题目录名 |
| WP-CLI | 有 SSH | 最快 | 需服务器装了 WP-CLI |
相关白屏(前台空白但后台正常)是另一类表现,处理方式不同,见 主题启用后前台空白排查。
保姆级实操
- 先找恢复模式邮件:检查站点管理员邮箱(收件箱与垃圾箱),邮件标题通常是「[站点名] 您的站点遇到了技术困难」。点链接登录,按提示暂停出错主题。
- 没有邮件就走数据库:登录 phpMyAdmin,打开
wp_options表,搜索option_name为template和stylesheet的两行,把值改成默认主题目录名(如twentytwentyfour),current_theme也一并改。 - 可用 WP-CLI 就更快:有 SSH 权限时一条命令切换主题,并且它会自动处理相关选项。
- 文件系统兜底:FTP 把出错主题目录改名,WordPress 找不到当前主题会自动回退到
WP_DEFAULT_THEME指定的默认主题。 - 定位根因:访问恢复后,开启
WP_DEBUG_LOG复现一次(切回该主题),读wp-content/debug.log里的PHP Fatal error行,按文件路径判断是主题还是插件。 - 预防:给站点配好 SMTP 发信;重要站点准备 staging 环境,先在 staging 上启用新主题;定期备份
wp_options与主题目录。
-- 1. 先查当前值,记下来以便回滚
SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('template','stylesheet','current_theme');
-- 2. 切回默认主题(三行一起改,子主题场景尤其重要)
UPDATE wp_options SET option_value = 'twentytwentyfour' WHERE option_name = 'template';
UPDATE wp_options SET option_value = 'twentytwentyfour' WHERE option_name = 'stylesheet';
UPDATE wp_options SET option_value = 'Twenty Twenty-Four' WHERE option_name = 'current_theme';
-- 3. 清理可能残留的恢复模式标记
DELETE FROM wp_options WHERE option_name LIKE 'recovery_mode_%';
# WP-CLI:一条命令切换主题(推荐,自动处理相关选项)
wp theme list
wp theme activate twentytwentyfour
# 文件系统兜底:改名后 WordPress 自动回退默认主题
mv wp-content/themes/broken-theme wp-content/themes/broken-theme.paused
# 复现并抓取日志
tail -n 40 wp-content/debug.log | grep -i "fatal"
<?php
// wp-content/fatal-error-handler.php:自定义致命错误处理器(drop-in,WP 5.2+)
class Mimangfei_Fatal_Error_Handler extends WP_Fatal_Error_Handler {
protected function display_error_template( $error, $handled ) {
if ( defined( 'WP_CLI' ) && WP_CLI ) {
return;
}
// 把错误写入日志,便于事后查(不要在这里输出敏感路径给访客)
error_log( sprintf(
'[Mimangfei] %s in %s on line %d',
$error['message'],
$error['file'],
$error['line']
) );
parent::display_error_template( $error, $handled );
}
}
return new Mimangfei_Fatal_Error_Handler();
<?php
// wp-config.php:明确指定默认主题,改名兜底时才知道会回退到哪
define( 'WP_DEFAULT_THEME', 'twentytwentyfour' );
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
常见踩坑
- 只改
template不改stylesheet:子主题场景下前台会加载一半父主题、一半子主题,表现为样式错乱而非白屏,反而更难排查。 - 改完数据库没清缓存:对象缓存里仍有旧的主题配置,前台看起来没变化。改完执行
wp cache flush。 - 恢复模式链接过期才想起来用:token 有时效,且一天后暂停状态失效。收到邮件应当先处理根因,而不是依赖暂停。
- 把
WP_DEBUG_DISPLAY设成 true 应急:全站访客看到完整堆栈与服务器路径,属信息泄露。只开 log。 - 删掉了默认主题:很多主机为了省空间删掉自带主题,出事时无主题可回退。至少保留一个默认主题。
- 案例:一个会员站在启用新主题后整站 500,管理员邮箱因为没配 SMTP 从未收到恢复模式邮件。运维情急之下恢复了昨天的全站备份,结果丢掉了当天几十条订单数据。事后复盘发现,只需在 phpMyAdmin 里改两行
wp_options就能在两分钟内恢复访问,数据一行不丢。应急时最忌讳的第一个动作就是「回滚备份」,它应当是最后手段。 - 误以为是插件冲突而逐个停用:主题导致的致命错误停用插件不会恢复,白白浪费时间。先看日志里的文件路径。
总结
应急的优先级是:恢复模式链接 → WP-CLI 切换 → 数据库改 template/stylesheet → 文件系统改名。目标只有一个:先让站点可访问,再谈排查。定位根因必须回到 debug.log 里的 PHP Fatal error 行,看文件路径判断责任方。日常要做三件预防:配好 SMTP 发信、保留至少一个默认主题、在 staging 上验证新主题。发布流程与缓存注意事项可参考 WordPress 主题更新规范。
