用 crontab 给云服务器做自动备份:网站文件与 MySQL 每日备份实战

举报
yd_251860871 发表于 2026/11/15 09:22:07 2026/11/15
【摘要】 本文使用 cron、tar 与 mysqldump 搭建每日自动备份方案,并介绍日志、旧备份清理与恢复演练。

云服务器上跑着网站或小项目,最怕的不是宕机,而是误删文件、数据库被写坏之后发现没有备份。本文以 Flexus L 这类单机云服务器为例,用系统自带的 cron + tar + mysqldump,搭一套“每天自动备份、自动清理旧备份、出错能看到日志”的方案,全程不依赖第三方工具。

一、规划备份目录

先约定好目录,后面的脚本和清理逻辑都围绕它:

sudo mkdir -p /data/backup/{site,mysql,logs}
sudo chmod 700 /data/backup
  • /data/backup/site:网站文件压缩包
  • /data/backup/mysql:数据库导出文件
  • /data/backup/logs:备份脚本的运行日志

权限设为 700,避免其他用户读到数据库导出内容。

二、编写备份脚本

新建 /usr/local/bin/daily_backup.sh:

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

DATE=$(date +%F_%H%M)
BASE=/data/backup
SITE_DIR=/var/www/html
KEEP_DAYS=7

# 1. 打包网站文件
tar -czf "$BASE/site/site_$DATE.tar.gz" -C "$(dirname $SITE_DIR)" "$(basename $SITE_DIR)"

# 2. 导出数据库(账号信息放在 ~/.my.cnf,不写进脚本)
mysqldump --single-transaction --routines --all-databases | gzip > "$BASE/mysql/db_$DATE.sql.gz"

# 3. 清理超过 KEEP_DAYS 天的旧备份
find "$BASE/site"  -name '*.tar.gz' -mtime +$KEEP_DAYS -delete
find "$BASE/mysql" -name '*.sql.gz' -mtime +$KEEP_DAYS -delete

echo "[$(date '+%F %T')] backup ok"

几个要点:

  1. set -euo pipefail 让任何一步出错就立即退出,避免“前面失败了还继续清理旧备份”这种最糟糕的情况。
  2. --single-transaction 对 InnoDB 表做一致性快照,导出时不锁表,网站可以照常访问。
  3. 数据库密码不要写进脚本,放在执行用户的 ~/.my.cnf 中,并 chmod 600:
[client]
user=backup
password=请替换为你自己的密码

建议单独建一个只有 SELECT、LOCK TABLES、SHOW VIEW、TRIGGER 权限的 backup 账号,不要直接用 root。

赋予执行权限并手动跑一次:

sudo chmod +x /usr/local/bin/daily_backup.sh
sudo /usr/local/bin/daily_backup.sh
ls -lh /data/backup/site /data/backup/mysql

三、交给 cron 定时执行

sudo crontab -e 添加一行,每天凌晨 3:30 执行:

30 3 * * * /usr/local/bin/daily_backup.sh >> /data/backup/logs/backup.log 2>&1

cron 表达式五个字段依次是:分、时、日、月、星期。常见写法:

表达式 含义
30 3 * * * 每天 03:30
0 */6 * * * 每 6 小时整点
0 2 * * 0 每周日 02:00
*/10 * * * * 每 10 分钟

四、cron 常见的三个坑

1. 环境变量不同。 cron 运行时 PATH 很短,手动能跑的脚本在 cron 里可能报 command not found。解决办法是在脚本开头写上 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin,或者命令一律写绝对路径。

2. 时区不对。 云服务器默认可能是 UTC,凌晨 3 点会变成北京时间上午 11 点,正好是访问高峰。用 timedatectl 查看,必要时执行 sudo timedatectl set-timezone Asia/Shanghai,然后 sudo systemctl restart cron(CentOS 系为 crond)。

3. 静默失败。 不重定向输出的话,出错信息会被丢弃或发到本地邮箱,很难发现。上面的 >> backup.log 2>&1 就是为了把每次运行结果都留在日志里。可以用 grep -c "backup ok" /data/backup/logs/backup.log 快速核对成功次数,用 grep /usr/local/bin/daily_backup.sh /var/log/syslog(或 /var/log/cron)确认 cron 是否真的触发了。

五、备份要能恢复才算数

定期做一次恢复演练,确认备份文件不是空壳:

# 检查压缩包完整性
tar -tzf /data/backup/site/site_最新日期.tar.gz > /dev/null && echo site ok
gunzip -t /data/backup/mysql/db_最新日期.sql.gz && echo db ok

# 恢复数据库(谨慎操作,最好先在测试库上验证)
gunzip < /data/backup/mysql/db_最新日期.sql.gz | mysql

六、再进一步:异地保存

备份和网站放在同一块云盘上,一旦实例被误删或磁盘故障,备份也会一起丢失。条件允许的话,可以把每天的备份再同步到对象存储 OBS 或另一台机器上(例如用 rsync -az 推送到另一台服务器),形成“本机保留 7 天 + 异地保留 30 天”的两层策略。同时留意磁盘占用,可以用 du -sh /data/backup 定期查看,避免备份把系统盘写满。

小结

一个 20 行左右的脚本加一行 crontab,就能让云服务器拥有每日自动备份能力。关键是三件事:脚本出错立即停止、日志一定要留、定期做恢复演练。把这套流程配好,误删文件时就不会手足无措了。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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