代码之家  ›  专栏  ›  技术社区  ›  planetp

如何确保一次只能运行一个Perl脚本副本?

  •  4
  • planetp  · 技术社区  · 14 年前

    我需要确保一次只运行一个Perl脚本副本。根据建议 here 我写了一张支票:

    sub check_instances {
        open my $fh, '<', $0 or die $!; 
    
        unless (flock($fh, LOCK_EX|LOCK_NB)) {
            print "$0 is already running. Exiting.\n";
            exit 1;
        } 
    }
    

    但没用。有什么问题吗?

    4 回复  |  直到 14 年前
        1
  •  5
  •   cjm    14 年前

    您使用的是限定在sub内的词法文件句柄 check_instances 返回时,文件句柄将自动关闭,从而释放锁。所以你永远不会看到冲突,除非两个副本同时检查。

    确保只要脚本运行(或者只要您想维护锁),filehandle就保持打开状态。例如:

    {
    my $fh;
    sub check_instances {
        return if $fh; # We already checked
        open $fh, '<', $0 or die $!; 
    
        unless (flock($fh, LOCK_EX|LOCK_NB)) {
            print "$0 is already running. Exiting.\n";
            exit 1;
        } 
    }
    } # end scope of $fh
    

    这也是一个使用 state variable ,如果您需要Perl 5.10。

        2
  •  2
  •   Ether    14 年前

    您可以检查进程列表中的其他实例( Proc::ProcessTable 但在许多语言中,unix程序采用的一种常见方法是创建一个pid文件——请参见 File::Pid

        3
  •  2
  •   mob    14 年前

    的正常语义 flock 可能需要您以写模式打开文件句柄,例如,

    open $fh, '>>', $0;
    open $fh, '+<', $0;
    

    (来自 perldoc -f flock )

    注意,fcntl(2)对flock(3)的模拟要求 它是以使用LOCK_EX的方式打开的。

        4
  •  1
  •   Aaron Digulla    14 年前

    文件锁定可能由于各种原因而失败(例如,如果文件位于网络文件系统(如NFS)上)。

    我的解决方案是在脚本运行时创建一个目录。创建目录总是一个原子操作。

    推荐文章
    mjb4  ·  在Bash中锁定文件
    10 年前