0

我正在编写一个脚本来与远程服务器通信。我了解如何发送基本的 shell 命令,例如“ls”或“find / |grep foo”。但我正在另一端执行一个交互式应用程序。

如果我调用 $ssh->shell,我会从远程服务器获得提示,因此我知道 SSH 正在接收此提示。但是后来我什么也做不了,因为脚本被阻止在 shell 中。

我安装了两个处理程序。如果我使用脚本连接到一个基本的 ssh 主机,并执行一个 shell 命令,响应就会传递给处理程序,所以我知道它们是好的。所以我希望我正在执行的应用程序的提示会发送到这些,但事实并非如此。

#!/usr/bin/perl -w
use strict;    
use Net::SSH::Perl;    

my $host = 'rt.olsendata.com';
my $user = 'rtdemo';
my $pass = 'rtdemo';    
my %params = ('debug' => 1,'protocol' => 2);
my $ssh = Net::SSH::Perl->new($host, %params);

$ssh->register_handler("stderr", sub{ 
            my ($ssh, $packet) = @_;
            receiveerrors($packet);
        });
$ssh->register_handler("stdout", sub{ 
            my ($ssh, $packet) = @_;
            receivedata($packet);
        });
my ($output, $errors, $exit) = $ssh->login($user, $pass);

此时我需要通过发送“1”来响应提示。但这被远程主机解释为 shell 命令,而不是对提示的响应。它返回错误“h:1:没有这样的文件或目录”。

如果您想尝试一下,可以使用代码顶部的演示 ssh 帐户。它是公开的。

编辑:我意识到 Expect 解决了这个问题,但我在 Expect 中找不到任何与 register_handler() 等效的东西。我是对的吗?

4

2 回答 2

0

迄今为止最简单的解决方案是 Net::SSH::Expect。下面是代码。登录后,我需要立即发送一个“1”来响应提示(“1”是我想要的选择)。然后我得到另一个提示,因为我想要默认值,所以我只发送\n。然后我想永远逐行读取输入。它就像一个魅力。

    my $ssh = Net::SSH::Expect->new (
        host => $host,
        user => $user,
        password=> $pass,
        raw_pty => 1
    );
    my $login_output = $ssh->login();
    my $prompt = $ssh->exec("1");
    my $line;
    $ssh->send("\n");
    while ( defined ($line = $ssh->read_line()) ) {
        print "$line\n"; 
    }
于 2013-08-08T19:56:33.663 回答
0

我使用 expect 来自动化 ssh/sftp 会话。


Net::SSH::Perl为“交互式”会话提供了 shell()方法。否则,这个和它的兄弟一样,假设您正在远程服务器上执行单个命令。

于 2013-08-07T21:23:36.507 回答