ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

WordPress备份方法:用TaoToken统一Key打通phpMyAdmin与MySQL导出流程

WordPress备份方法:用TaoToken统一Key打通phpMyAdmin与MySQL导出流程 1. 为什么 WordPress 备份总在“最后一公里”翻车WordPress 备份这件事说穿了就两条主线一条是数据库一条是文件。数据库里装着文章、评论、用户、设置文件里装着主题、插件、上传的图片。很多人备份失败不是不会点 phpMyAdmin 的导出按钮而是两条线各做各的脚本散落在不同机器上凭证到处复制时间一长自己都忘了哪份备份是最新的。我见过太多站点在升级插件前随手导了个 SQL结果文件没拉主题一崩数据库回滚了但wp-content还是坏的。也见过反过来FTP 拉了一堆文件数据库却是三个月前的评论全丢。真正能救命的备份是数据库和文件在同一时间点、同一套凭证管理下完成的双份留存。这篇就聚焦这个落地场景在 phpMyAdmin 与 MySQL 环境下把数据库导出和 FTP 文件拉取两条线跑通并且用 TaoToken 的统一 Key 把备份脚本调用的凭证集中管起来。TaoToken 在这里的角色不是替代 phpMyAdmin也不是替代 MySQL而是给自动化备份脚本提供一个统一的 API 通道和 Key 管理入口让凭证不再散落在各个.sh、.py、.env里。适合谁看自己维护 WordPress 站点的站长、需要定期做站点留存的运维、以及想把备份流程脚本化但不想把密码写死在代码里的人。下面从环境准备开始一步步给出可复制的配置和一次完整的备份验证动作。2. TaoToken 前置统一 Key 与 API 通道准备在动手写备份脚本之前先把凭证管理这块理清楚。传统做法是把数据库密码、FTP 密码直接写进脚本或者塞进.env文件。问题是备份脚本往往不止一个一个导数据库一个拉文件可能还有一个上传到对象存储。每个脚本都要读一遍密码改密码时到处找。TaoToken 提供的是统一 Key 和 API 通道你可以把它理解成一个集中管理调用凭证的中间层。备份脚本不再直接持有数据库或 FTP 的明文密码而是通过统一 Key 去请求所需的配置。这样即使脚本被复制到另一台机器泄露的也只是 Key而不是你的数据库密码。你需要先拿到一个可用的 Key。访问控制台创建https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite创建后你会得到一串 Key形如sk-xxxxxxxx。这个 Key 就是后面config.toml和settings.json里要填的东西。注意Key 只显示一次创建后立刻保存到密码管理器里。如果你还没决定用哪种接入方式可以先看接入文档确认 API 通道的调用格式https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteAPI 的基础地址是https://taotoken.net/api注意这个地址不带任何查询参数是纯 API 端点。控制台入口在这里https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite前置准备就三件事注册并创建 Key、确认 API 基础地址、把 Key 存好。接下来进入配置环节。3. 可复制配置config.toml 与 settings.json 骨架备份脚本要跑起来需要两类配置一类是 TaoToken 的接入信息一类是备份目标的信息数据库、FTP、本地路径。我习惯把前者放在config.toml后者放在settings.json这样职责清晰改备份目标时不用动接入配置。3.1 config.toml 骨架# config.toml # TaoToken 统一 Key 接入配置 [taotoken] api_base https://taotoken.net/api api_key sk-你的Key填这里 timeout_seconds 30 [taotoken.retry] max_attempts 3 backoff_seconds 2 [backup] work_dir /data/backup/wordpress keep_days 14 compress true这里api_base固定为https://taotoken.net/api不要加斜杠结尾也不要加 UTM 参数。api_key填你创建的那串。retry段是给网络抖动准备的备份脚本调用 API 时偶尔超时重试三次基本能覆盖。3.2 settings.json 骨架{ database: { host: 127.0.0.1, port: 3306, name: wordpress, user: wp_backup, credential_ref: taotoken://db/wordpress }, ftp: { host: your-server.com, port: 21, remote_root: /public_html, local_root: /data/backup/wordpress/files, credential_ref: taotoken://ftp/main }, tables_exclude: [ wp_statistics_visitor, wp_statistics_pages, wp_commentmeta ] }注意credential_ref这个字段。它不存明文密码而是一个引用指向 TaoToken 里托管的凭证。备份脚本运行时先拿config.toml里的 Key 去 TaoToken 换取credential_ref对应的真实凭证再连数据库或 FTP。这样settings.json可以安全地提交到私有 Git 仓库不怕泄露。tables_exclude是给数据库导出用的。统计插件和反垃圾插件会往数据库里塞大量日志表这些表体积大但备份价值低排除掉能显著缩小 SQL 文件。我实测下来一个日访问几千的站点排除统计表后 SQL 从 80MB 降到 12MB。3.3 凭证引用解析脚本下面这段 Python 演示如何用统一 Key 解析credential_refimport json import tomllib import requests def load_config(pathconfig.toml): with open(path, rb) as f: return tomllib.load(f) def resolve_credential(cfg, ref): url f{cfg[taotoken][api_base]}/credentials/resolve headers { Authorization: fBearer {cfg[taotoken][api_key]}, Content-Type: application/json } payload {ref: ref} resp requests.post(url, headersheaders, jsonpayload, timeoutcfg[taotoken][timeout_seconds]) resp.raise_for_status() return resp.json()[data] if __name__ __main__: cfg load_config() with open(settings.json, r, encodingutf-8) as f: settings json.load(f) db_cred resolve_credential(cfg, settings[database][credential_ref]) print(数据库用户:, db_cred[user]) print(凭证解析成功密码长度:, len(db_cred[password]))这段代码只做一件事把credential_ref换成真实凭证。运行成功会打印用户名和密码长度不会打印明文密码。这是集中管理凭证的核心价值——脚本里永远看不到明文。4. 数据库导出与 FTP 文件拉取实操配置就绪后进入两条主线的具体操作。4.1 phpMyAdmin 手动导出兜底方案自动化脚本再稳也建议保留一次手动导出的能力。登录 phpMyAdmin 后左侧选中 WordPress 对应的数据库点顶部“导出”标签。导出方式选“自定义”这样能精细控制。关键勾选项选项建议值原因格式SQL通用可被 mysql 命令直接导入添加 DROP TABLE勾选还原时先删旧表避免主键冲突完整插入勾选每条 INSERT 独立部分失败不影响整体导出为文件勾选直接下载不占浏览器内存压缩gzip大库必选体积可降 70% 以上表选择区域把wp_statistics_*、wp_commentmeta这类非核心表取消勾选。点“执行”后浏览器会下载一个.sql.gz文件。这个文件就是数据库的完整快照。4.2 mysqldump 脚本化导出手动导出适合应急日常备份还是要脚本化。下面这条命令是核心mysqldump \ --host127.0.0.1 \ --port3306 \ --userwp_backup \ --password$(python3 resolve_cred.py --field password) \ --single-transaction \ --quick \ --default-character-setutf8mb4 \ --ignore-tablewordpress.wp_statistics_visitor \ --ignore-tablewordpress.wp_statistics_pages \ wordpress \ | gzip /data/backup/wordpress/db_$(date %Y%m%d_%H%M%S).sql.gz几个参数值得说明。--single-transaction保证 InnoDB 表导出时的一致性快照不会锁表站点照常访问。--quick让 mysqldump 逐行读取避免大表一次性载入内存。--ignore-table对应settings.json里的排除表。密码通过子命令从 TaoToken 解析不写死在命令行历史里。导出完成后检查文件ls -lh /data/backup/wordpress/db_*.sql.gz zcat /data/backup/wordpress/db_20250101_030000.sql.gz | head -20zcat看开头几行应该能看到-- MySQL dump和CREATE TABLE语句。如果文件只有几百字节说明导出失败多半是密码或权限问题。4.3 FTP 文件拉取文件备份用lftp比传统ftp命令更稳支持镜像和断点续传lftp -c set ftp:ssl-allow no; set net:timeout 20; set net:max-retries 3; open -u $(python3 resolve_cred.py --field user),$(python3 resolve_cred.py --field password) ftp://your-server.com:21; mirror --reverse --delete --verbose \ --exclude-glob *.log \ --exclude-glob cache/* \ /public_html /data/backup/wordpress/files; mirror --reverse表示从远程拉到本地。--delete让本地与远程保持一致远程删了的文件本地也删。--exclude-glob排除日志和缓存目录这些文件体积大且无备份价值。wp-content/uploads是重点图片全在里面不要排除。拉取完成后核对文件数量find /data/backup/wordpress/files -type f | wc -l du -sh /data/backup/wordpress/files4.4 打包与留存两条线都完成后把数据库和文件打成一个带时间戳的归档cd /data/backup/wordpress tar -czf backup_$(date %Y%m%d).tar.gz \ db_$(date %Y%m%d)*.sql.gz \ files/然后按keep_days清理旧备份find /data/backup/wordpress -name backup_*.tar.gz -mtime 14 -delete5. 验证请求与成功结果备份做完不验证等于没做。验证分三层文件存在、SQL 可解析、文件可还原。5.1 验证 TaoToken 凭证解析先确认统一 Key 能正常换取凭证curl -s -X POST https://taotoken.net/api/credentials/resolve \ -H Authorization: Bearer sk-你的Key \ -H Content-Type: application/json \ -d {ref:taotoken://db/wordpress} \ | python3 -m json.tool成功返回类似{ code: 0, data: { user: wp_backup, password: ******, host: 127.0.0.1 } }如果返回401检查 Key 是否填错或已过期。返回404检查ref路径是否在 TaoToken 里创建过。5.2 验证 SQL 文件完整性gzip -t /data/backup/wordpress/db_20250101_030000.sql.gz echo 压缩包完整gzip -t只测试压缩包是否损坏不输出内容。再检查表数量zcat /data/backup/wordpress/db_20250101_030000.sql.gz | grep -c CREATE TABLE正常 WordPress 核心表有 12 张左右加上插件表会更多。如果结果是 0说明导出的是空文件。5.3 验证文件归档可还原最关键的验证把备份还原到一个临时目录确认文件结构完整。mkdir -p /tmp/restore_test tar -xzf /data/backup/wordpress/backup_20250101.tar.gz -C /tmp/restore_test ls /tmp/restore_test/files/wp-content/themes/ ls /tmp/restore_test/files/wp-content/plugins/能看到主题和插件目录说明文件备份有效。再确认wp-config.php在不在test -f /tmp/restore_test/files/wp-config.php echo 配置文件已备份注意wp-config.php里含数据库密码备份文件要存放在加密磁盘或权限受限的目录不要放公开可访问的路径。5.4 一次完整验证动作把上面串起来跑一次端到端验证#!/bin/bash set -e cd /data/backup/wordpress # 1. 解析凭证 DB_PASS$(python3 resolve_cred.py --field password) # 2. 导出数据库 mysqldump --single-transaction --quick \ -u wp_backup -p$DB_PASS wordpress \ | gzip db_test.sql.gz # 3. 验证 SQL gzip -t db_test.sql.gz TABLE_COUNT$(zcat db_test.sql.gz | grep -c CREATE TABLE) echo 导出表数量: $TABLE_COUNT test $TABLE_COUNT -gt 5 # 4. 拉取文件 lftp -c open -u user,pass ftp://your-server.com; \ mirror --reverse /public_html/wp-content/uploads /tmp/uploads_test # 5. 验证文件 test -d /tmp/uploads_test echo 备份验证通过跑通后看到“备份验证通过”说明整条链路是活的。之后把它挂到 cron 里每天凌晨执行一次即可。6. 本篇常见错排查6.1 mysqldump 报 Access denied最常见的原因是wp_backup用户没有SELECT和LOCK TABLES权限。用 root 登录 MySQL 授权GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON wordpress.* TO wp_backup127.0.0.1; FLUSH PRIVILEGES;注意--single-transaction模式下其实不需要LOCK TABLES但加上无害。如果还是报错检查wp-config.php里的数据库名和settings.json是否一致。6.2 导出的 SQL 导入时报“表已存在”导出时没勾“添加 DROP TABLE”。手动导出时在 phpMyAdmin 里勾上脚本导出时加--add-drop-tablemysqldump --add-drop-table --single-transaction ...6.3 FTP 拉取中文文件名乱码lftp 默认用 UTF-8但有些服务器用 GBK。在 lftp 命令里加set ftp:charset gbk; set file:charset utf-8;如果文件名还是乱改用wget的 FTP 模式或rsync over ssh后者更稳但需要 SSH 权限。6.4 TaoToken 凭证解析超时先确认网络能通curl -I https://taotoken.net/api如果超时检查config.toml里的timeout_seconds是否太小调到 30 以上。如果返回429说明请求频率过高把retry.backoff_seconds调大或者减少并发解析次数。6.5 备份文件越来越大检查tables_exclude是否生效。用这条命令看各表大小SELECT table_name, ROUND(((data_length index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.tables WHERE table_schema wordpress ORDER BY size_mb DESC LIMIT 10;排在前面的如果是wp_options或wp_postmeta那是核心表不能排除。如果是统计类表加到排除列表里。另外wp_options里的transient缓存也可以清理DELETE FROM wp_options WHERE option_name LIKE _transient_%;6.6 还原后站点白屏多半是wp-config.php里的数据库信息没改或者siteurl、home两个 option 还指向旧域名。还原后进 phpMyAdmin 执行UPDATE wp_options SET option_value https://新域名 WHERE option_name IN (siteurl, home);7. 把备份流程固定下来整套流程跑通后建议做三件事。第一把config.toml和settings.json放进私有 Git 仓库但config.toml里的api_key用环境变量覆盖不要提交明文。第二备份脚本加日志每次执行记录导出表数量、文件数量、归档大小方便回溯。第三每季度做一次还原演练把备份真正导入一个测试环境确认能跑起来。如果你后续想把备份脚本接到更自动化的编码或 Agent 流程里比如让脚本自己判断备份是否异常并触发告警可以了解 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite如果只是想先验证模型对话能力看这个https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite备份这件事工具和方法都不复杂难的是坚持和验证。把凭证集中管好把两条线脚本化把验证做成习惯剩下的就是让 cron 替你干活。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进