几乎每个站长都知道要备份,多数人也确实在备份:宝塔面板开了计划任务,每天打包一次,传到对象存储。听起来没问题。真出事的时候,打开备份目录才发现:最近三天的包都是 0 字节,因为磁盘满了;或者包能下载,解压报错,因为打包时数据库正在写入。
备份这件事,只有恢复成功才算数。没验证过的备份,不能计入安全库存。
备份要满足四个条件
第一,完整性。网站目录、数据库、配置文件、SSL 证书、伪静态规则,缺一项都可能恢复不起来。只备份数据库不备份 uploads 目录,恢复后图片全丢。
第二,可读性。压缩包能正常解开,SQL 文件能正常导入。建议每次备份后自动校验文件大小和 CRC,异常就告警。
第三,异地。备份和数据在同一台服务器上,服务器挂了备份也没了。至少一份放到对象存储或另一台机器。
第四,版本。保留最近七天日备、四周周备、十二个月月备。勒索病毒加密后会潜伏一段时间才发作,只有日备容易被一锅端。
恢复演练怎么做
不需要等到出事。准备一台测试服务器(1 核 2G 就够),按下面的步骤走一遍:
- 从对象存储下载最近一次备份,记录耗时。
- 解压网站目录,导入数据库,修改配置文件里的数据库账号。
- 配置伪静态,启动 Nginx 和 PHP。
- 用测试域名访问首页、栏目页、文章页、后台。
- 检查图片是否完整、表单是否能提交、搜索是否可用。
- 记录总耗时和遇到的问题。
整个过程两小时左右。第一次做大概率会发现问题:数据库版本不一致、字符集错误、附件目录漏备、证书没导出。这些问题在演练时发现,成本是两小时;在真出事时发现,成本是业务停摆。
四个常见的恢复失败原因
1. 数据库版本不匹配
生产是 MySQL 8.0,测试是 5.7,导入时报语法错误。备份策略里要记录环境版本,恢复环境尽量保持一致。
2. 字符集问题
导出时用了默认字符集,导入后中文变问号。导出命令里明确写 utf8mb4,导入时也指定。
3. 文件权限
解压后属主是 root,PHP 跑在 www 用户下,读写失败,后台白屏。恢复脚本里加一步 chown -R www:www。
4. 绝对路径写死
配置文件里的路径是 /www/wwwroot/old.com,新环境路径不同,程序找不到文件。恢复时先改配置再启动。
一套可以直接用的脚本思路
备份脚本做四件事:打包网站目录(排除缓存和日志)、导出数据库、计算校验值、上传到对象存储并记录日志。任何一步失败就发通知,不要静默失败。
恢复脚本做五件事:下载指定日期的包、校验、解压到临时目录、导入数据库、替换配置里的域名和路径。脚本化之后,恢复时间能从半天压缩到半小时。
宝塔面板的计划任务可以完成打包和上传,但校验和恢复还得自己写。具体的任务配置见宝塔计划任务。
演练频率
建议每季度一次,换版本、换服务器、改架构之后加做一次。演练完写一页记录:备份日期、恢复耗时、遇到的问题、改进项。这页纸在真出事时比任何文档都有用。
备份策略要写进运维文档
备份这件事最怕依赖某个人的记忆。谁知道备份放在哪、怎么恢复、脚本在哪台机器上,这些信息必须写下来,放进团队的运维文档,而不是留在某个人的电脑里。
文档至少包含:备份频率与保留周期、存储位置与访问方式、恢复步骤与预计耗时、最近的演练日期与结果、负责人与备份人。五条信息,一页纸。
人员变动时,这份文档就是交接材料。我们见过因为运维离职,备份脚本失效半年没人发现的情况——磁盘满了,计划任务静默失败,谁也不知道。
常见问题
云服务器的自动快照够不够
快照适合整机回滚,不适合单文件恢复,也不防"数据被误删后继续运行"的场景。快照加逻辑备份,两层都要有。
备份文件要不要加密
要。备份包里是完整的客户数据和数据库账号,泄露的后果比网站被黑更严重。对象存储桶设为私有,文件加密后再上传。
小站也要做演练吗
要,而且更简单。一个小站恢复只要二十分钟,一年做两次,成本很低。等到客户数据丢了再补,代价高得多。
备份是安全的最后一道防线,前面还有一层是加固。日常该改的七项设置见宝塔面板安全设置。