6

私はThorを使用して小さなライブラリを作成し、新しいプロジェクトやサイトをすばやく作成できるようにしています。私はこの小さな方法を書きました:

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:

しかし、それを入力した後、すべてがハングします。

なぜそれが正確にハングするのか、そしてNet :: SSH(またはいくつかの代替手段)の下のリモートサーバーでsudoコマンドを実行するために私ができることを誰かが知っているでしょうか?

*注:提案される前は、トールに出くわすまで、私はもともとこのライブラリをCapistranoの下でレシピとして書き始めていたので、試してみる良い機会になると思いました。必要に応じてすべてをCapistranoに戻す必要はありませんが、リモートサーバーでsudoコマンドを実行する簡単な方法がない場合は本当に驚きます。

4

6 に答える 6

14

これが誰かの検索に役立つことを願っています。展開中も必要でした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

1 つのチャネルで実行できるコマンドは 1 つだけであることに注意してください。したがって、コマンドを一緒にチェーンしましたcommands.join(';')

参照: Net::SSH::Connection::Channel

于 2012-11-30T04:22:59.663 に答える
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

しかし、このソリューションでは、ルートパスワードがスクリプトファイルのどこかに明確に書き込まれています...

于 2010-11-20T22:59:02.083 に答える
5

で設定することは可能ですnet/sshが、本当に手間がかかりすぎますssh。次のようなコマンドを実行するだけです。

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

これ-tは、ttyを割り当てることを意味します。それがなくても機能しますが、パスワードは明確に表示されます。

(sudoパスワードを手動で入力するつもりだと思います。そうでない場合は、許可されたキーを使用してください)。

于 2010-07-28T23:28:55.167 に答える
2

これを追加してだましました:

sudouser  ALL=(ALL:ALL) NOPASSWD: ALL

/etc/sudoers

また、編集時に必ず使用visudoしてください!!!

于 2012-12-05T21:13:09.637 に答える
1

最初に試みたいことは、パスワードの代わりに公開鍵を使用してログインすることです。次に、対話型シェルからコマンドを実行してみてください。

例えば:

(この部分は、実際に使用しているサーバー/クライアント ソフトウェアに依存します)

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

$ scp -c "ls"

キーの共有が成功した場合、これはプロンプトなしで機能するはずです。

于 2010-07-28T19:56:15.797 に答える
-1

実際、最終的には、Riba の提案と非常に似たようなことをしました (ただし、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
于 2010-11-21T06:14:49.817 に答える