直接用crontab调度写死绝对路径、自带清理和日志的Shell脚本即可稳定备份;失败主因是cron环境极简——不加载bashrc、PATH极短、HOME错乱,须脚本内声明PATH、全路径调用命令、mkdir -p建目录、时间戳防覆盖、find自动清理旧包、tar校验包完整性,并在crontab条目末尾重定向日志。

直接用 crontab 调度一个写死绝对路径、自带清理和日志的 Shell 脚本,就能稳定运行定时备份;别指望 cron 本身能“智能备份”,它只负责准时调用,成败全在脚本是否独立可靠。
crontab 定时任务执行失败的常见原因
很多备份看似配置好了,却从没真正跑成,问题几乎都出在环境不一致上:
- crontab 不读
~/.bashrc或/etc/environment,PATH默认极短(通常只有/usr/bin:/bin),脚本里写的tar或mysqldump直接报command not found - 脚本里用了相对路径(如
./backup.sh或~/backup),cron 执行时工作目录是/root或/home/user,但不是你期望的那个 - 脚本需要 root 权限(比如备份
/etc或停库),却用普通用户 crontab 运行,权限不足静默失败 - 日志没重定向,失败时没有任何输出,你根本不知道它没跑
备份脚本必须显式声明 PATH 和使用绝对路径
脚本开头不加这几行,等于裸奔:
#!/bin/bash PATH=/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin export PATH
所有命令必须带绝对路径,否则 cron 环境下大概率失效:
- 用
/bin/tar而不是tar - 用
/usr/bin/find而不是find - 用
/usr/bin/mysqldump而不是mysqldump(如果 MySQL 是包管理安装) - 源目录、目标目录、日志路径全部写绝对路径,例如
SOURCE_DIR="/var/www/html"、BACKUP_DIR="/backup"
时间戳命名也得防冲突:DATE=$(date +\%Y\%m\%d_\%H\%M)(注意 % 要转义),生成类似 20260710_0302.tar.gz 的文件名。
自动清理旧备份不能靠人工,必须写进脚本
清理逻辑放在脚本末尾,比单独起个清理任务更可控、更少出错:
- 用
/usr/bin/find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete删除 7 天前的归档包 - 别用
-daystart(部分老系统不支持),-mtime +7已足够稳定 - 如果目标目录可能为空或不存在,先加
mkdir -p "$BACKUP_DIR" - 加校验一步:用
/bin/tar -tzf "$ARCHIVE" > /dev/null检查压缩包是否损坏,失败就exit 1,避免把坏包当成功
crontab 条目必须重定向日志并手动验证
别信“我设了,它就在跑”。每次新增或修改后,必须做三件事:
- 手动执行一次:
/usr/local/bin/backup.sh,确认生成文件、日志有记录、tar -tzf能列出内容 - crontab 行末必须加日志重定向:
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 - 检查 cron 是否活着:
systemctl is-active cron(Debian/Ubuntu)或systemctl is-active crond(RHEL/CentOS),挂了就sudo systemctl start cron
真正容易被忽略的是:脚本里写的 echo 日志,和 crontab 重定向的日志,是两回事。前者记关键节点(如“开始打包”“清理完成”),后者捕获所有 stdout/stderr(包括错误堆栈)。两者都要有,缺一不可。


















