测试站(staging)要解决的不是“再装一个 WordPress”,而是让生产数据能安全地流到测试站、测试结果能可控地回到生产。最小可用做法是:独立数据库 + 独立域名 + 禁搜索引擎 + 拦截邮件;生产到测试可以整表覆盖内容表,用户表、wp_options、订单表和任务表不要整表同步。
下面按“建站 → 表分类 → 生产到测试 → 测试到生产 → 检查清单”给一套能照着做的流程。示例表前缀是 wp_,实际前缀按你的 wp-config.php 替换。
方向定错,后面所有命令都会变成事故。
用子域名、独立数据库、独立目录,代码可以和生产同一套,靠 wp-config.php 区分环境。
# 生产库只读导出;凭据放 ~/.my.cnf.prod,避免密码进 history
mysqldump --defaults-extra-file=$HOME/.my.cnf.prod --single-transaction --quick --default-character-set=utf8mb4 production_wp > prod-$(date +%F).sql
mysql -h staging-db -u staging_user -p staging_wp < prod-$(date +%F).sqlwp-config.php 里至少加:
define('WP_ENVIRONMENT_TYPE', 'staging');
define('DISALLOW_FILE_EDIT', true);
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);改站点地址不要直接 UPDATE wp_options,序列化数据会被改坏。用 WP-CLI:
wp option update home 'https://staging.example.com'
wp option update siteurl 'https://staging.example.com'
wp search-replace 'https://example.com' 'https://staging.example.com' --all-tables-with-prefix --precise --dry-run
wp search-replace 'https://example.com' 'https://staging.example.com' --all-tables-with-prefix --precise --skip-columns=guid
wp option update blog_public 0先跑 --dry-run 看会改多少行,再执行。--skip-columns=guid 保留原来的 GUID,避免 feed 里旧链接被改。
再加一层访问控制,别让测试站被搜索引擎抓到:
server {
server_name staging.example.com;
auth_basic "staging";
auth_basic_user_file /etc/nginx/.htpasswd;
add_header X-Robots-Tag "noindex, nofollow, noarchive" always;
# root、fastcgi 等配置与生产保持一致
}Basic Auth 会挡住第三方回调(支付、webhook)。测试站本来就不该接真实回调,这一点要提前确认。
邮件也要拦掉。放一个 mu-plugin:
<?php
// wp-content/mu-plugins/staging-mail-guard.php
add_filter('pre_wp_mail', function ($return, $atts) {
$to = is_array($atts['to']) ? implode(',', $atts['to']) : $atts['to'];
error_log('[staging mail] to=' . $to . ' subject=' . $atts['subject']);
return true;
}, 10, 2);返回 true 会短路 wp_mail(),邮件只进日志,不真发。
整表覆盖的前提是:测试站只当生产镜像用,测试站上新建的内容可以被丢弃。
表 | 处理 | 说明 |
|---|---|---|
| 可整表覆盖 | 文章、页面、产品、菜单项、附件记录都在这里;会覆盖测试站新建内容 |
| 随 | 封面、页面构建器数据、产品属性;不要只导一半 |
| 可整表覆盖 | 分类、标签、商品分类;和 posts 一起导 |
| 可整表覆盖 | 测试站不需要保留测试评论时可覆盖 |
| 有就覆盖 | 老站友链表 |
表 | 处理 | 原因 |
|---|---|---|
| 不能整表同步 | 用户、角色、会话、应用密码;覆盖会把生产管理员换成测试账号 |
| 不能整表同步 | 站点地址、插件开关、密钥、cron、transient、许可证混在一起,只能按白名单逐项处理 |
| 不能 | 多站点网络表 |
订单表( | 不能 | 测试订单不能回流生产;生产订单也不该出现在测试站 |
任务队列表( | 不能 | 覆盖会让生产任务丢失或重复执行 |
会话、API 密钥、支付令牌表 | 不能 | 测试站用测试凭据,生产密钥不进测试站 |
表单提交、会员、统计、安全/备份插件私有表 | 不能 | 各插件结构不同,用插件自己的导出工具处理 |
产品数据要单独说:只同步商品时,不要直接整表覆盖 wp_posts,否则页面、菜单、订单记录会一起变。用 WooCommerce 自带导入导出或按 SKU 更新;产品属性、变体、库存 lookup 表要一起处理。
多站点注意:wp_2_posts 这类子站表也要按同一规则判断,--all-tables-with-prefix 只处理当前前缀。
1)先备份生产,并在测试库恢复一次,确认备份可用:
wp db export /backup/prod-$(date +%F).sql
tar -czf /backup/uploads-$(date +%F).tar.gz wp-content/uploads2)只导出白名单内容表:
TABLES='wp_posts wp_postmeta wp_terms wp_term_taxonomy wp_term_relationships wp_termmeta wp_comments wp_commentmeta'
mysqldump --defaults-extra-file=$HOME/.my.cnf.prod --single-transaction --quick --default-character-set=utf8mb4 production_wp $TABLES > content-$(date +%F).sql3)导入前先备份测试站同表:
mysqldump --defaults-extra-file=$HOME/.my.cnf.staging --single-transaction --quick staging_wp $TABLES > staging-content-$(date +%F).sql
mysql --defaults-extra-file=$HOME/.my.cnf.staging staging_wp < content-$(date +%F).sql4)跑替换、清缓存:
wp search-replace 'https://example.com' 'https://staging.example.com' --all-tables-with-prefix --precise --dry-run
wp search-replace 'https://example.com' 'https://staging.example.com' --all-tables-with-prefix --precise --skip-columns=guid
wp cache flush
wp rewrite flush5)媒体文件只从生产往测试同步:
rsync -avz --delete production:/var/www/example/wp-content/uploads/ /var/www/staging/wp-content/uploads/如果测试站要保留自己上传的测试图片,去掉 --delete,或在测试站单独用目录排除。
6)打开测试站检查:首页、登录、搜索、表单、404、feed、sitemap。
代码用 Git tag 或 rsync 推主题/插件目录,排除上传、缓存、日志:
rsync -avzn --delete --exclude 'uploads/' --exclude 'cache/' --exclude '*.log' ./wp-content/themes/acme/ user@prod:/var/www/example/wp-content/themes/acme/先加 -n 看 dry-run 结果,确认删除列表里没有生产独有文件,再去掉 -n 执行。
内容变更用 WXR 导出导入,不要整表推 wp_posts:
wp export --dir=/tmp --filename_format=staging-content.xml
wp import /tmp/staging-content.xml --authors=createWXR 导入会创建新 ID,适合新增页面/文章;更新已有页面要按 ID 对照,人工确认后再操作。
配置项手工对照,不要导 wp_options。至少核对:home、siteurl、active_plugins、permalink_structure、blog_public、支付网关模式(测试/生产)、SMTP、缓存开关、cron 事件、许可证绑定的域名。
上线顺序建议:备份 → 维护模式 → 推代码 → 导入内容 → 清缓存和重写规则 → 关维护 → 检查。
wp maintenance-mode activate
wp cache flush
wp rewrite flush
wp maintenance-mode deactivate回滚时保留数据库备份和上一个代码 tag。直接恢复数据库会覆盖上线后产生的新数据,恢复前先把当前库再导一份。
wp_users、wp_usermeta、wp_options、订单表、任务表blog_public=0,有 Basic Auth 或 IP 白名单wp option get home 是测试域名wp plugin list、wp theme list 没有意外启用或停用wp cron event list 没有重复任务search-replace。wp_posts 不导 wp_postmeta,页面构建器内容丢失。wp_options 整表推生产,站点地址、插件开关、cron 一起变。rsync --delete 方向反了,删掉生产图片。需要把测试通过的站点交付到客户自己的主机、并清掉示例内容,可参考 AumCreate 的代部署说明:https://aumcreate.com/setup?utm_source=tencent&utm_medium=content&utm_campaign=tencent-wp-staging-sync-safe-tables
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。