Ответьте на приглашение SSH перед первой командой с помощью ruby ​​и Net :: SSH - PullRequest
0 голосов
/ 08 февраля 2010

Я пытаюсь подключиться, используя Net :: SSH, к серверу, который сразу после login выполняет скрипт, который требует ввода от пользователя. Пользователь должен ввести «1» или «2» и впоследствии будет получать некоторые данные через терминал.

Моя проблема в том, что, хотя я могу подключиться, я не могу найти способ отправить «1 \ n» на сервер и получить вывод.

Следующий код останавливается на «INFO - net.ssh.connection.session [80906b74]: channel_open_confirmation: 0 0 0 32768».

Использование channel.exec ("1 \ n") вместо channel.send_data, что неудивительно, также не работает.

Net::SSH.start('host', 'user', :password => "pass", :auth_methods => ["password"], :verbose => :debug) do |session|

  session.open_channel do |channel|

    channel.on_data do |ch, data|
      STDOUT.print data
    end 

    channel.send_data( "1\n")

  end

  session.loop
end    

Есть идеи, кто-нибудь?

Заранее спасибо

Ответы [ 5 ]

2 голосов
/ 09 февраля 2010

Спасибо всем за указатели. Мне удалось разобраться в проблеме - помимо использования channel.request_pty также необходимо было запросить оболочку. Следующее, наконец, работает как ожидалось:

Net::SSH.start('host', 'user', :password => "pass", :auth_methods => ["password"]) do |session|

  session.open_channel do |channel|

    channel.request_pty do |ch, success| 
      raise "Error requesting pty" unless success 

      ch.send_channel_request("shell") do |ch, success| 
        raise "Error opening shell" unless success  
      end  
    end

    channel.on_data do |ch, data|
      STDOUT.print data
    end 

    channel.on_extended_data do |ch, type, data|
      STDOUT.print "Error: #{data}\n"
    end

    channel.send_data( "1\n" )

    session.loop
  end  
end    
2 голосов
/ 08 февраля 2010

Можете ли вы убедиться, что ваш send_data звонок происходит после того, как вы получите приглашение от удаленного сервера? Попробуйте построить channel.on_data блок вокруг вашего send_data вызова, чтобы вы могли убедиться, что получили ожидаемое приглашение от сервера, прежде чем отправить ответ.

Возможно, вы не захотите использовать exec здесь. Из документов для Net :: SSH :: Connection :: Channel:

Отправляет запрос на канал с просьбой данная команда будет вызвана.

Вы хотите отправить текстовую строку, чтобы ответить на приглашение, а не вызывать команду. Документы показывают, что exec используется для отправки полных команд CLI, таких как "ls -l /home".

Вместо этого send_data, вероятно, то, что вы хотите. Документы показывают, что он использовался для отправки произвольного текста, такого как channel.send_data("the password\n"). Обратите внимание, однако, это предложение в документах:

Обратите внимание, что это не сразу отправить данные по каналу, но вместо этого просто добавляет данные в выходной буфер канала, подготовиться к упаковке и разослал в следующий раз соединение принимает данные.

Возможно, вы захотите взглянуть на channel.request_pty. Похоже, он предназначен для взаимодействия с консольным приложением.

Если вы пытаетесь (по сути) создать сценарий SSH-сеанса, который вы обычно выполняете вручную, вам может оказаться проще использовать expect -подобный интерфейс (например, гем, такой как sshExpect может стоит попробовать).

0 голосов
/ 08 февраля 2010

Я не очень разбираюсь в этой библиотеке, но в SSH вы можете открывать несколько каналов. Возможно, сервер отвечает только на первый канал по умолчанию, и если вы откроете другой канал, вы получите новую оболочку.

0 голосов
/ 08 февраля 2010

Если я выполню "1\n" в оболочке, я получу ответ: bash: 1: command not found

Если я выполню echo "1", я получу: 1

Вы уверены, что хотите попробовать выполнить отправляемый текст? Может быть, вы искали что-то вроде:

output = ""
Net::SSH.start('host', 'user', :password => "pass") do |ssh|
   output = ssh.exec! "echo 1"
end
puts output
0 голосов
/ 08 февраля 2010

Я не очень хорошо знаком с библиотеками Net :: SSH, поэтому я не могу помочь с этим как таковым, но похоже, что вы можете достичь того, чего хотите, используя Capistrano .

Например, у меня есть задача capistrano, которая подключается к удаленному серверу, запускает команду, которая ожидает ввода, а затем продолжает. Capistrano позаботится о дистанционном вводе / выводе. Может быть, это может быть решением для вас?

Надеюсь, это поможет!

...