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