我有以下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功能
答案 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。嗯...没有破坏,它不会像你认为的那样工作。
您希望将多个哈希值传递到子例程中。每个都包含三个值:
在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;
}
现在您可以根据需要使用任意数量的主机调用此函数,执行远程命令并返回结果列表;