有时您必须确保同一时间只有一个 shell 脚本实例正在运行。
例如,通过 crond 执行的 cron 作业本身不提供锁定(例如默认的 Solaris crond)。
实现锁定的常见模式是这样的代码:
#!/bin/sh
LOCK=/var/tmp/mylock
if [ -f $LOCK ]; then # 'test' -> race begin
echo Job is already running\!
exit 6
fi
touch $LOCK # 'set' -> race end
# do some work
rm $LOCK
Run Code Online (Sandbox Code Playgroud)
当然,这样的代码有竞争条件。有一个时间窗口,其中两个实例的执行都可以在第 3 行之后才能访问$LOCK文件。
对于 cron 作业,这通常不是问题,因为两次调用之间有几分钟的间隔。
但是事情可能会出错——例如,当锁定文件在 NFS 服务器上时——挂起。在这种情况下,多个 cron 作业可以在第 3 行阻塞并排队。如果NFS服务器再次处于活动状态,那么你已经惊群并行运行的作业。
在网上搜索我发现工具lockrun似乎是该问题的一个很好的解决方案。使用它,您可以运行一个需要像这样锁定的脚本:
$ lockrun --lockfile=/var/tmp/mylock myscript.sh
Run Code Online (Sandbox Code Playgroud)
您可以将其放在包装器中或从您的 crontab 中使用它。
lockf()如果可用,它使用(POSIX) 并回退到flock()(BSD)。并且lockf()对 NFS …