我一直在尝试使用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下编写这个库作为食谱,直到我遇到Thor,并认为这是一个尝试它的好机会。如果需要的话,我不反对将整个事情转回Capistrano,但如果没有一种简单的方法在远程服务器上运行sudo命令,我会感到非常惊讶。
答案 0 :(得分: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(';')
答案 1 :(得分: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
但是使用此解决方案,您可以在某个脚本文件中明确写入root密码...
答案 2 :(得分:4)
可以使用net/ssh
进行设置,但这确实太费力了,只需执行ssh
命令:
system("ssh", "-t", "#{user}@#{host}", "sudo cp #{file_from_path} #{file_to_path}")
此-t
表示分配tty。没有它它仍然可以工作,但你的密码将被清楚地看到。
(我假设您打算手动输入sudo密码。如果没有,请按授权密钥方式)。
答案 3 :(得分:2)
我通过添加以下内容作弊:
sudouser ALL=(ALL:ALL) NOPASSWD: ALL
到/etc/sudoers
此外,请务必在编辑时使用visudo
!
答案 4 :(得分:1)
您可能想要尝试的第一件事是使用公钥而不是密码登录。然后还尝试从交互式shell运行命令。
例如:
(这部分实际上取决于您拥有的服务器/客户端软件)
$ ssh-keygen
$ scp .ssh/id-dsa.pub server:
$ ssh server
server$ cat id-dsa.pub >> .ssh/authorizedkeys
$ scp -c "ls"
如果密钥共享成功,这应该没有任何提示。
答案 5 :(得分:-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