我正在设置一些内容,以“批量”方式将SSH输出到多个服务器。我基本上想要一次维护5个连接,当一个连接打开另一个连接时(遵循一系列服务器IP)。
我想知道这样的事情我应该使用fork()吗?如果是这样,我可以使用什么逻辑来确保我一次维持5个孩子?
答案 0 :(得分:11)
分叉(或线程)是你想要的,但是你应该看看CPAN的模块,它们将提供你需要的大部分内容,以防止你重新发明轮子并经历所需的学习痛苦要做。
例如,Parallel::ForkManager看起来就像你想要的那样。
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
}
答案 1 :(得分:5)
有几个模块可以解决这个问题。例如,请参阅Parallel::ForkManager,Forks::Super或Proc::Queue。
答案 2 :(得分:1)
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;
答案 3 :(得分:0)
我个人分叉(!)的最爱是Proc::Fork
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 /