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