哈希键/值作为函数参数

时间:2013-12-29 20:04:55

标签: perl

我有以下perl代码:

#!/usr/bin/perl 
use strict;
use warnings;
use Net::SSH::Perl;
sub SSH($$$$){             
          my ($host, $user, $pass, $cmd) = @_;
          my $ssh = Net::SSH::Perl->new($host);
          $ssh->login("$user", "$pass");
          return $ssh->cmd($cmd);
        };
        my %h = (
          "ILSW01" => {
                       "ip" => "1.1.1.",
                       "user" => "bla",
                       "pass" => "xxx"
                     }
                );
    SSH($h{host}{ip}, $h{host}{user}, $h{host}{pass}, "ls -ltr")

工作正常。 我的问题是,如果我有多个主机,如何使用“主机哈希”的键作为SSH功能中的参数来避免重复编写代码?

要明确:我希望避免每个主机使用SSH功能

3 个答案:

答案 0 :(得分:3)

  

我想避免每台主机使用SSH功能

这听起来像是一个非常糟糕的设计,因为你要在一个函数中组合不相关的两个任务。我个人一起去

my %hosts = (
   "ILSW01" => {
      host => "1.1.1.",
      user => "bla",
      pass => "xxx",
   },
   ...
);

sub SSH {
   my ($connect_info, $cmd) = @_;
   my $ssh = Net::SSH::Perl->new($connect_info->{host});
   $ssh->login($connect_info->{user}, $connect_info->{pass});
   return $ssh->cmd($cmd);
}

my @results = map { SSH($_, $cmd) } values(%hosts);

如果你真的想要一个sub,你可以制作一个由最后一行组成的子,但是我不确定这里有什么好处。

sub SSH_many {
    my ($hosts) = @_;
    return map { SSH($_, $cmd) } values(%$hosts);
}

my @results = SSH_many(\%hosts);

答案 1 :(得分:2)

首先,不要在Perl函数中使用原型。 It is broken。嗯...没有破坏,它不会像你认为的那样工作。

您希望将多个哈希值传递到子例程中。每个都包含三个值:

  • IP地址
  • 用户名
  • 密码

在Perl中,基本数据结构都传递标量数据。像$foo这样的变量包含一个标量数据。像@foo这样的变量包含标量数据列表,而像%foo这样的变量包含标量数据的键/值集。但是,并非所有数据都是标量。其中一些结构复杂。问题是如何在Perl中模拟这个结构。

我们在Perl中执行此操作的方式是通过 references 。引用是存储器中存储数据的位置。

例如,我的FTP位置是一个包含三个数据的哈希:

my %ftp_user;
$ftp_user{IP}       = 1.1.1.1;
$ftp_user{USRER}    = "foo";
$ftp_user{PASSWORD} = "swordfish";

我可以通过在它前面放一个反斜杠来获取引用

my $ftp_user_ref = \%ftp_user;

请注意$变量前面的$ftp_user_ref。这意味着$ftp_user_ref中的值是标量位数据。我可以把它放到一个数组中:

push @ftp_users_list, $ftp_user_ref;

现在我的@ftp_users_list包含一个完整哈希数组,而不是一组单独的标量数据。

我甚至可以参考我的@ftp_users_list

my $ftp_user_list_ref = \@ftp_users_list;

并且,我可以将其作为单个数据传递到我的子程序中。

查看Perl附带的Perl Reference Tutorial,了解参考如何工作以及如何使用它们。

同时,这是一个使用引用来调用每个主机并运行一系列命令的示例。请注意,我的ssh子例程只需要两个参数:一个哈希数组,它是我每个系统的登录凭据,以及我想在每个系统上运行的命令列表:

#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);

my @ftp_list;
while ( my $line = <DATA> ) {
    chomp $line;
    my ($ip, $user, $password) = split /:/, $line;
    # Push an anonymous hash into my @ftp_list
    push @ftp_list, { IP => $ip, USER => $user, PASSWORD => $password };
}
my @commands;
push @commands, "cd data";
push @commands, "get foo.txt";
push @commands, "del foo.txt";
ssh( \@ftp_list, \@commands );

sub ssh {
    my $ftp_list_ref = shift;
    my $commands_ref = shift;

    my @ftp_list = @{ $ftp_list_ref };
    my @commmands = @{ $commands_ref };

    for my $ip_ref ( @ftp_list ) {
        my $ip = $ip_ref->{IP};
        my $user = $ip_ref->{USER};
        my $pass = $ip_ref->{PASSWORD};

        say "my \$ssh = Net::SSH::Perl->new($ip);";
        say "\$ssh->login($user, $pass);";
        for my $command ( @commands ) {
            my $results = say "\$ssh->cmd($command);";
            return if not defined $results;
        }
    }
    return 1;
}
__DATA__
1.1.1.1:bob:swordfish
1.2.3.2:carol:secret
1.3.4.5:lewis:ca$h

答案 2 :(得分:0)

您可以将主机和元数据的哈希传递给SSH功能:

sub SSH { 
   my (%h, $cmd) = @_;
   my @commands; 

   for my $host ( keys %h ) {
      my $ssh = New::SSH::Perl->new($host); 
      $ssh->login($h{$host}->{user}, $h{$host}->{pass});

      push @commands, 
         $ssh->cmd($cmd);
   }

   return @commands; 
}

现在您可以根据需要使用任意数量的主机调用此函数,执行远程命令并返回结果列表;