通过锁定文件

时间:2017-01-26 11:52:45

标签: perl

我的一个脚本是安装组件。当并行运行时,同一个脚本会尝试安装相同的组件,因此我考虑通过在安装脚本时锁定文件来同步进程,并在其他脚本安装时等待。

代码如下所示:

# this will create a file handler on a file from TEMP dir with the
# name of the component; if it doesn't exist in TEMP dir, it will create it

my $file = $ENV{"TEMP"}. "\\" . $componentName;
open (my $fh, ">", "$file") or die "Couldn't open file!";

# this will apply an exclusive lock  meaning that if another process
# already locked the file, it will wait until the lock is removed

flock($fh, 2) or die "Failed to lock the file";

# install the component..

# closing the file handle automatically removes the lock
close $fh;

我担心脚本锁定文件并开始安装并且第二个脚本出现并尝试在锁定文件上创建文件句柄时的情况。我没有看到任何错误,但我不想错过任何东西。

这会有问题吗?

2 个答案:

答案 0 :(得分:4)

要记住的重要事项是 - ' open'在任何一种情况下都可以使用,因为它不会测试锁。它是flock操作,在锁被释放之前将阻塞。

这应该可以正常工作,虽然一旦锁 发布 - 您可能想检查是否仍然需要运行安装,除非您真的不关心这样做两次 - 例如如果脚本的其余部分使用/依赖它。

此外 - 是否有其他来源安装'那不是你的脚本,可能导致同样的问题吗?锁定是一种咨询。

在您的计划中,这也将是一种风格改进:

  • 测试$ENV{'TEMP'}以确定它是否存在,并且默认(或失败),如果它不存在。
  • use Fcntl qw ( :flock );因为您可以flock ( $fh, LOCK_EX );明确表示您正在进行独占锁定。
  • 您似乎使用\\作为文件分隔符。出于便携性的原因,如果您使用File::Spec之类的东西来做这件事,那可能会更好。
  • 您可以使用LOCK_NB进行非阻止:flock ( $fh, LOCK_EX | LOCK_NB ),然后只要它被锁定就跳过。

答案 1 :(得分:2)

锁定不会阻止文件被打开或修改;它可以防止它被锁定。

这意味着void setup(){ size(640,360); } int scl = 20; void draw(){ background(250); drawGrid(scl); makeObject(0,0,20,20); } void drawGrid(float size){ for(int v=0;v<640/20;v++){ for(int h=0;h<360/20;h++){ rect(h*size,v*size,size,size); } } } void makeObject(int obX,int obY,int obHeight,int obWidth){ this.x = obX; this.y = obY; this.obH = obHeight; this.obW = obWidth; rect(this.x,this.y,this.obH,this.obW); } 不会失败,即使文件被锁定并仍在使用,它也会破坏文件。如果锁意味着保护对文件的访问(即,如果程序实际写入锁定的文件),您希望使用open来避免文件已经存在 [1]

sysopen

use Fcntl qw( LOCK_EX O_CREAT O_WRONLY );

# Open the file without clobbering it, creating it if necessary.
sysopen(my $fh, $qfn, O_WRONLY | O_CREAT)
   or die($!);

# Wait for the file to become available.
flock($fh, LOCK_EX)
   or die($!);

truncate($fh, 0)
   or die($!);

...
  1. 如果您不介意将文件置于追加模式,也可以使用use Fcntl qw( LOCK_EX LOCK_NB O_CREAT O_WRONLY ); # Open the file without clobbering it, creating it if necessary. sysopen(my $fh, $qfn, O_WRONLY | O_CREAT) or die($!); # Check if the file is locked. flock($fh, LOCK_EX | LOCK_NB) or die($!{EWOULDBLOCK} ? "File already in use\n" : $!); truncate($fh, 0) or die($!); ...