在 Perl 中,如何验证 Parallel::ForkManager 的每个子项是不是都完成了它的工作?

Posted

技术标签:

【中文标题】在 Perl 中,如何验证 Parallel::ForkManager 的每个子项是不是都完成了它的工作?【英文标题】:In Perl, how can I verify that every child of Parallel::ForkManager finishes its job?在 Perl 中,如何验证 Parallel::ForkManager 的每个子项是否都完成了它的工作? 【发布时间】:2013-08-06 23:51:39 【问题描述】:

我正在开发一个使用Net::FTP 和Parallel::ForkManager 的Perl 程序。在我使用 ForkManager 创建的每个子进程中,我调用了许多 Net::FTP 方法。不幸的是,这些偶尔会失败,我相信是由于连接问题。

在 Net::FTP 文档中,他们明确表示您可以/应该像这样处理失败的方法调用:

$ftp = Net::FTP->new("some.host.name", Debug => 0) or die "Cannot connect to some.host.name: $@";

这可以很好地检测错误,但会在 ForkManager 中杀死我的子进程。这让我很难确保每个孩子都跑到完成或再次尝试直到成功。

我想要做的是,如果 Net::FTP 方法失败,则在子例程中都发出警告(与上面的 die 消息类似) return 0。我的想法是,这将允许我重新连接到 FTP 并重试,而不会杀死我的子进程。像这样(这只是一个代码sn-p):

foreach my $page (sort (keys %pages)) 
    my $pid = $pm1->start($page) and next;
    my $ok;
    my $attempts = 1;
    while (!($ok)) 
        print "Attempts on $page: $attempts\n";
        $ok = ftp_server_process($page);
        $attempts++;
    
    $pm1->finish;

与相关子程序:

sub ftp_server_process 
    my $ftp = Net::FTP->new("some.ip", Debug => 0, Passive => 1, BlockSize => 1048576) or warn "Cannot connect to some.ip for page $page: $@" and return 0;
    $ftp->login("username", "password") or warn "Cannot login to some.ip\n", $ftp->message and return 0;
    $ftp->binary or warn "opening binary mode failed\n", $ftp->message and return 0;
    $ftp->cwd($ftp_input_folder) or warn "changing directory failed\n", $ftp->message and return 0;
    $ftp->put($pages$page"ftp_upload_name") or warn "putting page $page failed\n", $ftp->message and return 0;
    $ftp->quit;
    return 1;

这是解决此问题的合理方法吗? object->method or warn "a message" and return 0; 语法是否正确,或者那里有我遗漏的问题?它似乎运行良好,但感觉不稳定,我想知道是否有更成熟的模式来解决确保每个子进程在工作完成之前存活的问题。

欢迎提出任何建议。谢谢!

【问题讨论】:

【参考方案1】:

die 并捕获异常更简单。

for my $page (sort keys %pages) 
    $pm->start($page) and next;

    my $attempts_left = 3;
    LOOP: 
        if (!eval  ftp_server_process($page); 1 ) 
           warn $@;
           if (--$attempts_left) 
              warn "Retrying...\n";
              redo;
            else 
              warn "Aborting.\n";
              $pm->finish(1);
           
        
    

    $pm->finish(0);

如果您愿意,您甚至可以记下父进程中哪一个失败:

$pm->run_on_finish(sub 
   my ($pid, $exit_code, $page, $signal) = @_;
   if ($exit_code || $signal) 
      print "Couldn't put page $page: ";
      if ($exit_code) 
         print "Exited with $exit_code\n";
       else 
         print "Killed by signal $signal\n";
      
   
);

【讨论】:

以上是关于在 Perl 中,如何验证 Parallel::ForkManager 的每个子项是不是都完成了它的工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中使用 POE::Component::IRC::State 检查用户是不是通过 NickServ 的身份验证?

如何验证 Perl 中的数组(列表)中是不是存在值?

(perl) Xerces 验证如何访问 http 模式?

Perl:如何验证对“XML::eXistDB::RPC”的成功调用

我应该如何使用 Catalyst 在 Perl 中进行 RPC?

在使用摘要身份验证的服务器上获取用户名 (Perl)