WordPress 备份与迁移:频率怎么定、到底要备什么、怎么验证备份真的能恢复

简介: 备份文件躺在那里,不等于你有一份可用的备份。真正决定成败的是三件事:多久备一次(RPO)、多久能恢复回来(RTO)、上一次成功演练是哪天。这篇把这三件事落成可执行的脚本和检查清单。

备份文件躺在那里,不等于你有一份可用的备份。真正决定成败的是三件事:多久备一次(RPO)、多久能恢复回来(RTO)、上一次成功演练是哪天。这篇把这三件事落成可执行的脚本和检查清单。

一、先把两个数字定下来

  • RPO(能丢多少数据):出事后你最多能接受丢失多长时间的内容。RPO=24h 就是每天至少备一次数据库。
  • RTO(多久能恢复):从发现故障到站点重新对外服务,你能接受多长时间。RTO 直接决定恢复演练要跑多快、备份要不要放在能快速拉取的地方。

定完这两个数字,频率就是算出来的,不是拍脑袋。

二、备份频率对照表

站点类型 数据库 文件(wp-content) 保留 恢复演练
企业展示站,偶尔改内容 每日 1 次 每周 1 次 + 每次上线前 30 天 每季度 1 次
有询盘表单的站 每 6 小时 每日 60 天 每月 1 次
有在线交易的站 每小时 每日 90 天 每月 + 大促前
内容更新频繁的站 每日 每日 30 天 每季度 1 次

再加一条硬规则:任何一次改主题、改插件、改数据库、换主机之前,手动做一次全量备份并立刻验证。变更前的那份备份是唯一一份「确定是好的」状态。

保留策略建议按「日备留 14 份 + 周备留 8 份 + 月备留 12 份」,比单纯按天数滚动更省空间也更好找。

三、备什么:清单

必须备:

  1. 数据库全量(含自定义表,很多插件会自己建表)
  2. wp-content/uploads(媒体库,最容易漏)
  3. wp-content/themes、wp-content/plugins、wp-content/mu-plugins
  4. wp-config.php(含数据库凭据和盐值)
  5. Web 服务器配置:Nginx/Apache 的站点配置文件
  6. 系统 crontab 里跟 WordPress 相关的条目(crontab -l)
  7. PHP 版本、MySQL 版本、已装扩展的清单(php -v、php -m、mysql --version)

不用备(占了体积还会拖慢恢复):

  • wp-content/cache、各类缓存目录、日志文件
  • 备份插件自己生成的备份目录(会自我嵌套)
  • node_modules、.git(除非你依赖它)

备份之外还要单独记一笔:

  • DNS 托管在哪、域名注册商账号
  • CDN 配置、SSL 证书申请方式
  • 表单/邮件/SMTP/支付这些第三方服务的凭据和回调地址

这些不随网站文件走,恢复时却必须一起就位。

四、备份脚本

用 WP-CLI 做数据库导出(底层是 mysqldump),tar 做文件归档。放到 /usr/local/bin/wp-backup.sh:

#!/usr/bin/env bash
set -euo pipefail

SITE_PATH=/var/www/html
BACKUP_DIR=/var/backups/wp
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
KEEP_DAYS=30

mkdir -p "$BACKUP_DIR"

# 1) 数据库
wp db export "$BACKUP_DIR/db-$STAMP.sql" --path="$SITE_PATH"
gzip -9 "$BACKUP_DIR/db-$STAMP.sql"

# 2) 文件(排除缓存和旧备份目录)
tar -czf "$BACKUP_DIR/files-$STAMP.tar.gz" \
  --exclude='./wp-content/cache' \
  --exclude='./wp-content/*cache*' \
  --exclude='./wp-content/*backup*' \
  --exclude='./wp-content/*.log' \
  -C "$SITE_PATH" ./wp-content ./wp-config.php

# 3) 完整性校验值
sha256sum "$BACKUP_DIR/db-$STAMP.sql.gz" "$BACKUP_DIR/files-$STAMP.tar.gz" \
  > "$BACKUP_DIR/sha-$STAMP.txt"

# 4) 清理过期备份
find "$BACKUP_DIR" -maxdepth 1 -type f -name '*.gz' -mtime +$KEEP_DAYS -delete
find "$BACKUP_DIR" -maxdepth 1 -type f -name 'sha-*.txt' -mtime +$KEEP_DAYS -delete

