如果在Perl中与主机的连接失败,请重试SSH到主机

如果在Perl中与主机的连接失败,请重试SSH到主机,perl,ssh,Perl,Ssh,我有一个脚本,它对服务器执行SSH并执行一些命令(在这个脚本中,为了演示,我正在运行带有Hello消息的perlprint语句) 这是我的剧本: #!/usr/bin/perl use strict; use warnings; use Net::OpenSSH; $Net::OpenSSH::debug = ~0; BEGIN { open my $out, '>', '/tmp/debug.txt' or warn $!; $Net::OpenSSH::debug_f

我有一个脚本,它对服务器执行SSH并执行一些命令(在这个脚本中,为了演示,我正在运行带有Hello消息的perlprint语句)

这是我的剧本:

#!/usr/bin/perl 

use strict; use warnings;

use Net::OpenSSH;

$Net::OpenSSH::debug = ~0;

BEGIN {
  open my $out, '>', '/tmp/debug.txt' or warn $!;
  $Net::OpenSSH::debug_fh = $out;
  $Net::OpenSSH::debug = -1;
}

my @hosts = ("ipaddress1","ipaddress2");

my $ssh;
my $command = "perl -e 'print \"Hello..\"'";

foreach my $n (@hosts) {
    
  #Here if connection to the host($n) fails, is it possible to retry again
  $ssh = Connect($n, "user", "passwd"); 
  $ssh->capture($command);

  print "Done execution in Host: $n\n";
 
}

undef $ssh;
print "**End**\n";

sub Connect {
    my ( $host, $user, $passwd ) = @_;
    my $ssh = Net::OpenSSH->new($host, user=>$user, password=>$passwd);
    $ssh->error and die "Couldn't establish SSH connection: " . $ssh->error;
    return $ssh;
}
每当我执行此脚本时,有时它会成功打印以下消息:

Done execution in Host: ipaddress1
Done execution in Host: ipaddress2
**End**
但有时无法对主机执行ssh操作(无论是
ipaddress1
还是
ipaddress2
),并给出以下消息:

Couldn't establish SSH connection: unable to establish master SSH connection: master process exited unexpectedly at script.pl ....
它在
Connect
子例程中死亡(因为我无法跟踪,打开了问题)


那么,如果我无法连接(ssh)到主机,有没有办法在一段时间后重试(对于
n
number次),而不是打印错误消息并使脚本死掉?

OpenSSH为错误提供了一个很好的接口。首先,我要看一下上面的例子。试试下面的方法

 foreach my $n (@hosts) {
    
  #Here if connection to the host($n) fails, is it possible to retry again
  $ssh = Connect($n, "user", "passwd", 3); 
  $ssh->capture($command);

  print "Done execution in Host: $n\n";
 
}

undef $ssh;
print "**End**\n";

