#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'rubygems' require 'optparse' require 'daemons' require 'fileutils' $LOAD_PATH << File.expand_path('../lib', File.dirname(__FILE__)) require 'tengine_core' @__config__ = Tengine::Core::Config::Core.parse(ARGV) Signal.trap(:INT) {puts ":INT"; @__bootstrap__.stop_kernel} # 必要なディレクトリの生成 FileUtils.mkdir_p(File.expand_path(@__config__[:process][:pid_dir])) FileUtils.mkdir_p(File.expand_path(@__config__[:tengined][:status_dir])) FileUtils.mkdir_p(File.expand_path(@__config__[:tengined][:activation_dir])) @__verbose__ = @__config__[:verbose] def verbose(msg, output = STDOUT) if @__verbose__ if block_given? output.puts("#{msg} begin") begin yield output.puts("#{msg} end") rescue Exception => e STDERR.puts("Exception occurred in #{msg}\n[#{e.class.name}] #{e.message}\n " << e.backtrace.join("\n ")) end else output.puts(msg) end else yield if block_given? end end verbose "define stop_process" do def stop_process(signal) verbose("stop_process") do pids = Dir.glob(File.expand_path(@__config__[:process][:pid_dir] + "/*")).map do |pid_path| File.open(pid_path, "r"){|f| f.gets.chomp.to_i} end results = pids.map{|pid| begin Process.kill(signal, pid) STDOUT.puts("Process stop successfully [#{pid}]") rescue # pid_dir には、古いpidファイルが残っていることを考慮して古いpidのkillシグナルの # 失敗は無視して起動しているプロセスに対してkillします verbose("warning: #$! [#{pid}]") end } end end end verbose "define show_status" do def show_status verbose("show_status") do pid_to_status = {} Dir.glob(File.expand_path(@__config__[:tengined][:status_dir] + "/*.status")).map do |status_filepath| pid_to_status[File.basename(status_filepath).scan(/\d+/).first.to_i] = File.read(status_filepath).chomp end pid_lines = [] pid_lines = `ps -opid -p #{pid_to_status.keys.join(',')}`.split(/\n/) unless pid_to_status.empty? living_pids = pid_lines.select{|line| line =~ /^\s*\d+\s*$/}.map(&:to_i) pid_to_status.each do |pid, status| puts "%6d %s" % [pid, living_pids.include?(pid) ? status : "terminated"] end end end end verbose "define run_daemons" do def run_daemons(options={}, &block) verbose("run_daemons") do daemonize_options = { :ARGV => ['start'], :ontop => !@__config__[:process][:daemon], :dir_mode => :normal, :dir => File.expand_path(@__config__[:process][:pid_dir]), # :log_dir => File.expand_path("../#{@__config__[:tengined][:log_dir]}", File.dirname(__FILE__)), # :log_output => false }.update(options) daemonize_options.update(:ARGV => ['start']) current_dir = Dir.pwd begin if @__config__[:action].to_sym == :start # pidファイルは、"tengined.0.pid"の数字の部分を連番でふります pids = Dir.glob("#{daemonize_options[:dir]}/tengined.*.pid") if pids.count == 0 max_pid_num = 0 else max_pid_num = pids.map{|pid_path| File.basename(pid_path).scan(/\d+/).first.to_i}.max.succ end pid_file_name = "#{File.basename(@__daemon_proc_path__)}.#{max_pid_num}" else pid_file_name = "#{File.basename(@__daemon_proc_path__)}_#{@__config__[:action]}" end Daemons.run_proc(pid_file_name, daemonize_options) do Dir.chdir(current_dir, &block) end rescue SystemExit => e verbose("Daemons.run_proc exit successfully") if e.status == 0 end end end end verbose "define make_activations" do def make_activations verbose("make_activations") do Dir.glob(File.expand_path(@__config__[:process][:pid_dir] + "/tengined.*.pid")).each do |pid_path| pid = File.open(pid_path, "r"){|f| f.gets.chomp} File.new(File.expand_path(@__config__[:tengined][:activation_dir] + "/tengined_#{pid}.activation"), "w").close end end end end verbose "define run" do def run(&block) verbose("run") do options = {} case @__config__[:action].to_sym when :stop then stop_process("HUP") when :force_stop then stop_process("KILL") when :status then show_status when :load then options = {:ontop => true} run_daemons(options, &block) when :test, :start, :enable then run_daemons(options, &block) when :activate then make_activations else verbose("Unknown action: #{@__config__[:action]}", STDERR) end end rescue SystemExit verbose("Exception occurred in run\n[#{$!.class.name}] #{$!.message}\n " << $!.backtrace.join("\n "), STDERR) raise rescue Exception verbose("Exception occurred in run\n[#{$!.class.name}] #{$!.message}\n " << $!.backtrace.join("\n "), STDERR) raise end end @__daemon_proc_path__ = File.expand_path(__FILE__) tengined_root = File.expand_path("..", File.expand_path(File.dirname(__FILE__))) if @__verbose__ verbose "configurations:" require 'pp'; pp @__config__.to_hash verbose "tengined_root: #{tengined_root}" end run do verbose "Dir.pwd: #{Dir.pwd}" config = nil begin config = @__config__ config.setup_loggers rescue Exception puts "[#{$!.class.name}] #{$!.message}\n " << $!.backtrace.join("\n ") raise end require 'mongoid' require File.expand_path('./lib/tengine_core', tengined_root) require 'tengine/core/mongoid_fix' Mongoid.configure do |c| c.send :load_configuration, config[:db] end require 'amqp' Mongoid.logger = AMQP::Session.logger = Tengine.logger Tengine::Core::MethodTraceable.disabled = !@__config__[:verbose] # Tengine::Core::Bootstrapが動く前に設定しないと余計なログが出ます @__bootstrap__ = Tengine::Core::Bootstrap.new(config) @__bootstrap__.boot end