Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Perl中管理fork池?_Perl_Logic_Fork - Fatal编程技术网

如何在Perl中管理fork池?

如何在Perl中管理fork池?,perl,logic,fork,Perl,Logic,Fork,我正在设置SSH以“批处理”方式连接到多个服务器。我基本上希望一次维护5个连接,当一个连接完成时打开另一个连接(跟随一组服务器IP) 我想知道像这样的东西我应该用吗?如果是这样,我可以使用什么样的逻辑来确保一次维护5个孩子?分叉(或线程)是您想要的,但您应该寻找能够提供您所需的大部分功能的模块,以防止您重新发明轮子,并经历您需要做的学习痛苦 例如,看起来这正是你想要的 use Parallel::ForkManager; $pm = new Parallel::ForkManager($MAX

我正在设置SSH以“批处理”方式连接到多个服务器。我基本上希望一次维护5个连接,当一个连接完成时打开另一个连接(跟随一组服务器IP)

我想知道像这样的东西我应该用吗?如果是这样,我可以使用什么样的逻辑来确保一次维护5个孩子?

分叉(或线程)是您想要的,但您应该寻找能够提供您所需的大部分功能的模块,以防止您重新发明轮子,并经历您需要做的学习痛苦

例如,看起来这正是你想要的

use Parallel::ForkManager;

$pm = new Parallel::ForkManager($MAX_PROCESSES);

foreach $data (@all_data) {
  # Forks and returns the pid for the child:
  my $pid = $pm->start and next; 

  ... do some work with $data in the child process ...

  $pm->finish; # Terminates the child process
}

有几个模块正好解决了这个问题。例如,请参阅或。

我个人最喜欢的叉子(!)是

pod概述:

use Proc::Fork;

run_fork {
    child {
        # child code goes here.
    }
    parent {
        my $child_pid = shift;
        # parent code goes here.
        waitpid $child_pid, 0;
    }
    retry {
        my $attempts = shift;
        # what to do if if fork() fails:
        # return true to try again, false to abort
        return if $attempts > 5;
        sleep 1, return 1;
    }
    error {
        # Error-handling code goes here
        # (fork() failed and the retry block returned false)
    }
};

为了限制SSH批处理之类的最大进程数,应该这样做:

use strict;
use warnings;
use 5.010;
use POSIX qw(:sys_wait_h);
use Proc::Fork;

my $max = 5;
my %pids;

my @ssh_files = (
    sub { system "scp file0001 baz@foo:/somedir/." },
    ...
    sub { system "scp file9999 baz@foo:/somedir/." },

);

while (my $proc = shift @ssh_files) {

    # max limit reached
    while ($max == keys %pids) {
        # loop thru pid list until a child is released
        for my $pid (keys %procs) {
            if (my $kid = waitpid($pid, WNOHANG)) {
                delete $pids{ $kid };
                last;
            }
        }
    }

    run_fork {
        parent {
            my $child = shift;
            $pids{ $child } = 1;
        }
        child {
            $proc->();
            exit;
        }
    }
}

/I3az/

另请参见Proc::Fork是否限制后台进程的数量?这是怎么回答这个问题的?@mobrule:对不起,我被叫走了!在Proc:Fork中没有任何特定的(我知道!)用于节流。因此,恢复到正常的waitpid度量(请参阅我更新的示例)。Proc::Queue会对现有脚本产生影响,因为不必更改实际的分叉操作。很好的建议。谢谢。但是ForkManager似乎并不真的支持一个池,而只是一个并发进程数的上限?start似乎总是为每次迭代做一个新的fork。是否有一个库支持真正的fork进程池,这样它们就不需要为每次迭代进行fork?这可能是正确的。现在我通常使用的是Thread::Pool::Simple。它自动处理您可以定义的最小/最大线程数,并根据工作负载管理活动线程数,并允许对每个作业执行前/后操作。我已经用了好几年了,效果很好。它确实需要线程,这对于那些使用Perl编译而没有ithreads的人来说是不幸的。如果是这样的话,AnyEvent::Fork::Pool看起来是个不错的选择,但我没有这方面的经验。
use Net::OpenSSH::Parallel;

my $pssh = Net::OpenSSH::Parallel->new(connections => 5);

for my $ip (@ips) {
  $pssh->add_host($ip);
}

$pssh->push('*', command => 'do this');
$pssh->push('*', command => 'do that');
$pssh->push('*', scp_get => 'foo', 'bar-%HOST%');
$pssh->push('*', scp_put => 'doz', 'there');

$pssh->run;