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到我的配置文件中,但错误拒绝消失。

EDIT2:当我在上述程序中使用 -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.
4

2 回答 2

2

Net::Appliance::Session模块使用一组称为“短语手册”的匹配模式来猜测密码查询输出、命令结束提示符......

在您的情况下,有 2 个主要问题和 1 个次要/化妆品问题:

  1. Net::Appliance::Session依赖于连接配置文件。正确的名称是“ bash”而不是“ Bash
  2. bash 默认短语手册(位于“ ~site_perl/Net/CLI/Interact/phrasebook/unix/bash/pb”中)针对基于 ssh/bash 的设备,与您的日常 unix 服务器行为不匹配:

    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  
    

    如您所见,“ generic”和“ pass”提示符都与您通常的 linux 密码和提示符不匹配。您需要根据自己的需要对其进行调整:

    • 通过创建一些嵌套目录来创建库结构:“ mylib\mybash\
    • 将“ bash”短语手册复制到该嵌套目录并对其进行编辑以匹配您的 unix 服务器行为。
  3. 还有 ssh 警告输出:

警告:将“...” (RSA) 永久添加到已知主机列表中。

您只需使用ssh 调用选项的“ -q”或“ ”选项将 ssh 警告设置为关闭。-o LogLevel=quiet

因此,最后,您的代码将如下所示:

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/whatever-appliance”,但应该允许轻松连接到服务器,执行 1 个命令,获取其结果,然后进入 root 并执行另一个命令(如果您没有来自 ssh 的直接 root 访问权限)
  • “Net::OpenSSH”仅在 1 个命令的基础上通过 ssh 处理命令执行,即执行命令,获取结果并退出。没有直接的方法来设置环境,进入根目录并执行命令(你需要使用像 Net::Telnet 这样的包装器来做到这一点)
  • “Net::OpenSSH”需要相当新版本的 openssh 客户端,并且不能在 Windows 上运行,甚至在 Cygwin 下也不能运行(参见“Net::OpenSSH”手册)。
于 2013-10-14T11:22:42.727 回答
1

尝试改用Net::OpenSSH。与 Unix 服务器通信时,它会更容易使用和更可靠。

于 2013-10-14T07:41:40.737 回答