首页/系统/Linux 运维命令速查/flock 防任务重入
定时任务与计划50 条

flock 防任务重入

上一次没跑完、下一次又触发会造成数据错乱;用 flock 对任务加锁,-n 拿不到锁立即退出,是 cron 防叠加的标准做法。

Linux 运维命令速查系统更新于 2026-10-13

flock 是什么

定时任务最常见的生产事故是重入:上一次任务还没跑完,下一次触发又启动一个实例,两个进程同时操作同一份数据,结果互相覆盖或产生重复记录。flock 用文件锁解决这个问题:任务启动时先对锁文件加排他锁,拿不到锁说明上一个实例还在运行。加上 -n 表示非阻塞,立即失败退出,这是 cron 防叠加的标准做法;不加 -n 会一直等待,相当于把任务排队执行,通常不是想要的行为。

基本信息

适用平台Linux(util-linux 的 flock 命令;也可在脚本语言里调用同名系统调用)
命令语法flock [-n] [-w 秒] 锁文件 命令
常用选项-n 非阻塞,拿不到锁立即退出 -w 等待指定秒数 -x 排他锁(默认) -s 共享锁 -o 运行前关闭锁描述符
所属util-linux
锁文件位置/var/lock 或 /run/lock,属于 tmpfs,重启后自动清空

典型使用场景

  • 防任务叠加:备份、同步、报表这类耗时任务,避免两次执行同时写同一份数据
  • 防重复启动:脚本被 cron 与手工同时触发时,只允许一个实例运行
  • 多机协调:多台机器通过共享存储上的同一锁文件做粗粒度互斥
  • 保护资源:限制同一任务的并发数,避免打满磁盘 IO 或数据库连接
  • 排障分析:用 fuser 或 lsof 查看当前是谁持有锁

两种用法

两种用法
# crontab 一行写法:拿不到锁直接跳过
*/5 * * * * /usr/bin/flock -n /var/lock/sync.lock /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

#!/bin/bash
# 脚本内写法:用文件描述符 9 持锁,整段任务都在锁内
exec 9>/var/lock/backup.lock
flock -n 9 || { echo "another instance running, skip"; exit 0; }
# ... 任务主体 ...

fuser /var/lock/sync.lock     # 查看当前持有锁的进程

几种行为对照

用法拿不到锁时的表现适用场景
flock -n立即退出,退出码非 0cron 防叠加,最常用
flock -w 30最多等 30 秒,超时后退出希望任务短暂排队而不是直接跳过
flock 不加选项一直阻塞等待锁释放交互式场景,cron 里会导致任务堆积
flock -o先关闭锁文件描述符再执行命令避免被调命令派生的子进程继续持有锁
flock 的互斥范围只是「同一个锁文件路径」。路径写得不一致(相对路径与绝对路径、软链接指向不同文件)就等于没加锁,脚本里一律使用固定的绝对路径。
进程被 kill -9 时内核会自动释放锁,但被中断留下的半成品数据需要脚本自己处理。防重入不能替代幂等设计,任务本身要能安全重跑。

易错点

  • 锁路径前后不一致,看似加了锁实际互斥失效,这是防重入失效最常见的原因
  • flock -n 拿不到锁会以非 0 退出,脚本未处理时监控会误报任务失败,通常应在跳过分支里显式 exit 0 并记日志
  • 锁文件放在 /tmp,被系统清理器删除后锁失效,应使用 /var/lock 或 /run/lock
  • 只在 crontab 层加锁,而脚本还会被手工或接口触发时,应从脚本入口统一加锁

数据来源与参考

  • man 1 flock
  • RHEL 文档:cron 任务防重复执行实践

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