Detecting that files are being copied in a folder

六月ゝ 毕业季﹏ 提交于 2019-12-22 14:09:10

问题


I am running a script which copies one folder from a specific location if it does not exist( or is not consistent). The problems appears when I run concurently the script 2+ times. As the first script is trying to copy the files, the second comes and tryes the same thing resulting in a mess. How could I avoid this situation? Something like system wide mutex.

I tryed a simple test with -w, I manually copied the folder and while the folder was copying I run the script:

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";
}

Of course this won't work, cuz I still have write acces to that folder. Any ideea of how could I check if the folder is being copied in Perl or usingbatch commands?


回答1:


Sounds like a job for a lock file. There are myriads of CPAN modules that implement lock files, but most of them don't work on Windows. Here are a few that seem to support Windows according to CPAN Testers:

  • File::Lockfile
  • File::TinyLock
  • File::Flock::Tiny

After having a quick view at the source code, the only module I can recommend is File::Flock::Tiny. The others seem racy.




回答2:


If you need a systemwide mutex, then one "trick" is to (ab)use a directory. The command mkdir is usually atomic and either works or doesn't (if the directory already exists).

Change your script as follows:

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";
}

The only thing you need to make sure is that you're allowed to create a directory in /tmp (or wherever).

Note that I intentionally do NOT firstly test for the existence of $mutex_dir because between the if (not -d $mutex_dir) and the mkdir someone else could create the directory and the mkdir would fail anyway. So simply call mkdir. If it worked then you can do your stuff. Don't forget to remove the $mutex_dir after you're done.

That's also the downside of this approach: If your copy-code crashes and the script prematurely dies then the directory isn't deleted. Presumably the lock file mechanism suggested in nwellnhof's answer behaves better in that case and automatically unlocks the file.




回答3:


As the first script is trying to copy the files, the second comes and tries the same thing resulting in a mess

A simplest approach would be to create a file which will contain 1 if another instance of script is running. Then you can add a conditional based on that.

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

Another approach would be to set an environment variable within the script and check it in BEGIN block.




回答4:


You can use Windows-Mutex or Windows-Semaphore Objects of the package 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...
}


来源:https://stackoverflow.com/questions/40021131/detecting-that-files-are-being-copied-in-a-folder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!