echo "backup ok: $STAMP"

注意事项:

  • wp db export 需要 WP-CLI 有权限读取 wp-config.php,用站点属主账号跑,别用 root 跑出 root 属主的文件。
  • 数据库大的话,导出期间会有较长的事务,建议在低峰期跑,脚本里加 --single-transaction 需要自己换成 mysqldump 调用。
  • 备份文件不要和站点放同一块盘。至少同步一份到对象存储或另一台机器,用 rclone 或云厂商 CLI 都行。
  • 备份文件权限设 600,里面是完整数据库,含用户表和表单提交内容。

挂到系统 cron:

0 3 * * * /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1

跑完检查日志里有没有 backup ok,没有就当失败处理。

五、验证:分四层,别跳步

只 ls -lh 看一眼文件存在,是七成事故的来源。恢复验证至少走四层。

第 1 层:文件完整性

cd /var/backups/wp && sha256sum -c sha-20261027T030000Z.txt
gzip -t db-20261027T030000Z.sql.gz && echo "sql gz ok"
tar -tzf files-20261027T030000Z.tar.gz > /dev/null && echo "tar ok"

第 2 层:能导入

不要导进生产库。 建一个临时库:

DB=wp_restore_test
mysql -e "DROP DATABASE IF EXISTS $DB; CREATE DATABASE $DB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
gunzip -c /var/backups/wp/db-20261027T030000Z.sql.gz | mysql "$DB"
mysql -e "SELECT COUNT(*) FROM $DB.wp_posts; SELECT COUNT(*) FROM $DB.wp_options;"

表前缀不是 wp_ 的话记得改。行数和生产库比一下,同一个数量级就正常。

第 3 层:站能跑起来

把文件解到临时目录,改 wp-config.php 指向临时库,用 PHP 内置服务器起一下:

RESTORE=/tmp/wprestore
rm -rf "$RESTORE" && mkdir -p "$RESTORE"
tar -xzf /var/backups/wp/files-20261027T030000Z.tar.gz -C "$RESTORE"
wp config set DB_NAME wp_restore_test --path="$RESTORE"
wp option get home --path="$RESTORE"
wp server --path="$RESTORE" --host=127.0.0.1 --port=8080 &
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/

首页返回 200 只是及格线,还要抽查:

wp post list --path="$RESTORE" --post_type=page --post_status=publish --fields=ID,post_title --format=table | head -20
wp plugin list --path="$RESTORE"
find "$RESTORE/wp-content/uploads" -type f | wc -l
find /var/www/html/wp-content/uploads -type f | wc -l

页面列表要能看到你认识的那些页面,插件列表不能有报错,两个 uploads 文件数应该一致(差异过大说明文件备份漏了)。

第 4 层:功能抽样

这一层最容易被跳过,也最容易在真出事时暴露:

  • 打开一个有图片的内页,确认图片不是坏图
  • 提交一次测试询盘/测试订单,看邮件能不能发出去
  • 打开后台登录页,能登录
  • 有表单、支付、搜索的,各点一次

wp server 只适合快速验证,固定链接、重写规则和部分插件在它下面可能不工作。要更接近真实环境,就在一台临时机器上按生产环境装一遍 Nginx + PHP,把域名用本机 hosts 指过去再测。

六、迁移:跟恢复的区别只在换地址

迁移本质上是「恢复到另一台机器 + 换域名」。多出来的风险全在域名替换上。

顺序:

  1. 提前 24–48 小时把 DNS TTL 降到 300 秒
  2. 源站全量备份并做一次第 3 层验证
  3. 新机装好同版本 PHP、MySQL 和扩展,建库建用户
  4. 导入数据库、解压文件、改 wp-config.php 的库连接
  5. 替换地址
  6. 本机 hosts 指向新 IP 测试
  7. 切 DNS
  8. 收尾检查

替换地址用 WP-CLI,不要用 SQL 直接 UPDATE:

# 先干跑,看会改多少处
wp search-replace 'https://old.example.com' 'https://new.example.com' \
  --all-tables --precise --recurse-objects --skip-columns=guid --dry-run --path=/var/www/html

# 确认后真跑
wp search-replace 'https://old.example.com' 'https://new.example.com' \
  --all-tables --precise --recurse-objects --skip-columns=guid --path=/var/www/html

