Perl根据计数将散列分成相等的部分,并发送以进行并行执行

Perl根据计数将散列分成相等的部分,并发送以进行并行执行,perl,hash,parallel-processing,fork,Perl,Hash,Parallel Processing,Fork,我有一个散列(%hash),其中包含节点列表和需要为各个节点执行的命令 在此之前,我有一个主机列表(@alive\u hosts)它应该在哪个主机上执行 这是我的密码: #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @alive_hosts = qw/10.0.0.1 10.0.0.2/; print Dumper(\@alive_hosts); my %hash = ( 'Node1'

我有一个散列(
%hash
),其中包含节点列表和需要为各个节点执行的命令

在此之前,我有一个主机列表(
@alive\u hosts
)它应该在哪个主机上执行

这是我的密码:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);

my %hash = (
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node2' => 'cmd2 | cmd3',
          'Node3' => 'cmd4 | cmd1',
          'Node4' => 'cmd1',
          'Node5' => 'cmd2',
          'Node6' => 'cmd1 | cmd2',
          'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);

my $num_buckets = scalar @alive_hosts;
print "num_buckets:$num_buckets\n"; 

my $no_of_nodes = scalar keys %hash;

my $per_bucket  = int( $no_of_nodes / $num_buckets ); 
print "per_bucket:$per_bucket\n";

my $num_extras  =      $no_of_nodes % $num_buckets; 
print "num_extras:$num_extras\n";
我想将这个散列(
%hash
)进行分割,以便根据活动主机的数量对散列进行分割。以便将其分发到每个主机。 在上面的例子中, 主机1(
10.0.0.1
)应包含:

'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1'
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4'
主机2(
10.0.0.2
)应包含:

'Node1' => 'cmd1 | cmd2 | cmd3',
'Node2' => 'cmd2 | cmd3',
'Node3' => 'cmd4 | cmd1',
'Node4' => 'cmd1'
'Node5' => 'cmd2',
'Node6' => 'cmd1 | cmd2',
'Node7' => 'cmd3 | cmd4'

以上2个值可以保存在新的哈希中,从那里我需要执行一个shell脚本,将上述值(即Node和cmds)作为参数并行传递。为了并行执行,我想使用
Parallel::Loops
Parallel::ForkManager
。任何想法/建议都将不胜感激。

您已经计算出每个新哈希中需要多少节点。因此,您可以从大散列中获得一个键列表,并在循环的每一次循环中,只需
slice()

大概是这样的:

#!/usr/bin/perl

use strict;
use warnings;
use 5.20; # For the new hash slices
use feature 'say';

use Data::Dumper;

my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);

my %hash = (
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node2' => 'cmd2 | cmd3',
          'Node3' => 'cmd4 | cmd1',
          'Node4' => 'cmd1',
          'Node5' => 'cmd2',
          'Node6' => 'cmd1 | cmd2',
          'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);

my $no_of_nodes = scalar keys %hash;
my $num_buckets = scalar @alive_hosts;

my $per_bucket  = int( $no_of_nodes / $num_buckets );
$per_bucket++ if $no_of_nodes % $num_buckets;

my @keys = keys %hash;

my %node_hash;

for (1 .. $num_buckets) {
  my @newkeys = splice @keys, 0, $per_bucket;

  $node_hash{$alive_hosts[$_ - 1]} = { %hash{@newkeys} }; # New hash slice syntax
}

say Dumper \%node_hash;

注意:我使用新的(ish)(从Perl 5.20开始)
%hash{…}
哈希片语法。如果您使用的是早期版本的Perl,则需要调整该行。

您已经计算出每个新哈希中需要多少节点。因此,您可以从大散列中获得一个键列表,并在循环的每一次循环中,只需
slice()

大概是这样的:

#!/usr/bin/perl

use strict;
use warnings;
use 5.20; # For the new hash slices
use feature 'say';

use Data::Dumper;

my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);

