如何从多个脚本同步(锁定/解锁)访问bash中的文件?

如何从多个脚本同步(锁定/解锁)访问bash中的文件?,bash,synchronization,locking,Bash,Synchronization,Locking,我正在编写并行运行的脚本,这些脚本将从同一个文件中获取它们的输入数据。这些脚本将打开输入文件,读取第一行,将其存储以供进一步处理,最后从输入文件中删除该读取行 现在的问题是,多个脚本访问该文件可能会导致两个脚本同时访问输入文件并读取同一行,从而产生两次处理该行的不可接受结果 现在,一种解决方案是写入锁定文件。在访问输入文件之前锁定输入,然后在释放输入文件时将其删除,但在我的情况下,这种解决方案并不吸引人,因为有时NFS会随机减慢网络通信,并且可能没有可靠的锁定 另一种解决方案是放置进程锁而不是写

我正在编写并行运行的脚本,这些脚本将从同一个文件中获取它们的输入数据。这些脚本将打开输入文件,读取第一行,将其存储以供进一步处理,最后从输入文件中删除该读取行

现在的问题是,多个脚本访问该文件可能会导致两个脚本同时访问输入文件并读取同一行,从而产生两次处理该行的不可接受结果

现在,一种解决方案是写入锁定文件。在访问输入文件之前锁定输入,然后在释放输入文件时将其删除,但在我的情况下,这种解决方案并不吸引人,因为有时NFS会随机减慢网络通信,并且可能没有可靠的锁定

另一种解决方案是放置进程锁而不是写入文件,这意味着访问输入文件的第一个脚本将启动一个名为lock|u input的进程,其他脚本将启动ps-elf | grep lock|u input。如果进程列表中有,他们将等待。这可能比写入NFS更快,但仍然不是完美的解决方案

所以我的问题是:我是否可以使用任何bash命令或其他脚本解释器或服务,它们的行为类似于线程编程中用于同步的信号量或互斥锁

多谢各位

简单的小例子:

假设我们有如下输入_文件:

Monday Tuesday Wednesday Thursday Friday Saturday Sunday 主脚本:

#! /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 我一直很喜欢procmail工具集中的lockfile程序示例搜索结果应该在大多数系统上都可用,尽管默认情况下可能不会安装它

它被设计用来锁定邮件假脱机文件,这些文件是?通常通过NFS安装,因此它可以在NFS上正常工作

此外,只要您通过假设您可以检查PIDs(PIDs最终包装时可能无法正常工作)来假设所有“工作人员”都在同一台机器上,您就可以在处理NFS服务器上托管的文件时将锁定文件放在其他一些本地目录中,例如/tmp。只要所有工作进程使用相同的锁文件位置,并将锁文件名一对一映射到锁定的路径名,就可以正常工作。

使用

line=`flock $lockfile -c "(gawk 'NR==1' < $infile ; gawk 'NR>1' < $infile > $infile.tmp ; mv $infile.tmp $infile)"`
用于访问要从中读取的文件。不过,这会使用文件锁

gawk NR==1 < ...
使用工具打印输入的第一行

,您的主脚本可以变得非常简单:

#!/bin/bash  
flom -- ./TrScript.sh &  
flom -- ./TrScript.sh &  
flom -- ./TrScript.sh &  
wait
如果在单个主机内运行脚本,请执行以下操作:

flom -A 224.0.0.1 -- ./TrScript.sh &

如果要在多台主机上分发脚本。以下URL提供了一些使用示例:

此处交叉发布:lockfile的可能副本看起来不错。但你的另一半答案是有缺陷的,可能会导致冲突。Dennis Williamson的第一个链接似乎是一个没有非标准命令的工作解决方案。完美。看到你使用flock命令暗示我要做man flock,这正是我所需要的。+1 flock,需要更多的投票。例如:flock-n您的锁定文件-c rsync-rl/media/dir1/media/dir2
flom -A 224.0.0.1 -- ./TrScript.sh &