简体   繁体   English

如何在perl中专门读取文件?

[英]How do I read a file exclusively in perl?

I have a perl module that my library of collecting scripts use. 我有一个perl模块,我的收集脚本库使用。 These scripts are for scanning my network, doing various tasks on my network devices, etc. 这些脚本用于扫描我的网络,在我的网络设备上执行各种任务等。

there are about 15 users and I only want 1 person at a time to run a collecting script. 大约有15 users ,我一次只想要1人来运行收集脚本。 if a second user tries to run the script, then I want them to wait until the first person is finished. 如果第二个用户尝试运行脚本,那么我希望他们等到第一个人完成。

The code below is just a test bed, so i can get it working correctly before i put it into production. 下面的代码只是一个测试床,所以我可以让它在投入生产之前正常工作。 I have a module that has a nap function. 我有一个具有nap功能的模块。 I only want one person to 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's my turn!
        while (@arr != 0) {
                open(IN, $path); @arr=<IN>; close IN;
                sleep 1;
        }

        #it's 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's can go
        open(IN,">",$path);
        close IN;
        print "\nsleep over\n";
}

my issue is it works if 1 user is waiting, but if 2 users are waiting, they both still take a nap at the same time ( after the first user finishes ) 我的问题是,如果1 user正在等待它是有效的,但如果2 users正在等待,他们仍然同时小睡(在第一个用户完成后)

can I lock or block this file? 我可以锁定或阻止此文件吗? I've seen flock but it appears no matter how you lock it, the user can still read. 我见过flock但看起来无论你如何锁定它,用户仍然可以阅读。

is this even a correct solution? 这是一个正确的解决方案吗? or is there something better used for these purposes? 还是有更好的东西用于这些目的?

Your solution is not correct. 您的解决方案不正确。 For one thing, you're using plain open , which buffers reads and writes, which causes complications when you want several processes to communicate via one file. 首先,您使用的是普通open ,它会缓冲读取和写入,当您希望多个进程通过一个文件进行通信时,这会导致复杂化。

As you seem to already suspect, and as others have commented, there is no (reasonable) way on a Unixlike operating system to forcibly make it so that only one process can read from a file. 正如您似乎已经怀疑的那样,并且正如其他人所评论的那样,在Unix类操作系统上没有(合理的)强制方式使其只有一个进程可以从文件中读取。 The in some sense correct way to handle it is to use a lock file, and only have the process currently holding the lock read from the data/communication file. 在某种意义上,处理它的正确方法是使用锁定文件,并且只有当前持有锁的进程从数据/通信文件中读取。 Check perldoc -f flock for details on that. 检查perldoc -f flock以获取详细信息。

File locks on Unix does have some drawbacks, unfortunately. 不幸的是,Unix上的文件锁确实有一些缺点。 Particularly if the lock file resides on a network filesystem they can be unreliable. 特别是如果锁定文件驻留在网络文件系统上,则它们可能不可靠。 With NFS, for example, functional locks depend on all machines mounting the filesystem having a lock daemon running. 例如,使用NFS,功能锁取决于安装运行锁守护程序的文件系统的所有计算机。 One somewhat hacky but traditional way to work around this is to abuse the semantics of mkdir . 一种有点hacky但传统的解决方法是滥用mkdir的语义。 If a bunch of processes all try to create a directory with the same name, it is guaranteed that only one of them will succeed (well, or none, but let's skip that for now). 如果一堆进程都试图创建一个具有相同名称的目录,那么可以保证只有其中一个会成功(好吧,或者没有,但现在让我们跳过它)。 You can use that for synchronizing the processes. 您可以使用它来同步进程。 Before a process starts doing the thing that only one at a time should be doing, it tries to create a directory with a pre-determined name. 在进程开始执行只能一次执行的操作之前,它会尝试创建具有预定名称的目录。 If it succeeds, fine, it can go on. 如果成功,那很好,它可以继续下去。 If it fails, someone else is already working and it has to wait. 如果它失败了,其他人已经在工作,它必须等待。 When the active process is done working, it removes the directory so another process can then succeed in creating it. 当活动进程完成工作时,它将删除目录,以便另一个进程可以成功创建它。

Anyway, the basic message is that you need two filesystem thingies: one that your processes use to determine which one of them may work, and one for the actual work. 无论如何,基本的信息是你需要两个文件系统的东西:一个是你的进程用来确定哪一个可以工作,一个是实际的工作。

You can lock the DATA section of a file to lock the file itself, so you can (ab)use that to control exclusive access to that script. 您可以锁定文件的DATA部分以锁定文件本身,因此您可以(ab)使用它来控制对该脚本的独占访问。

I put this in a library file nap.pl : 我把它放在一个库文件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 ran this in each one: 然后我打开了3个终端并在每个终端中运行:

#!/usr/bin/env perl
use strict;
do 'nap.pl';

&nap;
print `ls /tmp/`;
sleep 5;

The first terminal printed the contents of my /tmp directory immediately. 第一个终端立即打印了我的/ tmp目录的内容。 The second terminal printed "someone else has a lock" and then after 5 seconds, it printed the contents of /tmp. 第二个终端打印“别人有锁”,然后在5秒后打印出/ 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/. 第三个终端打印“别人有锁” 两次 ,一次立即打印,然后一次打印5秒,然后打印/ tmp /的内容。

Be careful about where you put this in your library though, you'd want to make sure that things aren't locking unrelated subroutines. 但要注意将它放在库中的位置,你要确保没有锁定不相关的子程序。

I would personally put the lock code in each collecting script, not in the library. 我个人会把锁码放在每个收集脚本中,而不是放在库中。 The collecting script is what you're actually trying to only run one instance of. 收集脚本是你实际上只想运行一个实例的。 It seems your title isn't accurate: you're not trying to exclusively read a file, you're trying to exclusively run a file. 看起来你的标题不准确:你不是试图专门读取文件,而是试图专门运行文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM