繁体   English   中英

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

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

我有一个perl模块,我的收集脚本库使用。 这些脚本用于扫描我的网络,在我的网络设备上执行各种任务等。

大约有15 users ,我一次只想要1人来运行收集脚本。 如果第二个用户尝试运行脚本,那么我希望他们等到第一个人完成。

下面的代码只是一个测试床,所以我可以让它在投入生产之前正常工作。 我有一个具有nap功能的模块。 我只希望一个人一次打盹。

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

我的问题是,如果1 user正在等待它是有效的,但如果2 users正在等待,他们仍然同时小睡(在第一个用户完成后)

我可以锁定或阻止此文件吗? 我见过flock但看起来无论你如何锁定它,用户仍然可以阅读。

这是一个正确的解决方案吗? 还是有更好的东西用于这些目的?

您的解决方案不正确。 首先,您使用的是普通open ,它会缓冲读取和写入,当您希望多个进程通过一个文件进行通信时,这会导致复杂化。

正如您似乎已经怀疑的那样,并且正如其他人所评论的那样,在Unix类操作系统上没有(合理的)强制方式使其只有一个进程可以从文件中读取。 在某种意义上,处理它的正确方法是使用锁定文件,并且只有当前持有锁的进程从数据/通信文件中读取。 检查perldoc -f flock以获取详细信息。

不幸的是,Unix上的文件锁确实有一些缺点。 特别是如果锁定文件驻留在网络文件系统上,则它们可能不可靠。 例如,使用NFS,功能锁取决于安装运行锁守护程序的文件系统的所有计算机。 一种有点hacky但传统的解决方法是滥用mkdir的语义。 如果一堆进程都试图创建一个具有相同名称的目录,那么可以保证只有其中一个会成功(好吧,或者没有,但现在让我们跳过它)。 您可以使用它来同步进程。 在进程开始执行只能一次执行的操作之前,它会尝试创建具有预定名称的目录。 如果成功,那很好,它可以继续下去。 如果它失败了,其他人已经在工作,它必须等待。 当活动进程完成工作时,它将删除目录,以便另一个进程可以成功创建它。

无论如何,基本的信息是你需要两个文件系统的东西:一个是你的进程用来确定哪一个可以工作,一个是实际的工作。

您可以锁定文件的DATA部分以锁定文件本身,因此您可以(ab)使用它来控制对该脚本的独占访问。

我把它放在一个库文件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!

然后我打开了3个终端并在每个终端中运行:

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

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

第一个终端立即打印了我的/ tmp目录的内容。 第二个终端打印“别人有锁”,然后在5秒后打印出/ tmp的内容。 第三个终端打印“别人有锁” 两次 ,一次立即打印,然后一次打印5秒,然后打印/ tmp /的内容。

但要注意将它放在库中的位置,你要确保没有锁定不相关的子程序。

我个人会把锁码放在每个收集脚本中,而不是放在库中。 收集脚本是你实际上只想运行一个实例的。 看起来你的标题不准确:你不是试图专门读取文件,而是试图专门运行文件。

暂无
暂无

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

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