sub Connect {
    my ( $host, $user, $passwd , $retry_limit ) = @_;
    my $timeout = 10;
    my $con;
    while ( $retry_limit-- > 0 )
    {
        $con = Net::OpenSSH->new($host, 
            user=>$user, 
            password=>$passwd,
            timeout=> $timeout,
            );
        last unless $con->error();
    }
    die "unable to connect ".$con->error() if retry_limit <0;
    return $con;
}
foreach my$n(@hosts){
#如果与主机($n)的连接失败,是否可以重试
$ssh=Connect($n,“用户”,“密码”,3);
$ssh->capture($command);
打印“在主机中完成执行:$n\n”;
}
未定义$ssh;
打印“**结束**\n”;
子连接{
我的($host、$user、$passwd、$retry\u limit)=@;
我的$timeout=10;
我的$con;
while($retry\u limit-->0)
{
$con=Net::OpenSSH->new($host,
用户=>$user,
密码=>$passwd,
超时=>$timeout,
);
最后,除非$con->error();
}

die“无法连接”。$con->error()如果重试\u limitOpenSSH为错误提供了一个很好的接口

 foreach my $n (@hosts) {
    
  #Here if connection to the host($n) fails, is it possible to retry again
  $ssh = Connect($n, "user", "passwd", 3); 
  $ssh->capture($command);

  print "Done execution in Host: $n\n";
 
}

undef $ssh;
print "**End**\n";

sub Connect {
    my ( $host, $user, $passwd , $retry_limit ) = @_;
    my $timeout = 10;
    my $con;
    while ( $retry_limit-- > 0 )
    {
        $con = Net::OpenSSH->new($host, 
            user=>$user, 
            password=>$passwd,
            timeout=> $timeout,
            );
        last unless $con->error();
    }
    die "unable to connect ".$con->error() if retry_limit <0;
    return $con;
}
foreach my$n(@hosts){
#如果与主机($n)的连接失败,是否可以重试
$ssh=Connect($n,“用户”,“密码”,3);
$ssh->capture($command);
打印“在主机中完成执行:$n\n”;
}
未定义$ssh;
打印“**结束**\n”;
子连接{
我的($host、$user、$passwd、$retry\u limit)=@;
我的$timeout=10;
我的$con;
while($retry\u limit-->0)
{
$con=Net::OpenSSH->new($host,
用户=>$user,
密码=>$passwd,
超时=>$timeout,
);
最后,除非$con->error();
}

die“无法连接”。$con->error()如果重试(由于您编写的代码将导致它死亡
),为什么不通过将
connect
调用包装在
eval{…connect(…);capture();};如果($@){异常发生}中来捕获它作为异常呢
?@tedlynmo好的。在这种情况下,
eval
的重试限制是多少。如果我传递了不正确的
user
passwd
,结果会是什么?它将尝试连接多少次。
eval{…};if($@{…}
只是在perl中进行异常处理的一种方法,比如
try>{…}catch(…){…}
在其他语言中。捕获异常时的操作取决于您自己。您可以减少一个计数器,并在几次尝试后停止,就像下面得到的答案一样(这样做没有异常处理)。既然您已经编写了将导致它死亡的代码,为什么不通过将
Connect
调用包装在
eval{…Connect(…);capture();};if($@{异常发生}中来捕获它作为异常呢
?@tedlynmo好的。在这种情况下,
eval
的重试限制是多少。如果我传递了不正确的
user
passwd
,结果会是什么?它将尝试连接多少次。
eval{…};if($@{…}
只是在perl中进行异常处理的一种方法,比如
try>{…}catch(…){…}
在其他语言中。捕获异常时,您将如何处理取决于您自己。您可以减少计数器,然后在几次尝试后停止,就像下面得到的答案中所示(这样做没有异常处理)。在我看来,perl-e'my$rt=3;而($rtYes,更改它也会起作用。如果保留后增量运算符,失败时将是
-1
。在循环中使用与之后相同的值是i.m.o。这意味着您可以在两个位置使用到布尔值的隐式转换,并在(-$retry\u limit){…}死亡时执行
,除非($retry_limit);
但是可以肯定,
>0
<0
是有效的。同意,可能是最清楚的,
die“无法连接”。$con->error()如果$con->error()是的,这可能是一个更好的选择-或者如果连接成功,从循环内部返回。
返回$con,除非$con->error;
-循环结束后不需要检查任何东西-只要
死亡
。对我来说,这看起来没问题perl-e'my$rt=3;而($rtYes,更改它也会起作用。如果保留后增量运算符,失败时将是
-1
。在循环中使用与之后相同的值是i.m.o。这意味着您可以在两个位置使用到布尔值的隐式转换,并在(-$retry\u limit){…}死亡时执行
,除非($retry_limit);
但是可以肯定,
>0
<0
是有效的。同意,可能是最清楚的,
die“无法连接”。$con->error()如果$con->error()是的,这可能是一个更好的选择-或者如果连接成功,就从循环内部返回。
返回$con,除非$con->error;
-无需在循环后检查任何内容-只要
死亡