Skip to content

Instantly share code, notes, and snippets.

@SpringMT
Created October 18, 2012 07:36
Show Gist options
  • Save SpringMT/3910306 to your computer and use it in GitHub Desktop.
Save SpringMT/3910306 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# encoding: UTF-8
require 'ap'
require 'optparse'
class UnicornStarter
def initialize(rails_env, rails_home, timeout)
@rails_env = rails_env
@rails_home = rails_home
@pid_file = "#{rails_home}/tmp/pids/unicorn.pid"
@timeout = timeout
end
def usage
puts "----- default -----"
puts "timeout : #{@timeout}"
puts "RAILS_ENV : #{@rails_env}"
puts "rails home : #{@rails_home}"
puts "----- usage -----"
puts "#{$0} {start|stop|restart|status} [-e RAILS_ENV] [-h RAILS_HOME] [-t timeout_sec]"
end
def start
exit 0 if is_unicorn_running?
cmd = "bundle exec unicorn -p 3000 -c #{@rails_home}/config/unicorn.rb -D"
pid = spawn({'RAILS_ENV' => @rails_env}, cmd)
# 起動するまで待つ
Process.waitpid pid
if File.exists? @pid_file
new_pid = open(@pid_file).read.to_i
end
unless new_pid
puts 'Failure'
exit 1
end
# 正常に起動できているか確認
begin
res = Process.kill(0, new_pid)
rescue => e
ap e.message
puts 'Failure! Check ps aux | grep "unicorn"'
exit 1
else
# killはシグナル送信に成功した場合、指定した pid の数返す
if res == 1
puts 'Success'
exit 0
else
puts 'Somethig wrong'
exit 1
end
end
end
def stop
exit 0 if is_unicorn_stop?
pid = open(@pid_file).read.to_i
puts "stop pid: #{pid}"
Process.kill :QUIT, pid
timeout_count = 0
# 正常に終了しているか確認
loop do
exit 1 if is_timeout?(@timeout, timeout_count)
if File.exists? @pid_file
print '.'
STDOUT.flush
else
begin
res = Process.kill(0, pid)
rescue => e
# プロセスがなくなると、例外が発生する
if e.message == 'No such process'
puts 'Success'
exit 0
end
end
end
sleep 1
timeout_count += 1
end
end
def restart
exit 0 if is_unicorn_stop?
exit 0 if is_unicorn_restarting?
old_pid = open(@pid_file).read.to_i
old_pid_file = "#{@pid_file}.oldbin"
puts "Send Signal USR2 to the pid: #{old_pid}"
Process.kill(:USR2, old_pid)
# 再起動が成功しているか確認
timeout_count = 0
new_pid = nil
loop do
exit 1 if is_timeout?(@timeout, timeout_count)
if new_pid
if File.exist?(old_pid_file)
print '.'
STDOUT.flush
else
if open(@pid_file).read.to_i == old_pid
puts 'Failure'
exit 1
else
puts 'Success'
exit 0
end
end
else
if File.exist? @pid_file
new_pid = open(@pid_file).read.to_i
end
end
sleep 1
timeout_count += 1
end
end
def status
old_pid_file = "#{@pid_file}.oldbin"
if File.exists? @pid_file
pid = open(@pid_file).read.to_i
if File.exists? old_pid_file
puts 'Restarting'
else
begin
res = Process.kill(0, pid)
rescue => e
if e.message == 'No such process'
puts "No such process : #{pid} ! check ps aux #{pid}"
end
else
if res == 1
puts 'Aready running unicorn'
else
puts 'Somethig Wrong'
end
end
end
else
if File.exists? old_pid_file
puts 'Aready Exist Old Pid. Please check ps aux | grep "unicorn"'
else
puts 'Not running unicorn.'
end
end
end
def method_missing(action, *args)
usage
end
private
def is_unicorn_stop?
if File.exists? @pid_file
old_pid = open(@pid_file).read.to_i
master_process = `ps aux #{old_pid}`
if master_process.empty?
puts 'Not running unicorn'
return true
end
else
puts 'No pid file. Start unicorn'
return true
end
return false
end
def is_unicorn_running?
if File.exists? @pid_file
old_pid = open(@pid_file).read.to_i
master_process = `ps aux #{old_pid}`
unless master_process.empty?
puts 'Aready running'
return true
end
end
return false
end
def is_unicorn_restarting?
if File.exists? "#{@pid_file}.oldbin"
puts 'Still restarting'
return true
end
return false
end
def is_timeout?(timeout, count)
if count > timeout
puts 'Timeout'
return true
end
return false
end
end
## script
# initial
action = ARGV.shift || ''
rails_env = 'production'
rails_home = "#{ENV['HOME']}/app"
timeout = 30
opt = OptionParser.new(ARGV)
opt.on('-e rails_env') {|e| rails_env = e }
opt.on('-h rails_home') {|h| rails_home = h }
opt.on('-t timeout_sec') {|t| timeout = t.to_i }
opt.parse!
unicorn = UnicornStarter.new(rails_env, rails_home, timeout)
unicorn.send action
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment