Использование ruby ​​gem net-ssh-multi для выполнения команды sudo на нескольких серверах одновременно - PullRequest
5 голосов
/ 01 июня 2011

В предыдущем вопросе Я выяснил, как запустить сеансы SSH с аутентификацией по паролю на нескольких серверах для запуска одной команды. Теперь мне нужно выполнить команду sudo. Проблема в том, что net-ssh-multi не выделяет псевдотерминал (pty), который необходим для запуска sudo, что приводит к следующей ошибке:

[127.0.0.1: stderr] sudo: извините, у вас должен быть tty для запуска sudo

Согласно документации , псевдотерминал может быть выделен с помощью вызова метода для объекта канала, однако следующий код не работает: он генерирует ошибку «no tty» выше:

require 'net/ssh'
require 'net/ssh/multi'

Net::SSH::Multi.start do |session|


  # define the servers we want to use
  my_ticket.servers.each do |session_server|
    session.use session_server , :user =>  user_name ,  \
                              :password => user_pass
  end


 # execute commands on all servers
  session.exec 'sudo ls /root' do |channel, stream, data|
   if data =~ /^\[sudo\] password for user:/
     channel.request_pty # <- problem must be here.
     channel.send_data user_pass
   end

  end

 # run the aggregated event loop
 session.loop
end

$ ruby ​​--version

ruby ​​1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin]

Ответы [ 3 ]

8 голосов
/ 01 июня 2011

Можете ли вы попробовать что-то вроде этого:

  channel.request_pty do |c, success|
    if success
      command = "sudo YOUR_COMMAND"
      c.exec(command) do |c, success|
        # Some processing
      end
    end
  end

В этом случае sudo находится внутри.

3 голосов
/ 01 июня 2011

Вам нужно запросить pty перед выполнением команды.

session.open_channel do |ch|
  ch.request_pty
  ch.exec "sudo ls /root"
end

Также вы можете удалить tty-реквизит из / etc / sudoers. Для этого запустите visudo и прокомментируйте Defaults requiretty

1 голос
/ 02 июня 2011

Это то, чем я занимаюсь, благодаря @Christian и этому чудесному Pastie :

Net::SSH::Multi.start do |session|

# define the servers we want to use
my_ticket.servers.each do |session_server|
  session.use session_server , :user =>  my_ticket.user_name ,  \
  :password => my_ticket.user_pass
end



session.open_channel do |channel|
channel.request_pty do |c, success|
  raise "could not request pty" unless success
  channel.exec   "sudo YOUR_COMMAND"
  channel.on_data do |c_, data|
  if data = /\[sudo\]/
  channel.send_data(@password + "\n")
  end  
   puts data

    end
   end
  end

# run the aggregated event loop
  session.loop
end
...