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

时间:2015-07-30 04:49:13

标签: perl file-io

我有一个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,但无论你如何锁定它,用户仍然可以阅读。

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

2 个答案:

答案 0 :(得分:4)

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

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

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

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

答案 1 :(得分:1)

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

我把它放在库文件s中:

nap.pl

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

#!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!

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

的内容

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

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