华为云 ECS 上用 crontab + obsutil 做定时备份:从脚本到过期清理的完整实践

举报
yd_252351073 发表于 2026/10/31 08:50:03 2026/10/31
【摘要】 服务器上的数据只放在一块云硬盘里,总归不太踏实。误删文件、程序写坏数据、系统盘出问题,哪一个碰上都够折腾半天。云硬盘快照当然能用,但如果只想把网站目录和数据库导出文件每天存一份,用 crontab 加 OBS 对象存储就够了,成本低,恢复起来也直观。下面是我在一台 CentOS/EulerOS 类 ECS 上实际搭的流程,Ubuntu 上命令基本一样。 一、准备工作:桶和访问密钥在 OBS ...

服务器上的数据只放在一块云硬盘里,总归不太踏实。误删文件、程序写坏数据、系统盘出问题,哪一个碰上都够折腾半天。云硬盘快照当然能用,但如果只想把网站目录和数据库导出文件每天存一份,用 crontab 加 OBS 对象存储就够了,成本低,恢复起来也直观。下面是我在一台 CentOS/EulerOS 类 ECS 上实际搭的流程,Ubuntu 上命令基本一样。

一、准备工作:桶和访问密钥

  1. 在 OBS 控制台创建一个桶,区域尽量和 ECS 保持一致。同区域走内网,速度快,也不产生公网流量费。存储类别选标准或低频访问都可以,备份文件读得少,低频访问更划算。
  2. 不建议直接用主账号的 AK/SK。在 IAM 里新建一个子用户,只授予这个桶的读写权限,再给它生成访问密钥。万一密钥泄露,影响范围也有限。

二、安装并配置 obsutil

obsutil 是华为云官方的 OBS 命令行工具,单个二进制文件,下载解压就能用:

cd /opt
wget https://obs-community.obs.cn-north-1.myhuaweicloud.com/obsutil/current/obsutil_linux_amd64.tar.gz
tar -xzvf obsutil_linux_amd64.tar.gz
cd obsutil_linux_amd64_*
chmod 755 obsutil
ln -s "$(pwd)/obsutil" /usr/local/bin/obsutil

配置密钥时推荐用交互模式,避免 AK/SK 留在 shell 历史里:

obsutil config -interactive

按提示填 AK、SK 和 Endpoint,例如华北-北京四是 obs.cn-north-4.myhuaweicloud.com。配置会写入当前用户的 ~/.obsutilconfig,记得 chmod 600 ~/.obsutilconfig。配好后先测一下:

obsutil ls obs://my-backup-bucket

能列出桶内容(空桶也会正常返回),说明连通性和权限都没问题。

三、写备份脚本

假设要备份 /var/www 网站目录和一个 MySQL 库。新建 /opt/backup/backup.sh:

#!/bin/bash
set -euo pipefail

DATE=$(date +%Y%m%d_%H%M)
WORKDIR=/data/backup
BUCKET=obs://my-backup-bucket/$(hostname)
OBSUTIL=/usr/local/bin/obsutil

mkdir -p "$WORKDIR"
cd "$WORKDIR"

# 1. 打包网站目录
tar -czf "www_${DATE}.tar.gz" -C /var www

# 2. 导出数据库(账号密码放在 /root/.my.cnf,权限 600)
mysqldump --single-transaction --routines mydb | gzip > "mydb_${DATE}.sql.gz"

# 3. 上传到 OBS
$OBSUTIL cp "www_${DATE}.tar.gz" "${BUCKET}/www/"
$OBSUTIL cp "mydb_${DATE}.sql.gz" "${BUCKET}/db/"

# 4. 清理 7 天前的本地文件
find "$WORKDIR" -name "*.gz" -mtime +7 -delete

echo "$(date '+%F %T') backup ok: ${DATE}"

