crontab中mysqldump不执行主因是环境变量缺失;需显式指定mysqldump全路径、声明path、避免依赖~/.my.cnf、添加时间戳与错误处理、确保日志权限、校验cron时间格式、定期清理旧备份。

crontab 里 mysqldump 命令总不执行?先检查 SHELL 环境和路径
很多情况下 crontab 任务看似添加成功,但备份文件始终没生成,根本原因常是环境变量缺失:crontab 默认使用 /bin/sh,而 mysqldump 可能装在 /usr/bin/ 或 /usr/local/bin/,sh 找不到它。
解决方法很简单:
- 在 crontab 条目里显式写全
mysqldump路径,用which mysqldump查准位置(常见为/usr/bin/mysqldump) - 加上
PATH声明,比如开头加一行:PATH=/usr/local/bin:/usr/bin:/bin - 避免依赖当前用户的
~/.my.cnf—— cron 不读这个,要么把账号密码明写进命令(不推荐),要么用独立配置文件并用--defaults-extra-file指定
备份脚本必须加时间戳和错误处理,否则覆盖或静默失败
直接用 mysqldump db_name > backup.sql 会每天覆盖,出问题也无从排查。实际脚本至少要包含日期标记、退出码判断和简单日志。
一个最小可用的备份脚本(保存为 /root/scripts/mysql_backup.sh):
#!/bin/bash DATE=$(date +\%Y\%m\%d_\%H\%M) DB_NAME="your_db" DUMP_CMD="/usr/bin/mysqldump" CONF_FILE="/root/.mybackup.cnf" # 内容:[client] user=xxx password=xxx <p>$DUMP_CMD --defaults-extra-file="$CONF_FILE" --single-transaction --routines "$DB_NAME" | gzip > "/backup/$DB_NAME-$DATE.sql.gz"</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill2334" title="MySQL"><img src="https://img.php.cn/upload/skill/000/000/081/178900927846657.jpg" alt="MySQL" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="overflowclass">MySQL</a> <p class="overflowclass">编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。</p> </div> <a rel="nofollow" href="/xiazai/skill2334" title="MySQL" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><p>if [ $? -ne 0 ]; then echo "[$(date)] ERROR: mysqldump failed for $DB_NAME" >> /var/log/mysql_backup.log exit 1 fi echo "[$(date)] OK: $DB_NAME-$DATE.sql.gz saved" >> /var/log/mysql_backup.log</p>
-
--single-transaction对 InnoDB 表保证一致性,不锁表;MyISAM 必须用--lock-all-tables(会阻塞写入) - gzip 压缩必须紧跟管道,别写成两步(否则中间文件可能被删或占满磁盘)
- 日志路径
/var/log/mysql_backup.log需确保 cron 用户(通常是 root)有写权限
crontab 时间表达式写错导致“每天跑两次”或“根本没跑”
最典型错误是把 0 2 * * *(每天 2 点)误写成 0 2 * * * *(多了一个 *),系统会当成非法格式跳过执行,且不报错。
正确添加方式(以 root 身份):
sudo crontab -e
然后加入这一行:
0 2 * * * /bin/bash /root/scripts/mysql_backup.sh
- 务必用绝对路径调用脚本,cron 不继承你的
$PATH或~ - 时间字段顺序是:分 时 日 月 周,别和某些文档里“秒 分 时…”混淆
- 测试是否生效:临时改成
* * * * *(每分钟跑一次),等 2 分钟后看日志和备份目录,确认再改回原时间
备份文件堆积太多,磁盘爆满前得自动清理旧文件
备份本身不难,难的是长期运行后 /backup 目录塞满几个月的压缩包。别等报警才处理,脚本末尾加一句清理逻辑即可:
find /backup -name "*.sql.gz" -mtime +7 -delete
-
-mtime +7表示“修改时间超过 7 天”,注意不是“创建时间”;mysqldump输出的文件修改时间即备份时刻,可直接用 - 先用
find /backup -name "*.sql.gz" -mtime +7 -print预览要删哪些,确认无误再换-delete - 如果备份文件名含空格或特殊字符,这条 find 命令仍安全 ——
-delete是 find 自带动作,不经过 shell 解析
真正麻烦的是跨主机同步或加密存储,那得另配 rsync 或 gpg;单机定时备份这件事,核心就三点:路径写死、错误检查、旧文件清理。漏掉任何一点,半年后都会变成救火现场。










