我想并行运行多个 Bash shell 脚本。但是,我想避免竞争条件。 Unix 命令是什么确实我可以用于此目的的原子,以及如何使用它们?
答案1
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
这可确保“(”和“)”之间的代码一次仅由一个进程运行,并且该进程等待锁的时间不会太长。
答案2
如果lockfile
您的系统上未安装,mkdir
则将执行此操作:这是一个原子操作,如果目录已存在(只要您不添加命令-p
行开关),则会失败。
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
答案3
lockfile(1) 看起来是一个不错的候选者,但要注意它是程序邮件软件包,您可能尚未在计算机上安装该软件包。它是一个足够流行的软件包,如果尚未安装,则应该为您的系统打包它。我检查的四个系统中有三个有它,另一个有它可用。
使用它很简单:
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
# Do protected stuff here
echo Doing protected stuff...
# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1
fi
我给出的选项使其每秒重试一次,最多持续 15 秒。如果您希望它永远等待,请删除“-r”标志。
答案4
也许 lockfile 命令可以满足您的需要。
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock