通过Perl进行SSH登录

3

我正在使用Net:Appliance::Session登录远程Unix服务器,但无法连接。以下是我的代码和调试输出:

my $s = Net::Appliance::Session->new({
     personality => 'Bash',
     transport => 'SSH',
     host => $host,
});
$s->set_global_log_at('debug');
try {
     print "Trying to connect\n";
     $s->connect({ username => $user, password => $pass });
     print "Executing command\n";
     print $s->cmd($cmd);   
}
catch {
     warn "failed to execute command: $_";
}
finally {
     $s->close;
};

输出结果为:

Trying to connect
[   0.019420] pr finding prompt
[   0.028553] tr creating Net::Telnet wrapper for ssh
[   0.031377] tr connecting with:  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o CheckHostIP=no -l user ...
[   3.151205] du   SEEN:
Warning: Permanently added '...' (RSA) to the list of known hosts.
[   3.183935] pr failed: [Can't call method "isa" on an undefined value at /usr/lib/perl5/site_perl/5.14/Net/CLI/Interact/Phrasebook.pm line 247.
], sending WAKE_UP and trying again
[   3.184943] pr finding prompt
[   4.898408] du   SEEN:
Warning: Permanently added '...' (RSA) to the list of known hosts.
Password:
[   4.920447] pr failed to find prompt! wrong phrasebook?
failed to execute command: Warning: Permanently added '...' (RSA) to the list of known hosts.
Password:
        ...propagated at /usr/lib/perl5/site_perl/5.14/Net/CLI/Interact/Role/Prompt.pm line 127.

当我通过Putty登录时,会得到以下响应并成功登录:

login as: user
Using keyboard-interactive authentication.
Password:

我无法弄清楚我做错了什么。感谢您的任何帮助。
编辑:我认为我应该提到我在使用Cygwin。我已经手动登录到远程服务器,并且我的.ssh/known_hosts文件中的密钥也已经设置好了,但是在Cygwin中运行此程序时仍然会出现RSA错误。我在SO上看到了这个问题:“警告:已永久添加到已知主机列表”来自Git的消息并将UserKnownHostsFile ~/.ssh/known_hosts添加到我的配置文件中,但错误仍然存在。
编辑2:当我在上面的程序中使用-vvv选项时,我得到以下输出:
Trying to connect
[   0.020327] pr finding prompt
[   0.062541] tr creating Net::Telnet wrapper for ssh
[   0.063709] tr connecting with:  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o CheckHostIP=no -vvv -l user 1.1.1.1
[   0.731041] du   SEEN:
OpenSSH_6.2p2
[   0.851829] pr failed: [Can't call method "isa" on an undefined value at /usr/lib/perl5/site_perl/5.14/Net/CLI/Interact/Phrasebook.pm line 247.
], sending WAKE_UP and trying again
[   0.852459] pr finding prompt
[   0.852748] du   SEEN:
OpenSSH_6.2p2, OpenSSL 1.0.1e 11 Feb 2013
[   0.863739] pr failed to find prompt! wrong phrasebook?
failed to execute command: OpenSSH_6.2p2, OpenSSL 1.0.1e 11 Feb 2013
        ...propagated at /usr/lib/perl5/site_perl/5.14/Net/CLI/Interact/Role/Prompt.pm line 127.

你应该首先通过ssh手动登录到远程主机,以确认/消除此“永久添加...(RSA)到已知主机列表中”的提示。问题很可能与输入密码行不严格为“Password:”(而是以此“Warning: ...”开头)有关。 - Ouki
您可以使用“connect_options”来停用主机身份验证(使用“ignore_host_checks”),或设置ssh调试模式(使用带有多个“-v”的“opts”)。 - Ouki
根据手册,ignore_host_checks 默认已启用。我现在正在尝试调试模式。 - user828647
使用-vvv选项,即使从命令行登录,我也无法登录到服务器。它在请求密码3次后显示权限被拒绝。 - user828647
你能在使用“Net::Appliance::Session”模块的“ssh”时发布调试输出吗? - Ouki
2个回答

2

Net::Appliance::Session模块使用一组名为“Phrasebook”的匹配模式来猜测密码查询输出、命令结束提示等。

在您的情况下,有两个主要问题和一个次要/美观问题:

  1. Net::Appliance::Session rely on connection profile. The correct one is named "bash" and not "Bash"
  2. The bash default phrasebook (located in "~site_perl/Net/CLI/Interact/phrasebook/unix/bash/pb") is targeting ssh/bash based appliance and is not matching your everyday unix server behavior:

    prompt user  
        match /[Uu]sername: $/  
    
    prompt pass
        match /password(?: for \w+)?: $/
    
    prompt generic
        match /\w+@.+\$ $/
    
    prompt privileged
        match /^root@.+# $/
    
    macro begin_privileged
        send sudo su -
        match pass or privileged
    
    macro end_privileged
        send exit  
        match generic  
    
    macro disconnect  
        send logout  
    

    As you can see, both "generic" and "pass" prompt does not match your usual linux password and prompt. You will need to adjust it to your needs:

    • create a library structure by creating some nested directory: "mylib\mybash\"
    • make a copy of the "bash" phrasebook to that nested directory and edit it to match your unix server behaviour.
  3. There is also the ssh warning output:

警告:将“...”(RSA)永久添加到已知主机列表中。
您只需要使用ssh调用选项中的“-q”或“-o LogLevel = quiet”选项关闭ssh警告。
因此,最终您的代码将如下所示:
my $s = Net::Appliance::Session->new
  ({ add_library     => 'mylib',
     personality     => 'mybash',
     transport       => 'SSH',
     host            => $host,
     connect_options => { opts => [ '-q', ], },
   });
$s->set_global_log_at('debug');
try {
    print "Trying to connect\n";
    $s->connect({ username => $user, password => $pass });
    print "Executing command\n";
    print $s->cmd($cmd);
}
catch {
    warn "failed to execute command: $_";
}
finally {
    $s->close;
};

有了这样的短语手册(很快就调整到了我的FreeBSD服务器):
prompt user
    match /[Uu]sername: $/

prompt pass
    match /[Pp]assword:\s*$/

prompt generic
    match /\w+@.+[\$>] $/

prompt privileged
    match /^root@.+# $/

macro begin_privileged
    send sudo su -
    match pass or privileged

macro end_privileged
    send exit
    match generic

macro disconnect
    send logout

macro paging
    send terminal length %s

注意:
关于 "Net::Appliance::Session" 和 "Net::OpenSSH":

  • 这两个模块都可以很好地处理ssh连接
  • "Net::Appliance::Session" 更偏向于"cisco/其他设备",但应该很容易连接到服务器,执行一个命令,获取其结果,然后进入root并执行另一个命令(如果您没有直接从ssh访问root权限,则非常方便)
  • "Net::OpenSSH" 只能基于单个命令执行通过ssh的命令,即它执行一个命令,获取其结果并退出。没有直接的方法设置环境,进入root并执行命令(您需要使用类似于Net::Telnet的包装器来完成此操作)
  • "Net::OpenSSH" 需要较新版本的openssh客户端,并且不适用于Windows,甚至不适用于Cygwin(请参阅"Net::OpenSSH"手册)。

感谢您的回复。我仍然觉得Net::Appliance::Session对我来说是最好的选择。但是手动登录服务器以删除RSA错误的解决方案并没有奏效。请查看我的编辑。 - user828647
感谢对Net::OpenSSH的澄清。但根据手册,ignore_host_checks默认已启用。 - user828647
谢谢你详细的回答,Ouki!现在我能够成功登录了。 - user828647

1
尝试使用Net::OpenSSH代替。这样使用起来更简单,与Unix服务器交互时更可靠。

如果你正在寻找“session”即一次以上的连续命令,那么现有的“Net::OpenSSH”不是很合适。 - Ouki
@Ouki,是的,你只能使用一个命令,但在另一端拥有Unix shell意味着你可以使用相当复杂的命令。我发现这种方法比与shell交互更可靠。在我看来,会话方法应该是最后的选择。 - salva
我需要在服务器上连续执行多个命令,而且没有一个复杂的查询可以完成这项工作。如果还有其他我可以尝试的 Perl 模块,请告诉我。 - user828647
Net::OpenSSH允许您连续运行命令,只是为每个命令创建了一个新会话,因此,对于它们的副作用(即cdexport),命令变得无用。但这不是问题,因为您可以将它们组合成复杂的命令。处理susudo更加困难,但对于大多数情况也可以完成。 - salva
最后一次用户编辑改变了很多事情。来自Net::OpenSSH手册:“另一方面,Net::OpenSSH在Windows上不起作用,甚至在Cygwin下也不行。” - Ouki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接