How to read a file exclusively in perl?

I have a perl module that my library uses to collect scripts. These scripts are designed to scan my network, perform various tasks on my network devices, etc.

there are about 15 users , and I want only 1 person to run the collection script. if the second user is trying to run the script, then I want them to wait until the first person is complete.

The code below is just a test bed, so I can get it to work correctly before I enter it. I have a module with nap function. I just want one person to take a nap at a time.

 sub nap { my $program = shift; my @arr; #open file to check the queue open(IN, $path); @arr=<IN>; close IN; #if someone is in the queue, print it out! $|++; if (@arr > 0) { print @arr; } #keep checking the queue, once the queue is empty it my turn! while (@arr != 0) { open(IN, $path); @arr=<IN>; close IN; sleep 1; } #it my turn, put my name in the queue open(IN,">",$path); print IN "$ENV{USER},$program"; close IN; #take a nap! print "\n Sleep starting \n"; sleep 10; #I'm finished with my nap, clear the queue so other can go open(IN,">",$path); close IN; print "\nsleep over\n"; } 

My problem is that it works if 1 user waiting, but if 2 users are waiting, both of them are still taking a nap at the same time (after the completion of the first user)

Can I lock or block this file? I saw flock , but it appears no matter how you block it, the user can still read.

Is this even the right decision? or is there something more effective for these purposes?

+4
source share
2 answers

You can lock the DATA section of the file to lock the file itself, so you can (ab) use it to control exclusive access to this script.

I put this in the nap.pl library nap.pl :

 #!usr/bin/env perl use strict; use Fcntl qw(LOCK_EX LOCK_NB); sub nap { ## make sure this script only runs one copy of itself until ( flock DATA, LOCK_EX | LOCK_NB) { print "someone else has a lock\n"; sleep 5; } } __DATA__ This exists to allow the locking code at the beginning of the file to work. DO NOT REMOVE THESE LINES! 

Then I opened 3 terminals and launched them in each of them:

 #!/usr/bin/env perl use strict; do 'nap.pl'; &nap; print `ls /tmp/`; sleep 5; 

The first terminal immediately printed the contents of the / tmp directory. The second terminal printed โ€œsomeone else has a lock,โ€ and then after 5 seconds it printed the contents of / tmp. The third terminal printed โ€œsomeone else has a lockโ€ twice, once immediately, and then once after 5 seconds, and then printed the contents of / tmp /.

Be careful if you put this in your library, but you need to make sure things don't block unrelated routines.

I personally put the lock code in each script collection, and not in the library. Gathering a script is that you are actually trying to run only one instance. It seems that your name is inaccurate: you are not trying to read the file exclusively, you are trying to exclusively run the file.

+1
source

Your decision is wrong. First, you use a simple open that buffers read and write, which is difficult when you want multiple processes to communicate through a single file.

As you seem to already suspect, and as others have commented, on a Unix-like operating system, there is no (reasonable) way to force so that only one process can read from a file. In a sense, the right way to handle this is to use a lock file and only have the process of reading the lock from the data / connection file at the moment. Check perldoc -f flock to find out more about this.

File locks on Unix have some drawbacks, unfortunately. In particular, if the lock file is located on a network file system, they may be unreliable. For example, when using NFS, functional locks depend on all machines that mount the file system with the start of the lock daemon. One somewhat hacky but traditional way to get around this is to abuse mkdir semantics. If a group of processes tries to create a directory with the same name, it is guaranteed that only one of them will succeed (well, or nothing, but do not miss it yet). You can use this to synchronize processes. Before a process begins to do what needs to be done only one at a time, it tries to create a directory with a predefined name. If it succeeds, great, it can go on. If this fails, someone else is working, and he must wait. When the active process runs, it deletes the directory so that another process can create it.

In any case, the main message is that you need two file systems: one that your processes use to determine which one can work, and one for real work.

+4
source

All Articles