几点说明:

  • set -euo pipefail 让任何一步失败时脚本立刻退出,不会出现“打包失败了还在上传空文件”的情况。
  • mysqldump --single-transaction 对 InnoDB 表做一致性导出,不锁表,适合线上库。密码写在 /root/.my.cnf 的 [client] 段里,比直接写进脚本安全。
  • 本地只留 7 天,云上的保留策略交给 OBS 处理,见第五节。

加执行权限后先手动跑一遍:

chmod +x /opt/backup/backup.sh
/opt/backup/backup.sh
obsutil ls obs://my-backup-bucket/$(hostname)/ -limit=20

四、交给 crontab 定时执行

crontab -e 添加一行,每天凌晨 3 点 15 分执行:

15 3 * * * /usr/bin/flock -n /tmp/backup.lock /opt/backup/backup.sh >> /var/log/backup.log 2>&1

五个字段依次是:分、时、日、月、星期。这里用了 flock -n:上一次备份还没跑完时,新任务直接跳过,避免两个进程同时打包、互相抢磁盘。输出追加到 /var/log/backup.log,出问题时先看这个文件。

日志会越写越大,可以加一个 logrotate 配置 /etc/logrotate.d/backup:

/var/log/backup.log {
    weekly
    rotate 4
    compress
    missingok
    notifempty
}

五、云上的过期清理:用生命周期规则

OBS 上的旧备份不需要自己写脚本删。在桶的“生命周期规则”里新建一条规则,前缀填对应的主机名目录,设置对象在 30 天后过期删除即可。如果对成本更敏感,还可以设置 N 天后转为归档存储,再过一段时间删除。规则由 OBS 后台执行,生效会有一定延迟,不用盯着当天的结果。

六、失败了怎么知道

定时任务最怕悄悄失败。备份脚本连续停了一个月,直到要恢复数据时才发现,这种事并不少见。比较省事的做法有两种:

一是在脚本末尾成功时写一个时间戳文件,再用另一个每天运行的小检查脚本判断这个文件是不是超过 26 小时没更新,超过就发告警。告警渠道可以用企业微信、钉钉机器人的 Webhook,或者服务器上已有的邮件工具。

二是定期查看桶里的最新对象时间。比如每周一抽空执行一次 obsutil ls,确认最近几天的文件都在、大小正常。数据库导出文件如果突然只有几 KB,通常说明导出出错了,只上传了一个空的压缩包。

不管用哪种方式,关键是让“没备份成功”这件事能被人看到,而不是只靠日志文件躺在磁盘上。

七、常见坑

  1. cron 环境变量很少:cron 里的 PATH 通常只有 /usr/bin:/bin,手动能跑、定时不跑,十有八九是这个原因。脚本里一律用绝对路径,或在开头显式设置 PATH。
  2. % 在 crontab 里是特殊字符:直接在 crontab 行里写 date +%F 会被截断,需要写成 \%。把逻辑放进脚本里就能避开这个问题。
  3. obsutil 配置文件找不到:配置跟着用户走。如果用 root 的 crontab,就要在 root 下执行 obsutil config,否则会报鉴权失败。
  4. 时区不对:部分镜像默认是 UTC,“凌晨 3 点”实际变成北京时间 11 点。用 timedatectl 确认,必要时执行 timedatectl set-timezone Asia/Shanghai,再重启 crond。
  5. 只备份、不恢复:建议每个月挑一份备份下载下来,实际解压、导入一次:
obsutil cp obs://my-backup-bucket/$(hostname)/db/mydb_xxx.sql.gz /tmp/
gunzip -c /tmp/mydb_xxx.sql.gz | mysql mydb_restore_test

能恢复出来的备份才算真正的备份。

小结

整套方案就是:脚本负责打包和上传,crontab 负责定时,flock 防止任务重叠,日志用来排查问题,OBS 生命周期规则负责清理旧备份。全部搭完大概半小时,之后基本不用再管。再配上每月一次的恢复演练,小型站点的数据安全就有了一个比较稳的底线。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。