287 lines
14 KiB
Ruby
287 lines
14 KiB
Ruby
require 'net/ssh'
|
|
require 'pathname'
|
|
namespace :exec_commands do
|
|
desc "Exec commands Script"
|
|
task :exec_commands,[:site_construct_id,:commands,:type,:server_name,:rails_env] => :environment do |task,args|
|
|
@type = args.type
|
|
if !args.site_construct_id.blank?
|
|
@site_construct = SiteConstruct.find(args.site_construct_id)
|
|
site_server = SiteServer.where(:server_name=>@site_construct.server_type).first
|
|
site_servers = [site_server]
|
|
else
|
|
@site_construct = nil
|
|
site_servers = SiteServer.where(:server_name.in=>args.server_name.split("////")).to_a
|
|
end
|
|
if args.type == "exec_all"
|
|
Multithread.where(:key=>'execing_commands').each{|thread| thread.destroy if (thread.status["status"] == "error" || thread.status["status"] == "finish")}
|
|
@thread = Multithread.where(:key=>'execing_commands').first
|
|
else
|
|
@thread = nil
|
|
end
|
|
if @thread.nil?
|
|
@command_trans = {}
|
|
@command_relations = {"upgrade_site"=>'git fetch origin && rails runner "a=Admin::SitesController.new;a.git_reset(%w(origin)[0],%w(update)[0]);while(1) do (Multithread.where(key: %w(update_manager)[0],status: %w(finish)[0]).count!=0 ? break : nil) end;sleep(5)"',
|
|
"bundle_update"=>"bundle update && kill -s USR2 `cat tmp/pids/unicorn.pid`",
|
|
"restart_site"=>"kill -s TERM `fuser tmp/pids/unicorn.sock tmp/sockets/unicorn.sock tmp/unicorn.sock`;bundle exec unicorn_rails -c config/unicorn.rb -D -E {{rails_env}}"}
|
|
@command_relations.each do |k,v|
|
|
@command_trans[k] = I18n.t("client_management.#{k}")
|
|
end
|
|
rails_envs = ["production", "development"]
|
|
rails_envs.each do |env|
|
|
@command_relations["start_site_in_env,#{env}"] = "kill -s TERM `fuser tmp/pids/unicorn.sock tmp/sockets/unicorn.sock tmp/unicorn.sock`;bundle exec unicorn_rails -c config/unicorn.rb -D -E #{env}"
|
|
@command_trans["start_site_in_env,#{env}"] = I18n.t("client_management.start_site_in_env",{:env=>env})
|
|
end
|
|
begin
|
|
if @thread.nil? && args.type == "exec_all"
|
|
@thread = Multithread.create(:key=>'execing_commands',:status=>{"infos"=>[],"status"=>"execing"})
|
|
end
|
|
site_servers.each do |site_server|
|
|
ip = site_server.ip
|
|
user = site_server.account
|
|
password = site_server.password
|
|
@password = password
|
|
begin
|
|
Net::SSH.start(ip , user , password: password) do |ssh|
|
|
end
|
|
rescue Net::SSH::HostKeyMismatch
|
|
system("ssh-keygen -f \"$HOME/.ssh/known_hosts\" -R #{ip}")
|
|
rescue Errno::ENOTTY
|
|
system("ssh-add \"$HOME/.ssh/id_rsa\"")
|
|
end
|
|
Net::SSH.start(ip , user , password: password) do |ssh|
|
|
@site_construct.update!(:infos=>[]) rescue nil
|
|
if args.type == 'close_site'
|
|
exec_ssh_command_by_sudo_and_see_output(ssh,"chmod 777 #{@site_construct.path}/#{@site_construct.site_name} -R",false)
|
|
exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'kill -s TERM `fuser #{@site_construct.path}/#{@site_construct.site_name}/tmp/unicorn.sock`'",false)
|
|
update_infos_for_exec("finish closing #{@site_construct.site_name}")
|
|
@site_construct.update(:status =>"closed")
|
|
elsif args.type == 'open_site'
|
|
default_rails_env = 'development'
|
|
enable_rails_env = ['development','production']
|
|
rails_env = @site_construct.rails_env.blank? ? default_rails_env : @site_construct.rails_env
|
|
cmd_output = exec_ssh_command_by_sudo_and_see_output(ssh,"ps -o args= -p `cat #{@site_construct.path}/#{@site_construct.site_name}/tmp/pids/unicorn.pid`",false) rescue []
|
|
enable_rails_env.each do |env|
|
|
if( cmd_output[0].include?(env) rescue false)
|
|
rails_env = env
|
|
break
|
|
elsif( cmd_output[0].include?("No such file or directory") rescue false)
|
|
@site_construct.update(:status => "closed")
|
|
break
|
|
end
|
|
end
|
|
if args.rails_env.present?
|
|
rails_env = args.rails_env
|
|
end
|
|
@site_construct.update(:rails_env=>rails_env)
|
|
update_infos_for_exec("starting site to #{rails_env}")
|
|
outputs = exec_ssh_command_by_sudo_and_see_output(ssh,"sudo -p 'sudo password:' chmod 777 #{@site_construct.path}/#{@site_construct.site_name} -R",false)
|
|
output = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'cd #{@site_construct.path}/#{@site_construct.site_name}\nkill -s TERM `fuser tmp/unicorn.sock`\nsudo -p \"sudo password:\" kill -s TERM `sudo -p \"sudo password:\" fuser tmp/unicorn.sock`\nsudo -p \"sudo password:\" rm -f tmp/pids/unicorn.pid\nbundle exec unicorn_rails -c config/unicorn.rb -D -E #{rails_env}\n'",false)
|
|
if output.include? "bundle install"
|
|
update_infos_for_exec("not yet bundle install")
|
|
outputs = exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'cd #{@site_construct.path}/#{@site_construct.site_name};bundle install'")
|
|
if outputs.join("\n").include? "Username for"
|
|
update_infos_for_exec("Cannot finish bundle install.")
|
|
update_infos_for_exec("This site include an private git project.")
|
|
@site_construct.update(:status =>"error")
|
|
break
|
|
else
|
|
exec_ssh_command_by_sudo_and_see_output(ssh,"bundle exec unicorn_rails -c config/unicorn.rb -D -E #{rails_env}",false)
|
|
end
|
|
end
|
|
update_infos_for_exec("finish starting #{@site_construct.site_name}")
|
|
@site_construct.update(:status =>"finish")
|
|
else
|
|
if args.type == 'exec_all'
|
|
sites = SiteConstruct.where(:server_type=>site_server.server_name).to_a
|
|
else
|
|
sites = [@site_construct]
|
|
end
|
|
if args.commands.include?("{{create_users}}")
|
|
commands = ['sudo -p "sudo password:" chmod 777 {{full_site_path}} -R',
|
|
'sudo -p "sudo password:" chmod 777 {{full_site_path}}/public -R',
|
|
'sudo -p "sudo password:" chmod 777 {{full_site_path}}/app/templates -R',
|
|
'sudo -p "sudo password:" useradd --home-dir {{full_site_path}}/app/templates {{site_name}} --no-create-home --badnames',
|
|
'sudo -p "sudo password:" bash -l -c \'echo -e "{{site_name}}\n{{site_name}}"|passwd {{site_name}}\'']
|
|
else
|
|
commands = args.commands.split("////").select{|c| c != ""} rescue [args.commands]
|
|
end
|
|
sites.each do |site_construct|
|
|
@site_construct = site_construct
|
|
@site_construct.update!(:infos=>[])
|
|
exec_ssh_command_by_sudo(ssh,"chmod 777 #{@site_construct.path}/#{@site_construct.site_name} -R")
|
|
rails_env = @site_construct.rails_env.blank? ? "development" : @site_construct.rails_env
|
|
commands.each do |command|
|
|
@command_i18n = command
|
|
update_flag = 1
|
|
@command_relations.each do |k,v|
|
|
if command.include?("{{#{k}}}")
|
|
update_flag = 2 #Not logging commands result
|
|
end
|
|
command = command.gsub("{{#{k}}}",v)
|
|
@command_i18n = @command_i18n.gsub("{{#{k}}}",@command_trans[k])
|
|
end
|
|
command = command.gsub("{{rails_env}}",rails_env)
|
|
command = command.gsub("{{full_site_path}}",@site_construct.full_site_path)
|
|
command = command.gsub("{{site_name}}",@site_construct.site_name)
|
|
@command_i18n = @command_i18n.gsub("{{rails_env}}",rails_env)
|
|
@command_i18n = @command_i18n.gsub("{{full_site_path}}",@site_construct.full_site_path)
|
|
@command_i18n = @command_i18n.gsub("{{site_name}}",@site_construct.site_name)
|
|
command = command.gsub(/'{1,3}/,"\"\'\"")
|
|
exec_ssh_command_by_sudo_and_see_output(ssh,"bash -l -c 'cd #{@site_construct.path}/#{@site_construct.site_name};#{command}'", update_flag)
|
|
@command_i18n = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if !@thread.nil?
|
|
@thread.update(:status=>@thread.status.merge({"status"=>"finish"}))
|
|
end
|
|
rescue => e
|
|
if !@thread.nil?
|
|
@thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.message),"status"=>"error"})
|
|
@thread.update(:status=>{"infos"=>@thread.status["infos"].push(e.backtrace.join("\n")),"status"=>"error"})
|
|
end
|
|
if !@site_construct.nil?
|
|
@site_construct.update(:status =>"error",:infos=>@site_construct.infos.push("#{e.message}"))
|
|
@site_construct.update(:status =>"error",:infos=>@site_construct.infos.push("#{e.backtrace.join("\n")}"))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
def exec_ssh_command_by_sudo(session,command)
|
|
output = session.exec!("echo '#{@password}' | sudo -S #{command}")
|
|
# output = session.exec!("echo '#{@password}' | sudo -S -s #{command}")
|
|
if output.include?("sudo:") && output.include?("command not found")
|
|
output = session.exec!(command)
|
|
end
|
|
return output.encode!("UTF-8", :invalid => :replace, :undef => :replace, :replace => '')
|
|
end
|
|
def update_infos_for_exec(info,update_last=false,update_array=false)
|
|
return if @site_construct.nil?
|
|
if(update_array)
|
|
info.map!{|i| i.encode!("UTF-8", :invalid => :replace, :undef => :replace, :replace => '')}
|
|
else
|
|
info.encode!("UTF-8", :invalid => :replace, :undef => :replace, :replace => '')
|
|
end
|
|
if update_last && !@site_construct.infos.empty?
|
|
@site_construct.infos[-1] += info.to_s
|
|
else
|
|
if update_array
|
|
@site_construct.infos += info
|
|
else
|
|
@site_construct.infos.push(info.to_s)
|
|
end
|
|
end
|
|
@site_construct.save!
|
|
return @site_construct.infos
|
|
end
|
|
def update_thread_infos_for_exec(info,update_last=false,update_array=false)
|
|
if update_last && !@thread.status["infos"].empty?
|
|
@thread.status["infos"][-1] += info.to_s
|
|
else
|
|
if update_array
|
|
@thread.status["infos"] += info
|
|
else
|
|
@thread.status["infos"].push(info.to_s)
|
|
end
|
|
end
|
|
@thread.save!
|
|
return @thread.status["infos"]
|
|
end
|
|
def exec_ssh_command_and_see_output(session,command,update_flag=1,output_string=false)
|
|
outputs = []
|
|
@flag = (@type == "exec_all")
|
|
command_i18n = command
|
|
update = (update_flag == true || update_flag == 1 || update_flag == 2)
|
|
update_outputs = (update_flag == true || update_flag == 1)
|
|
if update
|
|
command_i18n = @command_i18n if @command_i18n
|
|
if @site_construct
|
|
update_thread_infos_for_exec(["execing #{command_i18n} on on <a href='#{((@site_construct.get_port == "443") ? "https" : "http")}://#{@site_construct.domain_name}#{((@site_construct.get_port=="80" || @site_construct.get_port=="443" || @site_construct.get_port.blank?) ? "" : (':'+@site_construct.get_port))}'>#{@site_construct.domain_name}</a>",""],false,true) if @flag
|
|
update_infos_for_exec(["execing #{command_i18n}",""],false,true)
|
|
elsif @thread
|
|
update_thread_infos_for_exec(["execing #{command_i18n}...",""],false,true)
|
|
end
|
|
end
|
|
session.open_channel do |channel|
|
|
channel.request_pty do |channel, success|
|
|
channel.exec("LANG=en.UTF8 #{command}") do |ch, success|
|
|
abort "could not execute command: #{command}" unless success
|
|
channel.on_data do |ch, data|
|
|
if data.to_s.include?("sudo password:") || data.to_s.include?("Password:")
|
|
channel.send_data "#{@password}\n"
|
|
else
|
|
print "#{data}"
|
|
data_str = data.to_s
|
|
if data.include?("\n") || outputs.empty?
|
|
output_lines = data_str.split("\n")
|
|
first_output = output_lines[0]
|
|
if first_output
|
|
if outputs.count != 0
|
|
outputs[-1] += first_output
|
|
else
|
|
outputs << first_output
|
|
end
|
|
end
|
|
new_arr = output_lines[1..-1]
|
|
new_arr = [] if new_arr.nil?
|
|
if data_str[-1] == "\n"
|
|
new_arr << ""
|
|
end
|
|
outputs += new_arr
|
|
if update_outputs
|
|
if first_output
|
|
update_thread_infos_for_exec(first_output,true) if @flag
|
|
update_infos_for_exec(first_output,true)
|
|
end
|
|
update_thread_infos_for_exec(new_arr,false,true) if @flag
|
|
update_infos_for_exec(new_arr,false,true)
|
|
end
|
|
else
|
|
if outputs.count == 0
|
|
outputs.push(data_str)
|
|
else
|
|
outputs[-1] += (data_str rescue "")
|
|
end
|
|
if update_outputs
|
|
update_thread_infos_for_exec(data_str,true) if @flag
|
|
update_infos_for_exec(data_str,true)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
channel.on_close do |ch|
|
|
if update
|
|
if @site_construct
|
|
update_thread_infos_for_exec("finish execing #{command_i18n} on <a href='#{((@site_construct.get_port == "443") ? "https" : "http")}://#{@site_construct.domain_name}#{((@site_construct.get_port=="80" || @site_construct.get_port=="443" || @site_construct.get_port.blank?) ? "" : (':'+@site_construct.get_port))}'>#{@site_construct.domain_name}</a>") if @flag
|
|
update_infos_for_exec("finish execing #{command_i18n}")
|
|
elsif @thread
|
|
update_thread_infos_for_exec("finish execing #{command_i18n}")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
session.loop
|
|
if output_string
|
|
return outputs.join("\n")
|
|
else
|
|
return outputs
|
|
end
|
|
end
|
|
def exec_ssh_command_by_sudo_and_see_output(session,command,update=1,output_string=false)
|
|
outputs = exec_ssh_command_and_see_output(session,command,update)
|
|
tmp = outputs.join("\n")
|
|
if tmp.include?("Permission denied") || tmp.include?("Operation not permitted")
|
|
outputs = exec_ssh_command_and_see_output(session,"sudo -p 'sudo password:' #{command}",update)
|
|
tmp = outputs.join("\n")
|
|
end
|
|
if output_string
|
|
return tmp
|
|
else
|
|
return outputs
|
|
end
|
|
end
|
|
end |