Class: DaemonKit::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/daemon_kit/application.rb

Overview

Class responsible for making the daemons run and keep them running.

Class Method Summary collapse

Class Method Details

.exec(file) ⇒ Object

Run the specified file as a daemon process.

Raises:



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_logsObject

gist.github.com/304739

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

.stopObject



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