我正在运行一个脚本,该脚本从特定位置复制一个文件夹,如果它不存在(或不一致)。当我同时运行脚本2+次时,问题就出现了。当第一个脚本试图复制文件时,第二个脚本来了,并尝试同样的事情,导致混乱。我怎样才能避免这种情况呢?类似于系统级互斥锁。
我尝试了一个简单的测试与-w
,我手动复制文件夹,而文件夹正在复制我运行脚本:
use strict;
use warnings;
my $filename = 'd:\folder_to_copy';
if (-w $filename) {
print "i can write to the filen";
} else {
print "yikes, i can't write to the file!n";
}
当然不行,因为我仍然有对那个文件夹的写权限。我该如何检查文件夹是否在Perl
中复制或使用batch commands
?
听起来像是锁文件的工作。有无数的CPAN模块实现了锁文件,但它们中的大多数都不能在Windows上工作。根据CPAN测试人员的说法,以下是一些似乎支持Windows的应用程序:
- <罢工>文件:Lockfile罢工 罢工>
- <罢工>文件:TinyLock罢工 罢工>
- 文件::群::小
快速查看源代码后,我可以推荐的唯一模块是File::Flock::Tiny。
如果您需要一个系统范围的互斥锁,那么一个"技巧"是(ab)使用目录。命令mkdir
通常是原子的,可以工作,也可以不工作(如果目录已经存在)。
修改脚本如下:
my $mutex_dir = '/tmp/my-mutex-dir';
if ( mkdir $mutex_dir ) {
# run your copy-code here
# when finished:
rmdir $mutex_dir;
} else {
print "another instance is already running.n";
}
你唯一需要确保的是你被允许在/tmp
(或任何地方)创建一个目录。
注意,我故意让NOT首先测试$mutex_dir
是否存在,因为在if (not -d $mutex_dir)
和mkdir
之间,其他人可以创建目录,而mkdir
无论如何都会失败。所以只需调用mkdir
。如果成功了,你就可以做你的事了。完成后不要忘记移除$mutex_dir
。
这也是这种方法的缺点:如果复制代码崩溃并且脚本过早死亡,则不会删除目录。在这种情况下,nwellhof的答案中建议的锁文件机制可能会表现得更好,并自动解锁文件。
当第一个脚本试图复制文件时,第二个脚本来了尝试同样的事情导致混乱
最简单的方法是创建一个文件,如果另一个脚本实例正在运行,该文件将包含1。然后你可以在此基础上添加一个条件。
{local $/; open my $fh, "<", 'flag' or die $!; $data = <$fh>};
die "another instance of script is running" if $data == 1;
另一种方法是在脚本中设置环境变量,并在BEGIN
块中检查它。
您可以使用该包的windows互斥对象或windows信号量对象http://search.cpan.org/cjm/win32 - ipc - 1.11/
use Win32::Mutex;
use Digest::MD5 qw (md5_hex);
my $mutex = Win32::Mutex->new(0, md5_hex $filename);
if ($mutex) {
do_your_job();
$mutex->release
} else {
#fail...
}