备份脚本用 flock -n 加锁防止重入,某次脚本被 kill 之后,之后每天 02:00 的任务都直接退出,日志里只有一行 another instance is running。

一开始怀疑是「锁文件放在 /var/run 下,被 systemd-tmpfiles 清理后权限变了」,查了一圈,方向不对。

排查方向其实有限,先把可能性排一排。flock 的锁跟着文件描述符走,进程被杀后锁其实会释放,残留的是 pid 文件判断逻辑。少数情况下是脚本里额外写了 pid 文件存在就退出,pid 文件没人清。

还有一种情况,cron 启动的子进程继承了锁的文件描述符,脚本退出后锁还被孙进程持有。

上来先确认锁到底被谁持有

fuser -v /var/lock/backup.lock 2>&1

然后检查脚本里是否有额外的 pid 判断

grep -nE 'flock|pid' /opt/scripts/backup.sh

手工跑一次看是否还报占用

flock -n /var/lock/backup.lock -c 'echo ok'

剩下的就是清理残留并让 cron 再触发一次

rm -f /var/run/backup.pid && /opt/scripts/backup.sh

恢复的判定其实很直接。flock 测试返回 ok,cron 触发的备份任务正常执行,日志里出现本次备份的开始和结束时间戳。

这里还有个坑。flock 本身不需要清理,真正要清的是自己写的 pid 文件;子进程继承描述符导致锁不释放时,用 flock -o 或者把命令放进子 shell 里跑。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189