2010-07-28 7 views
5

Я пытался написать небольшую библиотеку с помощью Thor, чтобы помочь мне быстро создавать новые проекты и сайты. Я написал этот небольшой метод:Net :: SSH sudo command зависает после ввода пароля

def ssh(cmd) 
    Net::SSH.start(server_ip, user, :port => port) do |session| 
    session.exec cmd 
    end 
end 

, чтобы помочь мне в выполнении быстрых команд на удаленных серверах при необходимости.

Проблема в том, когда мне нужно запустить команду под sudo на удаленном конце, сценарий, похоже, висит на мне. Например, при выполнении этого ...

ssh("sudo cp #{file_from_path} #{file_to_path}") 

скрипт запросит у меня пароль

[sudo] password for user: 

Но тогда все hhangs после ввода его.

ли кто-нибудь случится знать почему он точно висит, и что я могу сделать, чтобы запустить команду sudo на удаленном сервере в Net :: SSH (или какой-то другой)?

* примечание: перед тем, как я предложил, я начал писать эту библиотеку в качестве рецепта под Капистрано, пока не натолкнулся на Тора, и подумал, что это будет хороший шанс попробовать. Я не против того, чтобы переключать все это обратно на Capistrano, если это необходимо, но я был бы очень удивлен, если бы не было простого способа запуска команд sudo на удаленном сервере.

+0

Вы можете подключить пароль? 'ssh (" sudo cp # {from} # {to} <"mysupass") ' – Fosco

+0

, конечно, я забыл избежать двойных кавычек в предыдущем комментарии. – Fosco

+0

Пробовал это, но он не работает. msgstr "bash: mysupass: Нет такого файла или каталога" .Это попытка передать пароль в приглашение? Если это так, идея может работать, но синтаксис, вероятно, совсем не работает. Я посмотрю, что я могу найти – joeellis

ответ

1

Первое, что вы можете попробовать - это использовать открытые ключи вместо паролей для входа в систему. Затем попробуйте запустить команду из интерактивной оболочки.

Например:

(Эта часть действительно зависит от программного обеспечения сервера/клиента у вас есть)

$ ssh-keygen 
$ scp .ssh/id-dsa.pub server: 
$ ssh server 
server$ cat id-dsa.pub >> .ssh/authorizedkeys 

$ scp -c "ls" 

это должно работать без каких-либо подсказок, если обмен ключ был успешным.

+1

На самом деле я использую открытые ключи. Пароль, на который он запрашивает пароль, не является паролем для ssh-соединения, а пароль для sudo для запуска команды. Поэтому я, по крайней мере, знаю, что он подключается, но он зависает после заполнения пароль sudo. – joeellis

+0

Вы можете попробовать установить sudo, чтобы не запрашивать пароль для конкретного пользователя. – sukru

+0

Я пробовал это в файле sudoers на удаленном сервере, добавляя строки следящего устройства в конце «user ALL = (ALL) ALL », но я все еще получаю подсказку. неверно? – joeellis

4

Можно настроить его с net/ssh, но это действительно слишком много усилий, просто выполнить ssh команды:

system("ssh", "-t", "#{user}@#{host}", "sudo cp #{file_from_path} #{file_to_path}") 

Это означает, что -t выделить терминал. Без него он по-прежнему будет работать, но ваш пароль будет заметным.

(Я предполагаю, что вы намереваетесь ввести пароль sudo вручную, а если нет, пройдите авторизованный ключ).

5

Вот возможное решение:

def ssh(cmd) 
    Net::SSH.start(server_ip, user, :port => port) do |session| 
    result = nil 
    session.exec!(cmd) do |channel, stream, data| 
     if data =~ /^\[sudo\] password for user:/ 
     channel.send_data 'your_sudo_password' 
     else 
     result << data 
     end 
    end 
    result # content of 'cmd' result 
    end 
end 

Но с этим решением, вы корневой пароль прописан в незашифрованном в файле сценария где-то ...

+0

@japancheese Последний код, который вы опубликовали, не обрабатывает пароль sudo prompt. Это точно такой же код, указанный в вашем вопросе. – Riba

-1

На самом деле, в конце концов, я сделал что-то очень похоже на предложение RIBA (хотя его/ее код намного лучше и умнее, я думаю)

def ssh(env, cmd, opts={}) 
    Net::SSH.start(config[env]["ip"], config[env]["user"], :port => config[env]["port"]) do |session| 
     cmd = "sudo #{cmd}" if opts[:sudo] 
     print cmd 
     session.exec cmd 
    end 
end 
13

Я надеюсь, что это поможет кому-то поиск.Я также необходимо sudo во время развертывания (перезапуск тонких экземпляров)

# deploy.rake 
require 'net/ssh' 

# INITIALIZE CONSTANTS HERE 
HOST = 'yourwebsite.com' 
USER = 'admin' 
PASSWORD = 'your server password' # or use ENV variables? 
# etc. 

namespace :deploy do 
    namespace :staging do 
    task :restart do 
     commands = [ 
     "cd #{PATH_TO_STAGING_APP} && git checkout master", 
     "git reset --hard HEAD", 
     "git pull origin master", 
     "bundle install --without test development", 
     "sudo thin restart -C /etc/thin/#{STAGING_APP}.yml" 
     ] 

     Net::SSH.start(HOST, USER, :password => PASSWORD) do |ssh| 
     ssh.open_channel do |channel| 
      channel.request_pty do |ch, success| 
      if success 
       puts "Successfully obtained pty" 
      else 
       puts "Could not obtain pty" 
      end 
      end 

      channel.exec(commands.join(';')) do |ch, success| 
      abort "Could not execute commands!" unless success 

      channel.on_data do |ch, data| 
       puts "#{data}" 
       channel.send_data "#{PASSWORD}\n" if data =~ /password/ 
      end 

      channel.on_extended_data do |ch, type, data| 
       puts "stderr: #{data}" 
      end 

      channel.on_close do |ch| 
       puts "Channel is closing!" 
      end 
      end 
     end 
     ssh.loop 
     end 
    end 
    end 
end 

Обратите внимание, что один канал может выполнить только одну команду. Поэтому я прикован команды вместе с commands.join(';')

Ссылка: Net::SSH::Connection::Channel

2

я обманул, делая это, добавив:

sudouser ALL=(ALL:ALL) NOPASSWD: ALL 

в /etc/sudoers

Кроме того, не забудьте использовать visudo при редактировании !! !