MySQL备份脚本需用--defaults-extra-file指定配置文件并设chmod 600权限,cron中须用绝对路径调用命令、显式声明PATH、重定向标准错误,备份文件名含时间戳,用find轮转保留7天,存储目录须独立且可写,并定期验证可恢复性。

MySQL 备份脚本必须显式指定 --defaults-extra-file 或避免密码明文
直接在 mysqldump 命令里写 -p'password' 会导致 cron 执行失败,因为 cron 环境不读取交互式 shell 的别名、函数或某些环境变量,且密码明文还存在安全风险。更稳妥的方式是使用配置文件:
- 创建仅限当前用户可读的配置文件,例如
/home/user/.mybackup.cnf - 内容为:
[client] user = backup_user password = your_strong_password host = localhost
- 执行备份时加参数:
mysqldump --defaults-extra-file=/home/user/.mybackup.cnf --single-transaction --routines --triggers db_name > backup.sql - 务必运行
chmod 600 /home/user/.mybackup.cnf,否则mysqldump会拒绝读取
cron 时间表达式要匹配实际执行权限和路径
很多备份脚本在终端能跑,但加进 crontab 就静默失败,根本原因是 cron 使用最小化环境:没有 $PATH,不加载 ~/.bashrc,找不到 mysqldump 或 gzip。
- 用绝对路径调用命令,比如
/usr/bin/mysqldump和/bin/gzip(可用which mysqldump确认) - 在 crontab 条目开头显式声明
PATH,例如:PATH=/usr/local/bin:/usr/bin:/bin - 测试 cron 环境:临时加一行
* * * * * env > /tmp/cron_env.txt,查看实际可用变量 - 日志重定向不能只写
> /path/to/log,要补全错误流:> /var/log/backup.log 2>&1
备份文件名必须含时间戳,且保留多份需手动轮转
不带时间戳的备份文件会被覆盖,而 cron 本身不提供文件轮转能力。靠命名 + 简单 find 删除是最轻量可控的做法。
- 生成带日期的文件名:
backup_$(date +\%Y\%m\%d_\%H\%M).sql.gz - 压缩一步到位,减少中间文件:
mysqldump ... | gzip > $filename - 保留最近 7 天的备份:
find /backup -name "backup_*.sql.gz" -mtime +7 -delete - 注意
find -delete不支持 macOS,默认用-exec rm {} \;
权限与存储位置不当会导致备份“成功”但不可恢复
常见假成功:cron 显示退出码 0,日志里却有 Access denied 或 No such file or directory,根源常在权限链上。
- 备份目录(如
/backup)必须由运行 cron 的用户(非 root)可写;若用sudo crontab -u mysql,则目录需对mysql用户开放 - 不要把备份存到 MySQL 数据目录(
/var/lib/mysql)下——万一磁盘满或误删,连原始数据一起丢 - 备份前加校验:
mysqldump --no-data --databases db_name >/dev/null 2>&1,快速确认连接和权限是否 OK - 定期抽样解压并
head -20检查 SQL 文件头,防 gzip 静默损坏
实际最难的不是写 cron 行,而是让每次备份都真正可恢复。建议每月手动执行一次 restore 流程,哪怕只到 mysql -e "CREATE DATABASE IF NOT EXISTS test_restore" 这一步。


