为什么不能直接 SQL 替换:WordPress 的很多选项和页面内容里存的是序列化数组,数组里带长度前缀,SQL 替换只改字符串不改长度,整个值会反序列化失败,表现为某些小工具、主题设置、页面构建内容直接空白。--precise 会走反序列化再重写,慢但正确。--skip-columns=guid 是保住文章 GUID,避免订阅源重复推送。

迁移收尾清单:

  • [ ] wp option get siteurl 和 home 都是新域名
  • [ ] wp rewrite flush --hard 刷新固定链接
  • [ ] 后台 → 设置 → 固定链接重新保存一次(等价于上一条)
  • [ ] 清空对象缓存(Redis/Memcached),旧键会带着旧域名
  • [ ] 检查 wp-config.php 里的盐值和数据库凭据
  • [ ] wp cron event list 确认定时任务在,再 wp cron event run --due-now 跑一遍
  • [ ] 文件属主改成 Web 用户(如 chown -R www-data:www-data)
  • [ ] SSL 证书在新机签好,curl -I https://new.example.com 看 200
  • [ ] 邮件/SMTP、支付回调、第三方 API 的域名白名单同步更新
  • [ ] 重新生成 sitemap,提交给搜索引擎
  • [ ] 旧站保留 301 跳转至少一个 TTL 周期

最后一条别忘了:搜索 sitemap、结构化数据、canonical 这些是跟着域名走的,换完域名都要重新生成一遍才能被正确读。我们有个免费插件 AumViso 专门做这块(sitemap、meta、schema、内链),迁移完想省事可以看:https://aumcreate.com/plugins/aumviso?utm_source=aliyun&utm_medium=content&utm_campaign=aliyun-wp-backup-restore-test-plan

七、几个反复踩的坑

  1. 只备数据库。恢复后站是空的,图片全没了。附件目录必须单独备。
  2. 备份文件放在 wp-content 里。攻击者拿到的就是全站数据,而且下次备份会把自己打包进去。
  3. 从没演练过。备份脚本绿灯跑了两年,第一次真恢复才发现数据库用户没权限导入。
  4. 临时库和生产库同名。恢复演练永远用独立库名和独立目录。
  5. 忽略版本差异。备份是 PHP 7.4 的站,恢复到 PHP 8.3 的机器上,老插件可能直接报错。备份清单里记版本就是这个用。
  6. cron 没迁。站看着正常,但定时发布、清理任务、自动对账全部停摆,几周后才被发现。

八、演练记录怎么留

每次演练记一行,比任何文档都有用:

日期 备份文件 恢复耗时 第 1–4 层 发现的问题 处理
2026-10-27 db/files-20261027T030000Z 18 分钟 全通过 uploads 少 12 个文件 已改为每周全量

演练频率跟站点重要性挂钩:有交易的站每月一次,纯展示站每季度一次,但每次大改版、换主机、换插件之前必须加一次。

一句话收尾:备份的价值只在恢复成功那一刻成立,其余时间它只是一堆文件。

相关文章
|
云安全 安全 网络安全
|
5天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
1920 1
|
11天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
1855 38
|
8天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1196 3
|
5天前
|
安全 应用服务中间件 Go
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
PHP2Shell 双 RCE 已遭在野利用:WordPress、Drupal 全在射程内,nginx 其实另有洞。拆成因与修复顺序
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
|
12天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
1774 0
|
12天前
|
安全 Linux 芯片
【万字长文】Ollama下载、安装、配置、使用保姆级教程(2026最新图解)
Ollama 是一款免费开源的本地大模型运行工具,支持 DeepSeek、Qwen 等主流模型,一条命令即可下载运行。2026 最新版 v0.35.1 官方安装包(1.47GB)已提供国内直连下载,纯本地、离线可用、无广告、无隐私泄露风险。
1142 2
|
16天前
|
存储 人工智能 安全
千问办公官网入口网页版登录:qwenwork.cn 注册送2000积分、登录送100积分
阿里云千问办公(QwenWork)是AI智能工作平台,支持一句话生成PPT、表格、网页、视频及数据分析。个人免费版送2000积分+每日登录赠100分,含1GB存储、5个发布页;企业版198元/席/月起。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
|
4天前
|
安全 程序员 应用服务中间件
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚
507 0

热门文章

最新文章