背景
手头维护着几个业务项目,日常关注点都在代码和功能迭代上,服务器的备份状况很久没完整梳理了。趁着项目间隙做了一次全面巡检,结果比预期的要严重。
巡检范围是 5 台生产服务器,地域分散、OS 各异:
| 编号 | 区域 | 系统 | 云平台 | 主要业务 |
|---|---|---|---|---|
| A | 美国 | Debian 10 | — | 仓储物流、电商同步 |
| B | 美国 | Debian | Linode | 演示环境、AI 服务 |
| C | 中国 | Debian 11 | — | 多站点 Web、CRM |
| D | 中国 | Debian 13 | — | 业务中台、OMS |
| E | 中国 | CentOS | 华为云 | WMS 库存系统 |
巡检方式为只读 SSH,检查维度:数据库备份、文件备份、磁盘容量、密码安全。
巡检发现
总体统计
| 指标 | 数值 |
|---|---|
| 已配置数据库备份 | 3 / 5(60%) |
| 文件备份正常运行 | 1 / 5(20%) |
| 磁盘告警(≥85%) | 2 / 5(40%) |
| 密码明文泄露 | 3 / 5(60%) |
| 备份有轮转策略 | 0 / 5(0%) |
逐台情况
服务器 A(美国): 磁盘 158G,已用 90%,仅剩约 2 天空间。MySQL 备份和文件备份都在跑,但 178 个历史备份无限累积(32GB + 54GB),没有轮转。MySQL 密码明文写在 crontab 里。
服务器 B(美国): 磁盘 311G(65%)。运行着 Docker 化应用和两个 MySQL 实例。完全无任何备份配置。无密码泄露(此前未配备份故无 cron)。
服务器 C(中国): 磁盘 79G,100% 满。14+ 个 Web 站点,MySQL 每日备份正常(连续 28 天),但文件备份因磁盘满已中断一个多月。密码明文写入 crontab。
服务器 D(中国): 磁盘 157G(4%)。完全无备份。OS 最新但缺少最基础的运维配置。
服务器 E(中国): 磁盘 40G(66%)。MySQL 每日备份已运行 92 天,但每个文件仅 351 字节(数据库近乎为空)。文件备份因目标目录不存在一直失败。两份 crontab 均含明文密码。
共性问题的严重性
六个字总结:无轮转、明文、裸奔。
- 无轮转是最普遍的慢性病。备份脚本写好就再也没人看过,文件无限堆积。
- 密码明文是安全红线。crontab 里的
-p<密码>对任何有 shell 权限的用户都是明文可读的。 - 零备份的两台服务器如果出问题,数据恢复几率为零。
实施方案
根据”已有备份修复增强、无备份全新部署”的原则,将 5 台分为三类:
| 服务器 | 策略 | 核心动作 |
|---|---|---|
| A | 增强现有 | 清旧备份、加轮转、修密码 |
| B | 全新部署 | 建脚本、配 cron、加轮转 |
| C | 修复现有 | 清磁盘、恢复 WWW 备份、加轮转、修密码 |
| D | 全新部署 | 建脚本、配 cron、加轮转 |
| E | 修复现有 | 建缺失目录、删重复 cron、加轮转、修密码 |
统一方案
所有服务器的备份都遵循同一套结构:
/backup/
├── mysql/ ← 数据库 dump
│ └── all-YYYYMMDD.sql.gz
└── www/ ← 应用文件 tar.gz
└── www-YYYYMMDD.tar.gz
关键设计决策:
1. MySQL 密码治理:从 crontab 明文到 .my.cnf
cat > /root/.my.cnf << 'EOF'
[mysqldump]
user=root
password=<actual-password>
EOF
chmod 600 /root/.my.cnf
crontab 命令从 mysqldump -uroot -p<password> 改为 mysqldump --defaults-extra-file=/root/.my.cnf。密码不再出现在任何可读文件中。
2. 轮转策略:find + mtime
备份脚本末尾统一添加一行:
find "$BACKUP_DIR" -name '*.gz' -mtime +7 -delete
find "$BACKUP_DIR" -name '*.tar.gz' -mtime +7 -delete
保留 7 天,简单可靠,不引入额外依赖。cron 命令用 && 串联备份和清理,清理失败不影响备份本身。
3. 全新部署使用独立脚本
对两台零备份服务器,创建 /opt/backup.sh 统一管理逻辑,cron 一行调用。对已有备份的服务器,直接在 cron 行中追加 && find ... -delete,避免叠加两个 cron 入口。
4. 重复 cron 治理
服务器 E 的 root 和 www 用户各有一份备份 cron,内容几乎一致。实施时清理了 www 用户的重复行,备份统一由 root 管理。
实施结果
| 服务器 | 策略 | 磁盘(前→后) | DB备份 | 文件备份 | 轮转 | 密码 |
|---|---|---|---|---|---|---|
| A | 增强 | 91% → 71% | 保留原有 | 保留原有 | 7天 | .my.cnf |
| B | 全新 | 67% → 67% | 新建 | 新建 | 7天 | .my.cnf |
| C | 修复 | 100% → 47% | 保留原有 | 恢复运行 | 7天 | .my.cnf |
| D | 全新 | 4% → 4% | 新建 | 新建 | 7天 | socket |
| E | 修复 | 66% → 67% | 保留原有 | 恢复运行 | 7天 | .my.cnf |
关键数字:
- 磁盘空间释放:52GB(服务器 A 清掉 179 个旧备份释放 29GB,服务器 C 清掉 16GB 残留文件释放 23GB)
- 密码安全:4 台明文密码全部迁移至
.my.cnf(600 权限),1 台使用 Unix socket 认证无需密码 - 备份覆盖率:从 60% 提升至 100%
- 轮转覆盖率:从 0% 提升至 100%
这次巡检教会了我什么
巡检比备份本身更稀缺。 备份脚本写好后人就会忘掉它——直到磁盘满了或数据丢了才发现问题。这次 5 台里有 2 台的备份虽然配置了但实际上没在跑(磁盘满、目录不存在),如果不是手动巡检根本不知道。
轮转不是锦上添花,是备份能持续运行的保证。 没有轮转的备份系统是有寿命的——磁盘终会被填满。7 天保留对大多数业务场景足够,具体天数可按需调整。
密码不能依赖”crontab 只有 root 能看”的安全假设。 .my.cnf 加 chmod 600 是 MySQL 官方推荐的认证方式,不增加依赖,习惯成本接近零。
统一结构降低心智负担。 5 台服务器、3 种 OS、2 种包管理器、不同 Web 目录——但备份脚本的逻辑完全一致。下次再巡检,只需要检查 /backup/ 下有没有今天的文件。
待办
这次只完成了基础备份。还有三层没覆盖:
- Redis 备份:5 台服务器的 Redis 均无持久化备份
- 异地备份:所有备份仅存本地磁盘,机房级故障无法恢复
- 监控告警:备份失败目前零感知,完全依赖人工巡检
小结
备份体系的建设不是一次性的,而是”配置→验证→轮转→监控”四个环节的闭环。这次花了半天时间把 5 台服务器从”部分有备份、全部有问题”拉到”全部有备份、轮转统一”的基线,但仍需持续投入。
如果你手上也有几台”跑着就行”的服务器,花一小时登上去看看 crontab、df -h 和备份目录——大概率会有意外发现。