perl Net::SSH2::channel 的问题

Posted

技术标签:

【中文标题】perl Net::SSH2::channel 的问题【英文标题】:Problems with perl Net::SSH2::channel 【发布时间】:2015-04-22 13:09:34 【问题描述】:

我在使用 Net::SSH2::Channel 时遇到问题。我正在使用 perl-5.10.1-136.el6.x86_64 开发 Oracle LINUX 2.6.39-400.214.5.el6uek.x86_64。

远程服务器运行 Debian 3.2.60-1+deb7u3 x86_64。

perl 代码将用作 bash 脚本中的函数。现在,它是一个普通的 perlscript。

我对 perl 编程不是很有经验。到目前为止,我只修改了现有的 perlscripts。

通过我的测试脚本,我可以使用 SSH2 登录到远程服务器。

然后,我可以使用$chan->shell(<conmmand>); 执行一个 - 并且只有一个 - 命令 第二个命令似乎失败了,即使它作为脚本中的第一个 shell 命令成功执行。 --> 虽然$chan->exec (); 据说在频道上只支持一个命令,但$chan->shell(); 在同一个频道上应该可以多次使用。 使用$chan-->close; 关闭频道并再次重新打开它也无济于事。 --> 如何解释$ssh2->error;的输出?

我的第二个问题是:阻塞到底在做什么? 在 ssh 连接(ssh->blocking();)和通道($chan->blocking(0);)上使用阻塞有什么区别?我都见过。 对我来说,在通道上使用阻塞或不使用都没有效果。

最后,我不知道如何获取执行命令的返回值以及如何以某种方式读取它,我不必提前知道它的长度。 (测试脚本中使用的目录 /tmpp 不存在。使用现有目录不会改变任何内容。 我的输出始终与uname -a 输出的前 65 个字符相同 当我设置bufleng =70 时,脚本挂起。在这里,似乎完全有问题。

非常欢迎任何建议。 感谢您的支持。

再见 拉尔夫


我的脚本如下:

#!/usr/bin/perl

  use warnings;
  use strict;
  use Net::SSH2;
  use Data::Dumper;

  # Handling options
  my $host = shift;
  my $user = shift;
  my $passwd = shift;
  my $command = shift;
  my $destination = shift;
  #my $source = $ARGV;

  # Defining variables
  my $LEC="";

  #my $scp_session=new Net::ssh2 ( Errmode=>'return',
  my $ssh2=Net::SSH2 -> new();
  $ssh2->debug(1);
##print Dumper($ENV);

  ### Connecting (10)
  #die "can\'t connect to $host, Error 10" unless $ssh2->connect($host);
  #print "Connected to $host\n";
  $ssh2->connect($host);
  if ("$?"==0) 
    print "Connected to $host\n";
   else 
    print "can\'t connect to $host, Error 10\n";
    #print $ssh2->error;
    print "\n";
  

  ### Logging in (20)
  #die "can't authenticate as $user" unless
  #$ssh2->auth(username => '$user',password => '$passwd');
  $ssh2->auth_password($user,$passwd);
  #  print $ssh2->error;
  #  #print "\n";
  if ("$?"==0) 
    print "  Authenticated as $user\n";
   else 
    print $ssh2->error;
    print "   Authentication failed\n";
    exit 20
  

print "  ## step 0\n";

  ### workload (30)
  my $chan = $ssh2->channel();
    print $ssh2->error;
    print "\n  ## step 2\n";
  #$chan->blocking(0);
  #  print $ssh2->error;
  #  print "\n  ## step 3\n";
  #$chan->shell('set cli-parameters console pager disabled');
  #   print $ssh2->error;
  #   print "\n  ## step 4\n";
  #   $chan->close;
  #   my $chan = $ssh2->channel();
  ### testing
  $chan->shell('ls -la');
    print $ssh2->error;
    print "\n  ## step 5\n";
  my $buflen = 65;
  my $buf1 = '0' x $buflen;
  $chan->read($buf1, $buflen);
  print $buf1,"\n";
  $chan1->shell($command);
    print $ssh2->error;
    print "\n  ## step 6\n";
  #my $buflen = 70;
    print $ssh2->error;
    print "\n  ## step 7\n";
  my $buf2 = '0' x $buflen;
    print $ssh2->error;
    print "\n  ## step 8\n";
  $chan->read($LEC, $buflen);
    print $ssh2->error;
    print "\n  ## step 9\n";
  print "$command:\n", $buf1,"\n";
    print $ssh2->error;
    print "\n  ## step 10\n";
  $chan->shell('exit');
    print $ssh2->error;
    print "\n  ## step 11\n";


  ### Logging off and disconnecting (90)
  $ssh2->disconnect($host);
    #print $ssh2->error;
    #print "\n";


   #($ssh2->auth_password($user,$passwd)) 
        #print "\n Executing command...\n";
        my $cmd = "ls";
        #print " ==> Running $cmd\n";

输出是:

perl ./test2.perl ifbscdd root dcdiag "LEC=1 ; [ -d /tmp ] && LEC=9 ; export LEC ;  return $LEC"
Connected to ifbscdd
  Authenticated as root
  ## step 0
libssh2_channel_open_ex(ss->session, pv_channel_type, len_channel_type, window_size, packet_size, ((void *)0) , 0 ) -> 0x1b89fc0
0
  ## step 2
0
  ## step 5
Net::SSH2::Channel::read(size = 65, ext = 0)
- read 65 bytes
- read 65 total
Linux ifbscdd 3.2.0-4-amd64 #1 SMP Debian 3.2.60-1+deb7u3 x86_64

libssh2_channel_open_ex(ss->session, pv_channel_type, len_channel_type, window_size, packet_size, ((void *)0) , 0 ) -> 0x1ba6490
0
  ## step 6
0
  ## step 7
0
  ## step 8
Net::SSH2::Channel::read(size = 65, ext = 0)
- read 0 bytes
- read 0 total
0
  ## step 9
LEC=1 ; [ -d /tmp ] && LEC=9 ; export LEC ;  return :
Linux ifbscdd 3.2.0-4-amd64 #1 SMP Debian 3.2.60-1+deb7u3 x86_64

0
  ## step 10
-1LIBSSH2_ERROR_SOCKET_NONEFailed waiting for channel success
  ## step 11
Net::SSH2::Channel::DESTROY
Net::SSH2::Channel::DESTROY
Net::SSH2::DESTROY object 0x1aa6230

【问题讨论】:

【参考方案1】:

您只能为每个 Channel 对象调用一次shell

另外,请注意shell 方法不接受任何参数。为了执行命令,您必须将其写入通道:

$channel->write("$cmd\n");

或者通常,您为每个要运行的命令请求一个新的 Channel 对象,然后以命令作为参数调用其 exec 方法。一般来说,像你试图做的那样与 shell 对话是一个坏主意,而且很难做到正确。

无论如何,当您在 Linux 环境中运行时,您可能更喜欢使用 Net::OpenSSH,而不是 Net::SSH2,后者非常原始且有缺陷。

【讨论】:

以上是关于perl Net::SSH2::channel 的问题的主要内容,如果未能解决你的问题,请参考以下文章

以后没有 Perl 6 了!Perl 之父同意改名

Perl 之父同意 Perl 6 改名为 Raku

Perl 的 rpm 版本不同于“perl -v”

Perl模块推荐23——Perl::Shell

Perl基础速成

Perl语言入门