Проблемы с perl Net::SSH2::channel

У меня проблема с Net::SSH2::Channel. Я работаю над Oracle LINUX 2.6.39-400.214.5.el6uek.x86_64, используя perl-5.10.1-136.el6.x86_64.

Удаленный сервер работает под управлением Debian 3.2.60-1+deb7u3 x86_64.

Код на Perl будет использоваться как функция внутри скрипта bash. Прямо сейчас, это простой perlscript.

Я не очень опытен в программировании на Perl. До сих пор я только адаптировал существующие perlscripts.

С помощью моего тестового сценария я могу войти на удаленный сервер, используя SSH2.

Затем я могу выполнить одну - и только одну - команду, используя $chan->shell(<conmmand>); Вторая команда кажется неудачной, даже если она будет успешно выполнена как первая команда оболочки в сценарии. -> Пока $chan->exec (); говорят, что поддерживает только одну команду на канале, $chan->shell(); должен использоваться несколько раз на одном и том же канале. Закрытие канала $chan-->close; и повторное его открытие тоже не поможет. -> Как я могу интерпретировать вывод $ssh2->error;?

Мой второй вопрос: что именно делает блокировка? А какая разница между использованием блокировки по ssh соединению (ssh->blocking();) и на канале ($chan->blocking(0);)? Я видел оба. Для меня не было никакого эффекта, используя блокировку на канале или не используя его.

Наконец, я не знаю, как получить возвращаемое значение выполненной команды и как ее прочитать таким образом, что мне не нужно заранее знать ее длину. (Каталог /tmpp, который используется в тестовом сценарии, не существует. Использование существующего каталога ничего не меняет. Мой вывод всегда идентичен первым 65 символам вывода uname -a Когда я установил 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 ответ

Вы можете только призвать shell один раз для каждого объекта канала.

Также обратите внимание, что shell Метод не принимает никаких аргументов. Чтобы выполнить команду, вы должны записать ее в канал:

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

Или обычно вместо этого вы запрашиваете новый объект Channel для каждой команды, которую хотите запустить, а затем вызываете ее exec метод с командой в качестве аргумента. В общем, говорить с оболочкой, как вы пытаетесь это сделать, - плохая идея, и ее довольно сложно сделать правильно.

В любом случае, поскольку вы работаете в среде Linux, вместо Net::SSH2, который является довольно примитивным и содержит ошибки, вы можете использовать Net:: OpenSSH.

Другие вопросы по тегам