Class: DaemonKit::Application
Overview
Class responsible for making the daemons run and keep them running.
Class Method Summary collapse
-
.exec(file) ⇒ Object
Run the specified file as a daemon process.
-
.exit!(code = 0) ⇒ Object
Exit the daemon TODO: Make configurable callback chain TODO: Hook into at_exit().
- .reopen_logs ⇒ Object
-
.run(file) ⇒ Object
Run the daemon in the foreground without daemonizing.
-
.running! {|DaemonKit.configuration| ... } ⇒ Object
Call this from inside a daemonized process to complete the initialization process.
-
.start(file) ⇒ Object
Run our file properly.
- .stop ⇒ Object
Class Method Details
.exec(file) ⇒ Object
Run the specified file as a daemon process.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/daemon_kit/application.rb', line 11 def exec( file ) raise DaemonNotFound.new( file ) unless File.exist?( file ) DaemonKit.configuration.daemon_name ||= File.basename( file ) command, configs, args = Arguments.parse( ARGV ) case command when :run parse_arguments( args ) run( file ) when :start parse_arguments( args ) start( file ) when :stop stop end end |
.exit!(code = 0) ⇒ Object
Exit the daemon TODO: Make configurable callback chain TODO: Hook into at_exit()
101 102 |
# File 'lib/daemon_kit/application.rb', line 101 def exit!( code = 0 ) end |
.reopen_logs ⇒ Object
Stolen from Unicorn::Util
This reopens ALL logfiles in the process that have been rotated using logrotate(8) (without copytruncate) or similar tools. A File
object is considered for reopening if it is:
1) opened with the O_APPEND and O_WRONLY flags
2) opened with an absolute path (starts with "/")
3) the current open file handle does not match its original open path
4) unbuffered (as far as userspace buffering goes, not O_SYNC)
Returns the number of files reopened
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/daemon_kit/application.rb', line 116 def reopen_logs nr = 0 append_flags = File::WRONLY | File::APPEND DaemonKit.logger.info "Rotating logs" if DaemonKit.logger #logs = [STDOUT, STDERR] #logs.each do |fp| ObjectSpace.each_object(File) do |fp| next if fp.closed? next unless (fp.sync && fp.path[0..0] == "/") next unless (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags begin a, b = fp.stat, File.stat(fp.path) next if a.ino == b.ino && a.dev == b.dev rescue Errno::ENOENT end open_arg = 'a' if fp.respond_to?(:external_encoding) && enc = fp.external_encoding open_arg << ":#{enc.to_s}" enc = fp.internal_encoding and open_arg << ":#{enc.to_s}" end DaemonKit.logger.info "Rotating path: #{fp.path}" if DaemonKit.logger fp.reopen(fp.path, open_arg) fp.sync = true nr += 1 end # each_object nr end |
.run(file) ⇒ Object
Run the daemon in the foreground without daemonizing
31 32 33 34 35 36 37 38 39 |
# File 'lib/daemon_kit/application.rb', line 31 def run( file ) self.chroot self.clean_fd self.redirect_io( true ) DaemonKit.configuration.log_stdout = true require file end |
.running! {|DaemonKit.configuration| ... } ⇒ Object
Call this from inside a daemonized process to complete the initialization process
92 93 94 95 96 |
# File 'lib/daemon_kit/application.rb', line 92 def running! Initializer.continue! yield DaemonKit.configuration if block_given? end |
.start(file) ⇒ Object
Run our file properly
42 43 44 45 46 47 48 49 50 |
# File 'lib/daemon_kit/application.rb', line 42 def start( file ) self.drop_privileges self.daemonize self.chroot self.clean_fd self.redirect_io require file end |
.stop ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/daemon_kit/application.rb', line 52 def stop @pid_file = PidFile.new( DaemonKit.configuration.pid_file ) unless @pid_file.running? @pid_file.cleanup puts "Nothing to stop" exit end target_pid = @pid_file.pid puts "Sending TERM to #{target_pid}" Process.kill( 'TERM', target_pid ) if seconds = DaemonKit.configuration.force_kill_wait begin Timeout::timeout( seconds ) do loop do puts "Waiting #{seconds} seconds for #{target_pid} before sending KILL" break unless @pid_file.running? seconds -= 1 sleep 1 end end rescue Timeout::Error Process.kill( 'KILL', target_pid ) end end if @pid_file.running? puts "Process still running, leaving pidfile behind! Consider using configuration.force_kill_wait." else @pid_file.cleanup end end |