Обнаружение того, что файлы копируются в папку

Я запускаю скрипт, который копирует одну папку из определенного места, если она не существует (или не соответствует). Проблема возникает, когда я запускаю сценарий 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 ответа

Решение

Похоже, работа для файла блокировки. Существует множество модулей CPAN, которые реализуют файлы блокировки, но большинство из них не работают в Windows. Вот некоторые из них, которые, по-видимому, поддерживают Windows в соответствии с тестерами CPAN:

После быстрого просмотра исходного кода, единственный модуль, который я могу порекомендовать, это 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 (или где угодно).

Обратите внимание, что я специально не проверяю в первую очередь на наличие $mutex_dir потому что между if (not -d $mutex_dir) и mkdir кто-то еще может создать каталог и mkdir все равно потерпит неудачу. Так просто позвони mkdir, Если это сработало, тогда вы можете делать свои вещи Не забудьте удалить $mutex_dir после того, как вы сделали

Это также недостаток этого подхода: если ваш код копирования падает, а сценарий преждевременно умирает, то каталог не удаляется. Предположительно механизм блокировки файла, предложенный в ответе nwellnhof, в этом случае работает лучше и автоматически разблокирует файл.

Поскольку первый скрипт пытается скопировать файлы, второй приходит и пытается то же самое, что приводит к путанице

Самый простой подход - создать файл, который будет содержать 1, если запущен другой экземпляр скрипта. Затем вы можете добавить условное на основе этого.

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

Другой подход заключается в том, чтобы установить переменную окружения в скрипте и проверить ее в BEGIN блок.

Вы можете использовать объекты Windows-Mutex или 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...
}
Другие вопросы по тегам