【问题标题】:How do I get the PID of a process spawned with Perl's system function?如何获取使用 Perl 的系统函数生成的进程的 PID?
【发布时间】:2012-03-12 17:39:36
【问题描述】:

我正在编写一个调用另一个脚本newscript.pl 的Perl 脚本(比如script.pl)。我只想在script.pl 中获取两个脚本的 PID。我可以使用以下代码获取script.pl 的PID

my $pid = Unix::PID->new();
my @p = $pid->get_pidof( $pid->get_command($$), 1 );

在此之后我调用system 来执行newscript.pl

system("perl newscript.pl");

我想在script.pl中捕获这个newscript.pl生成的PID。

【问题讨论】:

    标签: perl system pid


    【解决方案1】:

    system 返回时,生成的进程将已经退出,将其 pid 作为有趣的历史参考——例如,用于日志分析。

    system LIST
    system PROGRAM LIST

    exec LIST 完全相同,只是先完成fork并且父进程等待子进程退出 ...

    如果您想要script.plnewscript.pl 的pid,fork 并自己管理它们的生命周期。有了关于您正在解决的问题的更具体信息,我们可以为您提供更具体的建议。


    要阻止程序的其他实例,一种常见的技术是使用操作系统的协作锁定功能:在启动时,尝试锁定某个文件。如果成功,您的程序知道它是唯一的。否则,另一个进程已经拥有锁,所以新进程退出。请参阅下面的示例。

    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    
    use Fcntl qw/ :flock /;
    use File::Basename;
    use POSIX qw/ strftime /;
    
    $0 = basename $0;
    
    my $LOCK = "$ENV{HOME}/.lock-$0";
    
    sub logmsg {
      my($msg) = @_;
      my $t = strftime "%F %T", localtime time;
      warn "$0: $t - $$ - $msg\n";
    }
    
    sub take_lock {
      open my $fh, ">", $LOCK or die "$0: open $LOCK: $!";
    
      unless (flock $fh, LOCK_EX | LOCK_NB) {
        logmsg "failed to lock $LOCK; exiting.";
        exit 1;
      }
    
      $fh;
    }
    
    my $token = take_lock;
    logmsg "processing...";
    sleep 2 * 60;
    logmsg "done.";
    

    请注意,您必须保持从take_lock 返回的文件句柄处于打开状态,而控制权在您的critical section 中。上面的代码将其视为一个不透明的令牌。当你的程序退出时,Perl 关闭文件句柄,它会自动释放锁。您不想做的是在 void 上下文中调用 take_lock,因为这会丢弃您的锁。

    【讨论】:

    • 我的 script.pl 负责调度其他脚本,如 newscript.pl 和许多其他脚本。我不能直接在 cron 中安排它们,因此想到制作这个将充当调度程序的父脚本。现在,当我从 MySql 数据库中获取脚本名称时,可能会重复预定脚本,我不希望已经运行的脚本再次执行,因此我在想是否可以捕获预定脚本的 PID,我可以根据这些 Pid 检查并避免同时运行相同的脚本。非常感谢您的帮助
    • 不使用fork还有其他方法吗?
    • 如果您需要排他性,请使用flock()use Fcntl qw(:flock); flock ($lockfd, LOCK_NB|LOCK_EX) or die "Same script already going"; # ... 注意 $lockfd 是一个文件描述符而不是文件名(你必须在flock之前打开它)。
    【解决方案2】:

    当前进程的进程号在$$。使用open3而不是system来接收子进程的进程号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-12
      • 2014-04-24
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      • 2020-05-19
      • 1970-01-01
      相关资源
      最近更新 更多