Net :: SSH sudo命令在输入密码后挂起
我一直在尝试使用Thor编写一个小型库来帮助我快速创建新项目和网站。我写了这个小方法:Net :: SSH sudo命令在输入密码后挂起
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}")
输入密码以后整个事情hhangs该脚本会提示我输入密码
[sudo] password for user:
但随后。
会有人碰巧知道为什么它完全挂起,以及我可以做什么来在Net :: SSH(或其他备选)下的远程服务器上运行sudo命令?
*注意:建议之前,我最初开始将这个图书馆作为Capistrano下的食谱编写,直到我找到Thor,并且认为这将是一个很好的尝试的机会。如果需要的话,我并不反对将所有事情都交给Capistrano,但如果没有简单的方法在远程服务器上运行sudo命令,我会感到非常惊讶。
您可能想要尝试的第一件事是使用公钥而不是密码登录。然后尝试从交互式shell运行命令。
例如:
(这部分真的取决于你拥有的服务器/客户端软件)
$ ssh-keygen
$ scp .ssh/id-dsa.pub server:
$ ssh server
server$ cat id-dsa.pub >> .ssh/authorizedkeys
$ scp -c "ls"
这应该没有任何提示,如果密钥共享成功。
有可能与net/ssh
设置它,但它确实太多精力,就执行这样ssh
命令:
system("ssh", "-t", "#{user}@#{host}", "sudo cp #{file_from_path} #{file_to_path}")
这-t
意味着分配一个tty。没有它,它仍然可以工作,但你的密码将被清楚地看到。
(我假设你打算手动输入sudo密码,如果没有,请使用授权密钥方式)。
这里是一个可能的解决方案:到底
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
但是这种解决方案,你有你的根密码以明文在某处的脚本文件writen ...
@japancheese您发布的最后一个代码不处理sudo提示符密码。这与你的问题中给出的代码完全相同。 – Riba 2010-11-22 16:00:36
其实,我做了非常类似于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
我希望这会帮助别人搜索。在部署过程中我还需要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(';')
链的命令一起
我被骗做添加此:
sudouser ALL=(ALL:ALL) NOPASSWD: ALL
到/etc/sudoers
此外,请务必在编辑时使用visudo
! !
你可以在密码中输入密码吗? 'ssh(“sudo cp#{from}#{to} Fosco 2010-07-28 19:58:35
当然,我忘了在以前的评论中忘掉双引号 – Fosco 2010-07-28 20:14:51
试过了,但它不起作用。 “bash:mysupass:没有这样的文件或目录”,这是否试图将密码输入到提示符中?如果是这样,这个想法可能会起作用,但是语法可能只是关闭了,我会看看我能找到什么 – joeellis 2010-07-28 20:24:42