class Nand::Daemon
Attributes
execname[R]
run_dir[R]
Public Class Methods
new(run_dir, execname, opts = {} )
click to toggle source
# File lib/nand/daemon.rb, line 15 def initialize(run_dir, execname, opts = {} ) @run_dir = Pathname.new(run_dir) @execname = execname.to_s @launcher = opts[:launcher] @arg_uid = opts[:uid] @pid_file = @run_dir.join(self.class.pid_filename(@execname)) @daemon_log = opts[:daemon_log] || "/dev/null" @daemon_out = opts[:daemon_out] || "/dev/null" @daemon_err = opts[:daemon_err] || "/dev/null" @recovery = opts[:recovery] || false @recovery_sec = opts[:recovery_sec] || 1 @limit = opts[:sec] log.level = LOG_DEBUG if opts[:debug] end
Public Instance Methods
kill()
click to toggle source
# File lib/nand/daemon.rb, line 44 def kill; stop_with_signal(:KILL) end
logger_formatter()
click to toggle source
# File lib/nand/daemon.rb, line 12 def logger_formatter ; TimeFormatter.new end
logger_output_params()
click to toggle source
# File lib/nand/daemon.rb, line 10 def logger_output_params ; [@daemon_log] end
logger_progname()
click to toggle source
# File lib/nand/daemon.rb, line 11 def logger_progname ; @execname end
pid()
click to toggle source
# File lib/nand/daemon.rb, line 45 def pid; @pid ||=self.class.pid_from_pidfile(@pid_file) end
run()
click to toggle source
# File lib/nand/daemon.rb, line 38 def run raise "Launcher is Not Specified for #{@execname}" if @launcher.nil? raise "PID file exist #{@pid_file}" if @pid_file.exist? daemonize end
running?()
click to toggle source
# File lib/nand/daemon.rb, line 36 def running?; @pid_file.exist? and self.class.running_with?(pid, @execname) end
stop()
click to toggle source
# File lib/nand/daemon.rb, line 43 def stop; stop_with_signal(:TERM) end
uid()
click to toggle source
# File lib/nand/daemon.rb, line 35 def uid; @arg_uid || Process.uid end
user()
click to toggle source
# File lib/nand/daemon.rb, line 30 def user Etc.getpwuid(uid).name rescue => e nil end
Private Instance Methods
daemonize( &block )
click to toggle source
# File lib/nand/daemon.rb, line 48 def daemonize( &block ) if child = Process.fork Process.waitpid(child) # wait until exit child process return child end Process.setsid exit(0) if Process.fork # double fork and exit child process Process.setsid Dir.chdir(@run_dir) File.umask(0) STDIN.reopen("/dev/null") STDOUT.reopen(@daemon_out) STDERR.reopen(@daemon_err) begin File.open(@pid_file, "w"){|fs| fs.puts Process.pid } log.info "Daemonize [#{Process.pid}]" Signal.trap(:INT) {Thread.new{log.warn("RECEVIED Signal INT") ; send_signal_and_exit(:INT)}} Signal.trap(:TERM) {Thread.new{log.warn("RECEVIED Signal TERM") ; send_signal_and_exit(:TERM)}} begin sleep 0.1 @child = @launcher.launch raise "Failed Launch for #{@execname}" if @child.nil? log.info "Launched Child Process [#{@child}]" wait_untill_limit if !@limit.nil? and 0 < @limit Process.waitpid2(@child) unless @child.nil? log.warn "PID #{@child} down" sleep @recovery_sec if @recovery end while @recovery rescue => e log.fatal e.message log.debug "\n\t" + e.backtrace.join("\n\t") ensure terminate end end
send_signal_and_exit(type)
click to toggle source
# File lib/nand/daemon.rb, line 97 def send_signal_and_exit(type) Process.kill(type, -@child) unless @child.nil? log.warn "Sent Signal #{type} to #{@child}" terminate rescue => e log.fatal "Failed Send Signal to -#{@child}, since #{e.message}" terminate -1 end
stop_with_signal(signal)
click to toggle source
# File lib/nand/daemon.rb, line 106 def stop_with_signal(signal) raise "Can Not Send #{signal.to_s.capitalize} Signal to #{@execname}" unless uid == Process.uid or uid == 0 unless running? @pid_file.delete if @pid_file.exist? raise "#{@execname} is Not Running" end Process.kill(signal, pid) end
terminate( code = 0 )
click to toggle source
# File lib/nand/daemon.rb, line 89 def terminate( code = 0 ) unless @child.nil? log.info "terminate for #{@child} with exit code #{code}" @child = nil end @pid_file.delete if @pid_file.exist? exit code end
wait_untill_limit()
click to toggle source
# File lib/nand/daemon.rb, line 114 def wait_untill_limit Signal.trap(:SIGCHLD) {terminate} pid, status = Process.waitpid2(@child, Process::WNOHANG) if pid.nil? log.info "Child[#{@child}] will be Stopped after #{@limit} sec" sleep @limit Signal.trap(:SIGCHLD, "IGNORE") log.info "Send Signal TERM to Child[#{@child}] #{@limit} sec past" Process.kill(:TERM, @child) end end