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

WordPress 维护模式设置:临时关闭站点与正确返回 503

站点卡在"正在执行定期维护"、或者要在改版期间临时关闭前台——都需要维护模式。本文讲清 .maintenance 文件的机制、正确返回 503 的插件与代码方案、允许管理员正常访问的配置,以及卡死时的排查命令。

U
UFO_PF 2017-06-13 · 阅读 13 分钟
Wo 报错排查
阅读提示
本文约 5,200 字,预计阅读 13 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:两种完全不同的”维护模式”

WordPress 里”维护模式”其实指两件事,处理方式完全不同:

  1. 自动维护模式:WordPress 在自动更新核心/插件/主题时,会自动进入维护模式,如果更新中断(超时、内存耗尽),就会卡在”正在执行定期维护,请一分钟后回来”这个页面,站点前台也打不开。
  2. 主动维护模式:你要改版、迁移、做重大调整,希望前台临时显示一个”维护中”页面,但不能影响 SEO。

第二种如果处理不当(比如直接关站点或者返回 200 的空白页),搜索引擎会把维护页当正式内容收录,收录全掉。所以必须返回 503。

原理分析:.maintenance 文件与 503 状态码

自动维护模式的机制

WordPress 更新时在网站根目录创建一个 .maintenance 文件,内容是一个 PHP 序列化数组:

<?php $upgrading = 1234567890; ?>

(1234567890 是时间戳)

wp-settings.php 加载时会检查:

if ( file_exists( ABSPATH . '.maintenance' ) ) {
    // 显示"正在执行定期维护"
}

更新完成后 WordPress 会自动删除这个文件。但如果更新过程被中断(PHP 超时、内存不足、浏览器关掉),文件残留,站点就一直卡住。

修复方法极其简单:删掉这个文件。

为什么必须返回 503

HTTP 状态码语义:

  • 200 OK:正常页面 → 搜索引擎会抓取并收录维护页内容;
  • 503 Service Unavailable:服务暂时不可用 → 搜索引擎知道这是临时状态,会稍后重试,不会用维护页替换原有收录;
  • 503 + Retry-After 头:告诉爬虫多久后重试,这是最规范的做法。

Google 官方明确建议:计划内停机用 503 + Retry-After,不要用 302 跳转到首页。

保姆级实操

场景一:站点卡在”正在执行定期维护”

# 进站点根目录
cd /var/www/site

# 查看文件
ls -la .maintenance

# 删除
rm -f .maintenance

