我正在编写将并行运行的脚本,并将从同一文件中获取输入数据。这些脚本将打开输入文件,读取第一行,存储它以供进一步处理,最后从输入文件中删除此读取行。
现在的问题是,访问该文件的多个脚本可能会导致两个脚本同时访问输入文件并读取同一行的情况,这会产生两次处理行的不可接受的结果。
现在一个解决方案是在访问输入文件之前编写一个锁文件(.lock_input
),然后在释放输入文件时将其删除,但这个解决方案在我的情况下并不吸引人,因为有时NFS会降低网络速度随机通信,可能没有可靠的锁定。
另一种解决方案是放置进程锁而不是编写文件,这意味着访问输入文件的第一个脚本将启动一个名为lock_input的进程,其他脚本将ps -elf | grep lock_input
。如果它出现在进程列表中,它们将等待。这可能比写入NFS更快,但仍然不是完美的解决方案......
所以我的问题是:是否有任何bash命令(或其他脚本解释器)或我可以使用的服务,其行为类似于线程编程中用于同步的信号量或互斥锁?
谢谢。
小粗略的例子:
假设我们有input_file如下:
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
治疗脚本:TrScript.sh
#!/bin/bash
NbLines=$(cat input_file | wc -l)
while [ ! $NbLines = 0 ]
do
FirstLine=$(head -1 input_file)
echo "Hello World today is $FirstLine"
RemainingLines=$(expr $NbLines - 1 )
tail -n $RemainingLines input_file > tmp
mv tmp input_file
NbLines=$(cat input_file | wc -l)
done
主要剧本:
#! /bin/bash
./TrScript.sh &
./TrScript.sh &
./TrScript.sh &
wait
结果应为:
Hello World today is Monday Hello World today is Tuesday Hello World today is Wednesday Hello World today is Thursday Hello World today is Friday Hello World today is Saturday Hello World today is Sunday
答案 0 :(得分:15)
使用
line=`flock $lockfile -c "(gawk 'NR==1' < $infile ; gawk 'NR>1' < $infile > $infile.tmp ; mv $infile.tmp $infile)"`
用于访问要读取的文件。但这会使用文件锁。
gawk NR==1 < ...
打印输入的第一行
答案 1 :(得分:10)
我一直很喜欢 procmail 工具集中的 lockfile 程序(lockfile manpage的示例搜索结果)(大多数系统都应该可用)它可能默认不安装。)
它被设计用于锁定邮件假脱机文件,这些文件通常是通过NFS安装的,因此它可以在NFS上正常工作(尽可能多的东西)。
此外,只要您假设所有“工人”都在同一台机器上(假设您可以检查PID,这可能在PID最终换行时无法正常工作),您可以放锁在处理NFS服务器上托管的文件时,在其他本地目录(例如/ tmp)中进行文件。只要所有工作人员使用相同的锁定文件位置(以及锁定文件名与锁定路径名的一对一映射),它就可以正常工作。
答案 2 :(得分:1)
使用FLOM (Free LOck Manager)工具,您的主脚本可以变得如此简单:
#!/bin/bash
flom -- ./TrScript.sh &
flom -- ./TrScript.sh &
flom -- ./TrScript.sh &
wait
如果您在单个主机中运行脚本,请执行以下操作:
flom -A 224.0.0.1 -- ./TrScript.sh &
如果要在许多主机上分发脚本。此网址提供了一些使用示例:http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/