2

我正在运行一个脚本,如果它不存在(或不一致),它会从特定位置复制一个文件夹。当我同时运行脚本 2 次以上时,就会出现问题。当第一个脚本试图复制文件时,第二个脚本来尝试同样的事情,导致一团糟。我怎样才能避免这种情况?类似于系统范围的互斥锁。

我尝试了一个简单的测试-w,我手动复制了文件夹,并在复制文件夹时运行脚本:

use strict;
use warnings;

my $filename = 'd:\\folder_to_copy';
if (-w $filename) {
  print "i can write to the file\n";
} else {
  print "yikes, i can't write to the file!\n";
}

当然这行不通,因为我仍然拥有对该文件夹的写入权限。关于如何检查文件夹是否被复制Perl或使用的任何想法batch commands

4

4 回答 4

7

听起来像是锁定文件的工作。有无数的 CPAN 模块实现了锁定文件,但大多数都不能在 Windows 上运行。根据 CPAN 测试人员的说法,这里有一些似乎支持 Windows:

在快速查看源代码后,我唯一推荐的模块是File::Flock::Tiny。其他人看起来很活泼。

于 2016-10-13T12:52:34.373 回答
4

如果您需要一个系统范围的互斥锁,那么一个“技巧”就是(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(或任何地方)创建目录。

请注意,我故意首先测试是否存在,$mutex_dir因为在if (not -d $mutex_dir)mkdir其他人之间可以创建目录并且mkdir无论如何都会失败。所以只需调用mkdir. 如果它有效,那么你可以做你的事情。完成后不要忘记删除$mutex_dir

这也是这种方法的缺点:如果您的复制代码崩溃并且脚本过早死亡,那么该目录不会被删除。据推测, nwellnhof 的答案中建议的锁定文件机制在这种情况下表现得更好,并自动解锁文件。

于 2016-10-13T12:50:55.580 回答
3

当第一个脚本试图复制文件时,第二个脚本来尝试同样的事情,导致一团糟

如果另一个脚本实例正在运行,最简单的方法是创建一个包含 1 的文件。然后,您可以在此基础上添加条件。

{local $/; open my $fh, "<", 'flag' or die $!; $data = <$fh>};
die "another instance of script is running" if $data == 1;

另一种方法是在脚本中设置一个环境变量并在BEGIN块中检查它。

于 2016-10-13T12:40:19.610 回答
1

您可以使用包 http://search.cpan.org/~cjm/Win32-IPC-1.11/的 Windows-Mutex 或 Windows-Semaphore Objects

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...
}
于 2016-10-18T14:51:38.103 回答