# 同时清掉升级缓存目录(更新中断会残留)
rm -rf wp-content/upgrade/*
# 也可以看文件里的时间戳
cat .maintenance
# <?php $upgrading = 1739123456; ?>

删除后立刻刷新,站点应恢复正常。

如果删除后又出现:说明有进程还在跑更新。检查:

ps aux | grep -i "wp\|php" | head

或者重跑一次更新让它正常完成:

wp core update --force
wp plugin update --all

场景二:主动设置维护页(推荐插件)

装插件 WP Maintenance Mode 或 LightStart(原 WP Maintenance Mode):

关键设置:

  • 状态:启用;
  • HTTP 503:必须开启(有的插件叫 “Bypass for Search Engines” 或 “503 header”);
  • 允许访问的角色:勾选 administrator(你自己能看到正常站点);
  • 结束时间:填维护结束时间,插件会自动恢复。

LightStart 的设置路径:后台左侧 “LightStart” → Settings → General → 勾选 “Enable maintenance mode”,然后在 “Advanced” 里确认 503 状态。

场景三:代码方式(不装插件)

子主题或功能插件里加:

add_action( 'template_redirect', 'mmf_maintenance_mode' );
function mmf_maintenance_mode() {
    // 管理员不受影响
    if ( current_user_can( 'manage_options' ) ) {
        return;
    }
    // 登录页、后台、REST API 不受影响
    if ( is_admin() || wp_doing_ajax() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
        return;
    }
    // 允许访问维护页本身
    if ( isset( $_GET['mmf_preview'] ) ) {
        return;
    }

    // 关键:返回 503
    status_header( 503 );
    header( 'Retry-After: 3600' );   // 1 小时后重试
    header( 'Content-Type: text/html; charset=utf-8' );
    nocache_headers();

    include get_stylesheet_directory() . '/maintenance.php';
    exit;
}

maintenance.php(放在子主题目录):

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="robots" content="noindex,nofollow">
    <title>站点维护中 - <?php bloginfo( 'name' ); ?></title>
    <style>
        body { font-family: -apple-system, "Microsoft YaHei", sans-serif;
               display: flex; align-items: center; justify-content: center;
               min-height: 100vh; margin: 0; background: #f5f5f5; color: #333; }
        .box { text-align: center; max-width: 480px; padding: 40px; }
        h1 { font-size: 24px; margin-bottom: 12px; }
        p  { color: #666; line-height: 1.8; }
    </style>
</head>
<body>
    <div class="box">
        <h1>站点正在维护升级</h1>
        <p>我们正在进行系统维护,预计 2 小时后恢复。<br>感谢您的耐心等待。</p>
        <p style="margin-top:24px;font-size:14px;color:#999;">
            紧急联系:admin@example.com
        </p>
    </div>
</body>
</html>

场景四:Nginx 层维护模式(最省资源)

站点完全不进 PHP,适合大流量站或者 PHP 挂了的情况:

server {
    # 维护开关:取消注释即开启
    # return 503;

    error_page 503 @maintenance;
    location @maintenance {
        root /var/www/maintenance;
        rewrite ^(.*)$ /maintenance.html break;
        add_header Retry-After 3600 always;
        add_header Cache-Control "no-store, no-cache, must-revalidate" always;
    }
}

需要建 /var/www/maintenance/maintenance.html。

放行管理员 IP:

# 用 geo 模块
geo $maintenance {
    default 1;
    203.0.113.10 0;    # 你的 IP 放行
}

server {
    if ($maintenance) {
        return 503;
    }
    ...
}

场景五:验证 503 是否正确返回

curl -I https://example.com/
# 应看到:HTTP/2 503
# Retry-After: 3600

注意:用无痕窗口测,因为管理员 cookie 会绕过维护模式。

Google Search Console 也可以用”网址检查”工具看抓取结果,应显示 503 而不是 200。

场景六:结束维护

  • 插件:后台点关闭;
  • 代码:注释掉 add_action 那行;
  • Nginx:注释掉 return 503 然后 nginx -s reload;
  • 别忘了清缓存(页面缓存、CDN 缓存),否则用户还看到维护页:
wp cache flush
# CDN 刷新缓存

常见踩坑与失败案例

  1. 案例一:某站改版三天,维护页返回 200,Google 把”维护中”当首页收录,标题和描述全变成维护提示,恢复后花了两个月才恢复排名。必须 503。
  2. 案例二:维护模式没放行管理员,自己也被拦在外面,只能进服务器删代码。代码方案里 current_user_can('manage_options') 判断不能省。
  3. 缓存导致维护页下不掉:关了维护模式但 CDN 还缓存着 503。必须同时清 CDN 缓存和页面缓存。
  4. 案例三:自动更新卡住后,站长删了 .maintenance,但 wp-content/upgrade/ 目录里的残留文件导致下次更新仍失败。两个都要清。
  5. 维护模式挡掉了 wp-cron 和 REST API:代码方案里已经放行 wp_doing_ajax() 和 REST_REQUEST,但 Nginx 层的 return 503 会全挡。用 Nginx 方案时要给 /wp-cron.php 和 /wp-json/ 加例外。
  6. Retry-After 时间写太长:设 86400(一天)会让搜索引擎一天后才来,恢复慢。建议 3600(1 小时)以内。
  7. 移动端维护页样式错乱:别忘了 <meta name="viewport">。

总结

维护模式的两件事要分开处理:卡在”正在执行定期维护”→ 直接删根目录的 .maintenance 文件(顺便清 wp-content/upgrade/);主动临时关闭站点 → 必须返回 503 + Retry-After 头,这是保住收录的关键(返回 200 会让搜索引擎把维护页当正式内容收录)。实现上三选一:插件(LightStart,要勾 503)、代码(template_redirect + status_header(503))、Nginx(return 503 + error_page,最省资源)。无论哪种,必须放行管理员(代码里判断 manage_options,Nginx 里用 geo 放行 IP),结束维护后必须清 CDN 和页面缓存。

U
UFO_PF作者

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

留下你的想法

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