2020-04-28 13:26:49 +00:00
require 'net/ssh'
require 'pathname'
2021-01-19 04:48:03 +00:00
namespace :exec_commands do
desc " Exec commands Script "
task :exec_commands , [ :site_construct_id , :commands , :type , :server_name ] = > :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?
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 = default_rails_env
log_files = exec_ssh_command_by_sudo_and_see_output ( ssh , " ls -t ' #{ @site_construct . path } / #{ @site_construct . site_name } /log' " , false ) . flat_map { | output | output . split ( / ( \ r \ n| \ t| \ n| \ s+) / ) } . select { | output | output . present? && / ( \ r \ n| \ t| \ n| \ s+) / . match ( output ) . nil? } rescue [ ]
log_files . each do | log_file |
if ( enable_rails_env . include? ( log_file . sub ( '.log' , '' ) ) rescue false )
rails_env = log_file . sub ( '.log' , '' )
break
end
end
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 } \n kill -s TERM `fuser tmp/unicorn.sock` \n sudo -p \" sudo password: \" kill -s TERM `sudo -p \" sudo password: \" fuser tmp/unicorn.sock` \n sudo -p \" sudo password: \" rm -f tmp/pids/unicorn.pid \n bundle 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
end
end
update_infos_for_exec ( " finish starting #{ @site_construct . site_name } " )
@site_construct . update ( :status = > " finish " )
elsif args . type == 'exec_all'
sites = SiteConstruct . where ( :server_type = > args . server_name ) . to_a
commands = args . commands . split ( " //// " ) . select { | c | c != " " } rescue [ args . commands ]
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 " )
commands . each do | command |
exec_ssh_command_by_sudo_and_see_output ( ssh , " bash -l -c 'cd #{ @site_construct . path } / #{ @site_construct . site_name } ; #{ command } ' " )
end
2020-04-28 13:26:49 +00:00
end
else
2021-01-19 04:48:03 +00:00
exec_ssh_command_by_sudo ( ssh , " chmod 777 #{ @site_construct . path } / #{ @site_construct . site_name } -R " )
commands = args . commands . split ( " //// " ) . select { | c | c != " " } rescue [ args . commands ]
commands . each do | command |
exec_ssh_command_by_sudo_and_see_output ( ssh , " bash -l -c 'cd #{ @site_construct . path } / #{ @site_construct . site_name } ; #{ command } ' " )
end
2020-04-28 13:26:49 +00:00
end
end
end
2021-01-19 04:48:03 +00:00
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
2020-04-28 13:26:49 +00:00
end
2021-01-19 04:48:03 +00:00
end
2020-04-28 13:26:49 +00:00
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
end
2021-01-19 04:48:03 +00:00
def update_infos_for_exec ( info , update_last = false )
if update_last && ! @site_construct . infos . empty?
@site_construct . infos [ - 1 ] += info . to_s
else
@site_construct . infos = @site_construct . infos . push ( info . to_s )
end
2020-04-28 13:26:49 +00:00
@site_construct . save!
return @site_construct . infos
end
2021-01-19 04:48:03 +00:00
def update_thread_infos_for_exec ( info , update_last = false )
if update_last && ! @thread . status [ " infos " ] . empty?
@thread . status [ " infos " ] [ - 1 ] += info . to_s
else
@thread . status [ " infos " ] = @thread . status [ " infos " ] . push ( info . to_s )
end
@thread . save!
return @thread . status [ " infos " ]
end
def exec_ssh_command_and_see_output ( session , command , update = true )
outputs = [ ]
@flag = ( @type == " exec_all " )
if update
update_thread_infos_for_exec ( " execing #{ command } on on <a href=' #{ ( ( @site_construct . port == " 443 " ) ? " https " : " http " ) } :// #{ @site_construct . domain_name } #{ ( ( @site_construct . port == " 80 " || @site_construct . port == " 443 " ) ? " " : ( ':' + @site_construct . port ) ) } '> #{ @site_construct . domain_name } </a> " ) if @flag
update_infos_for_exec ( " execing #{ command } " )
end
session . open_channel do | channel |
channel . request_pty do | channel , success |
channel . exec ( command ) do | ch , success |
abort " could not execute command: #{ command } " unless success
channel . on_data do | ch , data |
print " #{ data } "
if data . include? " \n " || outputs . empty?
outputs . push ( data . to_s )
if update
update_thread_infos_for_exec ( data ) if @flag
update_infos_for_exec ( data )
end
else
outputs [ - 1 ] += data . to_s rescue " "
if update
update_thread_infos_for_exec ( data , true ) if @flag
update_infos_for_exec ( data , true )
end
end
if data . to_s . include? ( " sudo password: " ) || data . to_s . include? ( " Password: " )
channel . send_data " #{ @password } \n "
end
end
channel . on_close do | ch |
if update
update_thread_infos_for_exec ( " finish execing #{ command } on <a href=' #{ ( ( @site_construct . port == " 443 " ) ? " https " : " http " ) } :// #{ @site_construct . domain_name } #{ ( ( @site_construct . port == " 80 " || @site_construct . port == " 443 " ) ? " " : ( ':' + @site_construct . port ) ) } '> #{ @site_construct . domain_name } </a> " ) if @flag
update_infos_for_exec ( " finish execing #{ command } " )
end
end
end
end
end
session . loop
return outputs
end
def exec_ssh_command_by_sudo_and_see_output ( session , command , update = true )
outputs = exec_ssh_command_and_see_output ( session , command , update )
if outputs . join ( " \n " ) . include? ( " Permission denied " ) || outputs . join ( " \n " ) . include? ( " Operation not permitted " )
outputs = exec_ssh_command_and_see_output ( session , " sudo -p 'sudo password:' #{ command } " , update )
end
return outputs
end
2020-04-28 13:26:49 +00:00
end