输入密码后,Net :: SSH sudo命令挂起

joe*_*lis 5 ruby sudo net-ssh sudoers thor

我一直在尝试使用Thor编写一个小型库来帮助我快速创建新项目和站点.我写了这个小方法:

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

在需要时帮助我在远程服务器上运行快速命令.

问题是当我需要在远程端的sudo下运行一个命令时,脚本似乎挂在我身上.例如,当执行此...时

ssh("sudo cp #{file_from_path} #{file_to_path}" )
Run Code Online (Sandbox Code Playgroud)

该脚本将提示我输入密码

[sudo] password for user:
Run Code Online (Sandbox Code Playgroud)

但是输入之后整个事情都会变得很糟糕.

有人会碰巧知道为什么它会完全挂起,我可以做些什么来在Net :: SSH(或其他替代方案)下的远程服务器上运行sudo命令?

*注意:在建议之前,我最初开始将这个库作为Capistrano下的食谱编写,直到我遇到Thor,并认为这是一个尝试它的好机会.如果需要的话,我不反对将整个事情切换回Capistrano,但如果没有一种简单的方法在远程服务器上运行sudo命令,我会感到非常惊讶.

Jon*_*Lin 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
Run Code Online (Sandbox Code Playgroud)

请注意,一个通道只能执行一个命令.因此我将命令链接在一起commands.join(';')

参考:Net :: SSH :: Connection :: Channel


taw*_*taw 5

用 来设置是可以的net/ssh,但是真的太费力了,就这样执行ssh命令:

system("ssh", "-t", "#{user}@#{host}", "sudo cp #{file_from_path} #{file_to_path}")
Run Code Online (Sandbox Code Playgroud)

-t意味着分配一个 tty。没有它它仍然可以工作,但您的密码将被清楚地看到。

(我假设您打算手动输入 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
Run Code Online (Sandbox Code Playgroud)

但是使用此解决方案,您可以在某个脚本文件中明确写入root密码...


suk*_*kru 1

您可能想要尝试的第一件事是使用公钥而不是密码登录。然后还尝试从交互式 shell 运行该命令。

例如:

(这部分实际上取决于您拥有的服务器/客户端软件)

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

$ scp -c "ls"
Run Code Online (Sandbox Code Playgroud)

如果密钥共享成功,这应该可以在没有任何提示的情况下工作。

  • 让它与 NOPASSWD 标签一起工作。对于任何寻找信息的人来说,语法是“user ALL=NOPASSWD: ALL”。@sukru,假设我使用密钥从我的个人计算机进行访问,那么我应该担心这种方法是否存在任何固有的安全风险? (2认同)