my %hash = (
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node2' => 'cmd2 | cmd3',
          'Node3' => 'cmd4 | cmd1',
          'Node4' => 'cmd1',
          'Node5' => 'cmd2',
          'Node6' => 'cmd1 | cmd2',
          'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);

my $no_of_nodes = scalar keys %hash;
my $num_buckets = scalar @alive_hosts;

my $per_bucket  = int( $no_of_nodes / $num_buckets );
$per_bucket++ if $no_of_nodes % $num_buckets;

my @keys = keys %hash;

my %node_hash;

for (1 .. $num_buckets) {
  my @newkeys = splice @keys, 0, $per_bucket;

  $node_hash{$alive_hosts[$_ - 1]} = { %hash{@newkeys} }; # New hash slice syntax
}

say Dumper \%node_hash;

注意:我使用新的(ish)(从Perl 5.20开始)
%hash{…}
哈希片语法。如果您使用的是早期版本的Perl,则需要调整该行。

查看是否可以接受下一种方法

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);

my %hash = (
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node2' => 'cmd2 | cmd3',
          'Node3' => 'cmd4 | cmd1',
          'Node4' => 'cmd1',
          'Node5' => 'cmd2',
          'Node6' => 'cmd1 | cmd2',
          'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);

my %dispatch;
my @hosts;

while( my($node,$cmd) = each %hash ) {
    @hosts = @alive_hosts unless @hosts;
    my $host = shift @hosts;
    $dispatch{$host}{$node} = $cmd;

}

say Dumper(\%dispatch);
输出

$VAR1 = [
          '10.0.0.1',
          '10.0.0.2'
        ];
$VAR1 = {
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node4' => 'cmd1',
          'Node6' => 'cmd1 | cmd2',
          'Node5' => 'cmd2',
          'Node3' => 'cmd4 | cmd1',
          'Node7' => 'cmd3 | cmd4',
          'Node2' => 'cmd2 | cmd3'
        };
$VAR1 = {
          '10.0.0.1' => {
                          'Node6' => 'cmd1 | cmd2',
                          'Node1' => 'cmd1 | cmd2 | cmd3',
                          'Node3' => 'cmd4 | cmd1',
                          'Node2' => 'cmd2 | cmd3'
                        },
          '10.0.0.2' => {
                          'Node4' => 'cmd1',
                          'Node5' => 'cmd2',
                          'Node7' => 'cmd3 | cmd4'
                        }
        };

看看你是否发现下一个方法是可以接受的

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my @alive_hosts = qw/10.0.0.1 10.0.0.2/;
print Dumper(\@alive_hosts);

my %hash = (
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node2' => 'cmd2 | cmd3',
          'Node3' => 'cmd4 | cmd1',
          'Node4' => 'cmd1',
          'Node5' => 'cmd2',
          'Node6' => 'cmd1 | cmd2',
          'Node7' => 'cmd3 | cmd4',
);
print Dumper(\%hash);

my %dispatch;
my @hosts;

while( my($node,$cmd) = each %hash ) {
    @hosts = @alive_hosts unless @hosts;
    my $host = shift @hosts;
    $dispatch{$host}{$node} = $cmd;

}

say Dumper(\%dispatch);
输出

$VAR1 = [
          '10.0.0.1',
          '10.0.0.2'
        ];
$VAR1 = {
          'Node1' => 'cmd1 | cmd2 | cmd3',
          'Node4' => 'cmd1',
          'Node6' => 'cmd1 | cmd2',
          'Node5' => 'cmd2',
          'Node3' => 'cmd4 | cmd1',
          'Node7' => 'cmd3 | cmd4',
          'Node2' => 'cmd2 | cmd3'
        };
$VAR1 = {
          '10.0.0.1' => {
                          'Node6' => 'cmd1 | cmd2',
                          'Node1' => 'cmd1 | cmd2 | cmd3',
                          'Node3' => 'cmd4 | cmd1',
                          'Node2' => 'cmd2 | cmd3'
                        },
          '10.0.0.2' => {
                          'Node4' => 'cmd1',
                          'Node5' => 'cmd2',
                          'Node7' => 'cmd3 | cmd4'
                        }
        };

谢谢@dave。这解决了创建新哈希的问题。我已经更新了如何在并行处理中执行此值的问题。@vinodk89:如果您还有其他问题,请不要将其添加到此处-在网站上发布新问题。谢谢@dave。这解决了创建新哈希的问题。我已经更新了如何在并行处理中执行此值的问题。@vinodk89:如果您还有其他问题,请不要只在此处添加,请在网站上发布新问题。