首页 > 解决方案 > 创建锁定文件时防止竞争条件

问题描述

我的脚本不能同时运行多次。因此它会创建一个锁定文件,并在退出之前将其删除。它在开始工作之前检查锁定文件是否不存在。

一种非常常见的锁定方法是这样的

function setupLockFile() {
  if (set -o noclobber; echo "lock" > "$lockfile") 2>/dev/null; then
    trap "rm -f $lockfile; exit $?" INT TERM EXIT
  else
    echo "Script running... exiting!" 
    exit 1
  fi
}

但是有一个竞争条件 -if如果文件不存在,则创建文件,并且脚本可以在trap定义之前终止。然后锁定文件不会被删除。

那么什么是安全的方法呢?

标签: linuxbashshelllocking

解决方案


这不是一场比赛——这是对失败的适应力。在脚本在删除文件之前就死掉的情况下,您需要手动清理。

尝试自动化此清理的常用方法是从任何现有文件中读取 PID,测试该进程是否仍然存在,如果不存在则基本上忽略它的存在。不幸的是,如果没有一个原子比较和设置操作,这并不是一件容易正确的事情,因为它引入了一个新的竞争,在 PID 的读取和其他人试图忽略它的存在之间。

查看这个问题,了解有关仅使用文件系统进行锁定的更多想法。

我的建议是将锁定文件存储在临时文件系统上(/var/run通常是 tmpfs 以允许 pidfile 在重新启动时安全消失),以便在重新启动后自行修复,或者让脚本举手并要求手动干预。可靠地处理每个失败案例会增加复杂性,因此可能会比寻求帮助的人带来更多的失败概率。

复杂性不仅在今天,而且在代码的整个生命周期中都是如此。完成后可能是正确的,但下一个人会打破它吗?


推荐阅读