crontab 备份脚本失效主因是环境差异:path 狭窄、无 shell 配置、工作目录为家目录;须用绝对路径、显式 cd、补全 path/shell、重定向日志;rsync 需 –delete 与 –exclude 配合,注意斜杠语义和时间戳格式;末尾加 sync 确保落盘。

crontab 里执行备份脚本不生效,路径和环境变量是主因
脚本在终端能跑,加到 crontab 就静默失败,大概率不是脚本逻辑问题,而是 cron 的执行环境太“干净”:没加载用户 shell 配置,$PATH 只有 /usr/bin:/bin,且当前工作目录是家目录,不是脚本所在目录。
- 所有命令用绝对路径,比如用
/usr/bin/rsync而非rsync;检查方式:which rsync - 在脚本开头显式设置
cd /path/to/backup/script,避免相对路径失效 - 必要时在 crontab 条目里补全环境变量,例如:
PATH=/usr/local/bin:/usr/bin:/bin SHELL=/bin/bash 0 2 * * * /path/to/backup.sh - 重定向 stdout/stderr 到日志文件,方便排查:
0 2 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1
rsync 增量备份必须加 --delete 和 --exclude 才可控
不用 --delete,源删了的文件会永远留在目标端;不设 --exclude,临时文件、缓存、.git 目录可能被同步过去,既占空间又干扰恢复。
-
--delete要搭配--dry-run先试运行,确认将删哪些文件,避免误删 - 排除常见干扰项:
--exclude='.git/' --exclude='*.tmp' --exclude='/cache/',路径末尾斜杠表示目录 - 如果目标是远程主机,
--delete默认只删已同步过的文件,要删源不存在但目标多出的目录,得加--delete-excluded - 注意
rsync的路径结尾斜杠语义:/src/同步内容,/src同步整个目录——差一个斜杠,备份结构完全不同
备份脚本里用 date +%Y%m%d_%H%M 生成时间戳最稳妥
时间戳命名是恢复依据,也是清理旧备份的前提。用 $(date) 不加格式容易含空格或特殊字符,导致后续 find 或 rm 失败;用 %Y-%m-%d 中的短横线,在某些 shell 环境下会被误判为选项前缀。
- 固定格式推荐:
$(date +%Y%m%d_%H%M),输出如20240520_1430,纯字母数字,无歧义 - 生成备份目录时直接嵌入:
/backup/web_$(date +%Y%m%d_%H%M) - 清理 7 天前备份,用
find /backup -maxdepth 1 -name 'web_*' -mtime +7 -exec rm -rf {} ;,注意-mtime +7是“修改时间早于 7×24 小时前”,不是按命名日期算
本地备份完立刻 sync 再退出,否则断电可能丢最后一批数据
linux 默认启用 write-back 缓存,rsync 返回成功只代表数据进了内核页缓存,还没真正落盘。突然断电或重启,最后几 MB 可能丢失,而你完全不知道。
- 脚本末尾加一行:
sync,强制刷盘;对 SSD 可选更轻量的sync -f /backup/latest.tar.gz(仅刷指定文件) - 不要依赖
rsync --archive自带的同步行为——它不保证元数据+内容全部落盘 - 如果备份目标是挂载的 NFS 或 CIFS,
sync效果有限,需额外确认服务端是否开启sync模式(如 NFS 的syncmount option)
备份脚本真正的复杂点不在语法,而在路径上下文、环境隔离和落盘确认这三个地方。漏掉任意一个,都可能让“自动”变成“假装自动”。