#!/bin/bash
if [ ! -f numbers ]; then echo 0 > numbers; fi
count=0
touch numbers
echo $count > numbers
while [[ $count != 100 ]]; do
if ln numbers numbers.lock
then
count=`expr $count + 1`
n=`tail -1 numbers`
expr $n + 1 >> numbers
rm numbers.lock
fi
done
我可以做些什么来避免count=`expr $count + 1`
和n=`tail -1 numbers`
的竞争条件,这样当我同时运行两个脚本时,它只会变为100,而不是200。我在多个网站上进行了研究,但没有一个庞大的功能,没有简明的答案。
答案 0 :(得分:3)
您已经使用锁定文件安全地避开了实际的竞争条件。您所描述的问题可以通过两种方式避免。
(1)将锁定文件移到主循环之外,这样程序的两个实例就不能同时运行它们的主循环。如果一个正在运行,另一个必须等到它完成,然后开始替换输出文件。
#!/bin/bash
while true; do
if ! ln numbers numbers.lock
then
sleep 1
else
if [ ! -f numbers ]; then echo 0 > numbers; fi
count=0
touch numbers
#echo $count > numbers # needless, isn't it?
while [[ $count != 100 ]]; do
count=`expr $count + 1`
n=`tail -1 numbers`
expr $n + 1 >> numbers
rm numbers.lock
done
break
fi
done
(2)通过检查文件的内容,使两个实例合作。换句话说,强制它们在数字达到100时停止循环,而不管有多少其他进程正在写入此文件。 (我猜当有超过100个实例在运行时会出现一个iffy的情况。)
#!/bin/bash
# FIXME: should properly lock here, too
if [ ! -f numbers ]; then echo 0 > numbers; fi
n=0
touch numbers
while [[ $n -lt 100 ]]; do
if ln numbers numbers.lock
then
n=$(expr $(tail -1 numbers) + 1 | tee numbers)
rm numbers.lock
fi
done
根据您的要求,您可能希望脚本在脚本的新实例启动时破坏文件中的任何先前值,但如果不是,则echo 0 > numbers
应由锁定文件管理,太