crontab 备份不生效主因是环境差异:需用绝对路径、显式调用 bash、重定向日志;rsync 增量备份须用 --dry-run 预览、--delete-after 保安全;时间戳变量要加双引号;远程传输需免密 ssh 和断点续传;数据库备份须应用层快照。

crontab 定时执行备份脚本总不生效?检查这几点
不是脚本写得不对,而是 crontab 的运行环境和你终端里根本不是一回事。它默认没有 $PATH,不读取 ~/.bashrc,连 which rsync 都可能返回空。
- 所有命令路径必须写绝对路径:用
which rsync、which tar查出真实路径,比如/usr/bin/rsync,别写rsync - 脚本开头加
#!/bin/bash,并在 crontab 里显式调用/bin/bash /path/to/backup.sh - 重定向输出到日志:
0 2 * * * /bin/bash /opt/backup.sh >> /var/log/backup.log 2>&1,否则失败了你也看不到错误 - 测试时先用
run-parts或手动执行一遍脚本,确认权限(chmod +x)和路径都 OK
rsync 增量备份怎么避免删错文件?
rsync 的 --delete 很危险——它只看「源端没有但目标端有」就删,一旦源路径配错或挂载失败,目标备份目录可能被清空。
- 永远先加
--dry-run看预览:rsync -av --dry-run --delete /data/ /backup/data/ - 加
--delete-after而非--delete,确保同步完成后再删,降低中间态风险 - 对关键目录加
--exclude,比如排除临时文件:--exclude='*.tmp' --exclude='/cache/' - 目标目录末尾的斜杠不能少:
/backup/data/是“进目录”,/backup/data是“覆写目录本身”,差一个字符行为完全不同
备份文件怎么带时间戳又不搞乱命名逻辑?
用 date 生成时间戳时,如果没引号包裹,shell 会把带空格的结果拆成多个参数,导致 tar 报错 tar: Cowardly refusing to create an empty archive。
- 时间戳变量必须用双引号:
TS="$(date +%Y%m%d_%H%M%S)",然后用"backup_${TS}.tar.gz" - 避免在文件名里用冒号(
:),某些文件系统不支持;用下划线或短横线更稳妥 - 如果要保留最近 7 天备份,别用
find /backup -name "*.tar.gz" -mtime +7 -delete直接删——-mtime看的是修改时间,而 tar 包解压后内容时间可能更早;改用-ctime或直接按文件名解析日期
本地备份够用吗?scp 传远程总断连怎么办
用 scp 在 crontab 里传备份,最常见问题是 SSH 连接被中断或需要交互输密码——crontab 不支持 tty,ssh 会卡住或报 Pseudo-terminal will not be allocated。
- 必须配置免密登录:用
ssh-keygen -t ed25519生成密钥,ssh-copy-id user@remote推过去,禁用密码登录 - 加超时和重试:用
timeout 600 scp -o ConnectTimeout=30 -o ServerAliveInterval=60 backup.tar.gz user@remote:/backup/ - 更稳的方式是换
rsync over ssh:rsync -avz -e "ssh -o StrictHostKeyChecking=no" /local/ user@remote:/remote/,自带断点续传 - 远程磁盘空间不足时,
scp不报明确错误,只会静默失败;建议传完加一步ssh user@remote 'df -h /backup | tail -1'检查剩余空间
真正麻烦的不是调度或传输,而是备份一致性——比如 MySQL 正在写数据时直接 tar /var/lib/mysql,大概率恢复不了。这类场景得配合 mysqldump 或 mysqlbackup 做应用层快照,不是加个 crontab 就算完事。










