用 flock 挡住重叠的定时脚本
很多运维脚本是用 cron 每分钟或每五分钟跑一次的。脚本本身不长,但只要某一次卡住,比如在等数据库、等磁盘或者等下游接口,下一次 cron 就会再起一个进程。两个进程同时写同一份报表、同时删同一批临时文件,结果比没跑更难查。
flock 是 util-linux 里的小工具,专门解决这件事。它靠内核的文件锁:谁先拿到锁,谁执行;后来的进程可以选择立刻退出,或者排队等待。
一、先给脚本一个固定的锁文件
锁文件只是一个普通文件,内容不重要,路径要固定。例如把备份脚本交给 flock:
flock -n /var/lock/backup.lock /opt/jobs/backup
参数 -n 表示非阻塞。锁已被占用时,flock 马上返回非零,不会再启动备份脚本。写进 crontab 时,把分钟字段设为每五分钟,命令同样是上面这一行,只是前面加上调度时间。
这样即使上一次还在跑,新的一次也会安静退出。把这次非零退出记进自己的日志,比让两个实例互相覆盖更清楚。
二、不要把锁放在会被清空的目录
有人把锁放在临时目录。部分系统会定期清理长时间没有被打开的临时文件,锁文件一旦被删,后来的进程会新建一个同名文件,两把锁就不再互斥。系统的 lock 目录更合适,它多半位于内存文件系统,重启后自然清空,正好符合进程没了、锁就该消失的语义。还要注意目录对运行脚本的用户可写,否则 flock 会因为打不开文件而失败,定时任务看起来像根本没执行。
三、分清锁文件和脚本稍后打开的业务文件
flock 锁的是你在命令里指定的那个锁文件,不是脚本里面再打开的报表或临时目录。两个任务如果必须互斥,就共用同一把锁;如果可以并行,就各用各的锁文件。给每类任务单独一把锁,比全局只留一把锁更不容易误伤无关作业。
四、用两条命令确认锁真的生效
开两个终端。一边执行 flock /var/lock/backup.lock sleep 30,另一边马上执行 flock -n /var/lock/backup.lock echo ok。第二条应当立刻失败,而不是打印 ok。等三十秒后再试,应当成功并打印 ok。这一步只验证锁的行为,不改任何业务数据。
定时任务重叠,表面上像偶发的脏数据,根因常常只是没有互斥。先加上 flock,再去优化脚本本身,排查顺序会顺很多。
- 点赞
- 收藏
- 关注作者
评论(0)