cron 与 flock 防重入
定时备份最常见的故障不是脚本写错,而是上一次还没跑完、下一次又启动了:两个进程同时读写同一个备份目标,产物互相覆盖,或者把存储 IO 挤到崩溃。flock 用文件锁把任务串行化,是给 cron 上的备份任务加的最便宜的一道保险。
基本信息
| 适用平台 | Linux 各发行版;cron 由 cronie / cron 提供,flock 来自 util-linux |
|---|---|
| 执行环境 | cron 的环境变量极简,脚本内应使用命令全路径并自行设置 PATH |
| 锁行为 | flock -n 拿不到锁立即退出(跳过本次);不加 -n 则等待锁释放 |
| 替代方案 | systemd timer 配合服务单元的 ExecStart 与超时设置,管理更清晰 |
典型使用场景
- 每日全量备份:数据量增长导致任务偶发超过间隔时,防止任务叠加
- 密集增量任务:每 15 分钟一次的快照任务,避免前一次未结束时重入
- 远程同步任务:链路慢导致 rsync 长时间运行,需要锁保护目标目录
- 多任务共享同一备份存储:用同一把锁串行化写操作,减少 IO 争抢
- 发布前后临时任务:临时备份脚本与例行任务互斥,避免产物命名冲突
crontab 示例与锁写法
crontab 示例与锁写法
# 每天 02:30 执行,持锁运行,锁被占用则跳过本次
30 2 * * * /usr/bin/flock -n /var/lock/backup.lock /usr/local/bin/backup.sh >> /var/log/backup-cron.log 2>&1
# 脚本内自行加锁(推荐,脚本手工执行时也受保护)
exec 9>/var/lock/backup.lock
flock -n 9 || { echo "$(date -Is) 已有任务在运行,跳过"; exit 0; }
# 跳过次数要计数并可告警,长期跳过说明窗口规划有问题两种锁行为对照
| 写法 | 行为 | 适用判断 |
|---|---|---|
| flock -n | 拿不到锁立即退出,本次跳过 | 任务间隔短、宁可跳过也不排队 |
| flock(不加 -n) | 等待锁释放后继续执行 | 任务必须完成、允许延后启动 |
| 锁文件位置 | 建议放 /var/lock 或专用于备份的目录 | 放在备份目标目录会被清理任务一起删掉 |
| 退出码 | 拿不到锁应返回 0 而非失败 | 返回非零会触发无意义的失败告警 |
cron 环境精简:脚本内使用命令全路径并自行设置 PATH,避免出现『手工跑正常、cron 跑失败』这类问题。
cron 的输出邮件通常无人阅读:把标准输出与错误重定向到日志文件,另外配置基于结果的告警,否则失败会长期无人发现。