Class: Process::Daemon

Inherits:
Object
  • Object
show all
Defined in:
lib/process/daemon.rb,
lib/process/daemon/version.rb,
lib/process/daemon/log_file.rb,
lib/process/daemon/controller.rb,
lib/process/daemon/priviledges.rb,
lib/process/daemon/process_file.rb

Overview

This class is the base daemon class. If you are writing a daemon, you should inherit from this class.

The basic structure of a daemon is as follows: class Server < Process::Daemon def startup # Long running process, e.g. web server, game server, etc. end def shutdown # Stop the process above, usually called on SIGINT. end end Server.daemonize

The base directory specifies a path such that:

working_directory = "."
log_directory = #{working_directory}/log
log_file_path = #{log_directory}/#{daemon_name}.log
runtime_directory = #{working_directory}/run
process_file_path = #{runtime_directory}/#{daemon_name}.pid

Defined Under Namespace

Modules: Priviledges Classes: Controller, LogFile, ProcessFile

Constant Summary collapse

VERSION =
"0.5.0"
TIMEOUT =

Daemon startup timeout

5

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_directory = ".") ⇒ Daemon

Returns a new instance of Daemon.



52
53
54
# File 'lib/process/daemon.rb', line 52

def initialize(base_directory = ".")
  @base_directory = base_directory
end

Class Method Details

.controller(options = {}) ⇒ Object

The process controller, responsible for managing the daemon process start, stop, restart, etc.



147
148
149
# File 'lib/process/daemon.rb', line 147

def self.controller(options = {})
  @controller ||= Controller.new(instance, options)
end

.daemonize(*args) ⇒ Object

The main entry point for daemonized scripts.



152
153
154
155
156
157
158
# File 'lib/process/daemon.rb', line 152

def self.daemonize(*args)
  # Wish Ruby 2.0 kwargs were backported to 1.9.3... oh well:
  options = (args.last === Hash) ? args.pop : {}
  argv = (args.last === Array) ? args.pop : ARGV
  
  controller(options).daemonize(argv)
end

.instanceObject

A shared instance of the daemon.



142
143
144
# File 'lib/process/daemon.rb', line 142

def self.instance
  @instance ||= self.new
end

.startObject

Start the daemon instance.



161
162
163
# File 'lib/process/daemon.rb', line 161

def self.start
  controller.start
end

.statusObject

Check if the daemon is runnning or not.



171
172
173
# File 'lib/process/daemon.rb', line 171

def self.status
  controller.status
end

.stopObject

Stop the daemon instance.



166
167
168
# File 'lib/process/daemon.rb', line 166

def self.stop
  controller.stop
end

Instance Method Details

#crashed?Boolean

Check the last few lines of the log file to find out if the daemon crashed.

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
# File 'lib/process/daemon.rb', line 103

def crashed?
  count = 3
  
  LogFile.open(log_file_path).tail_log do |line|
    return true if line.match("=== Daemon Crashed")

    break if (count -= 1) == 0
  end

  return false
end

#daemon_nameObject

Return the name of the daemon



57
58
59
# File 'lib/process/daemon.rb', line 57

def daemon_name
  return self.class.name.gsub(/[^a-zA-Z0-9]+/, '-')
end

#log_directoryObject

Return the directory to store log files in.



67
68
69
# File 'lib/process/daemon.rb', line 67

def log_directory
  File.join(working_directory, "log")
end

#log_file_pathObject

Standard log file for stdout and stderr.



72
73
74
# File 'lib/process/daemon.rb', line 72

def log_file_path
  File.join(log_directory, "#{daemon_name}.log")
end

#mark_logObject

Mark the output log.



87
88
89
90
91
# File 'lib/process/daemon.rb', line 87

def mark_log
  File.open(log_file_path, "a") do |log_file|
    log_file.puts "=== Log Marked @ #{Time.now.to_s} ==="
  end
end

#preforkObject

The main function to setup any environment required by the daemon



116
117
118
119
120
121
# File 'lib/process/daemon.rb', line 116

def prefork
  @base_directory = File.expand_path(@base_directory) if @base_directory

  FileUtils.mkdir_p(log_directory)
  FileUtils.mkdir_p(runtime_directory)
end

#process_file_pathObject

Standard location of process pid file.



82
83
84
# File 'lib/process/daemon.rb', line 82

def process_file_path
  File.join(runtime_directory, "#{daemon_name}.pid")
end

#runObject



133
134
135
136
137
138
139
# File 'lib/process/daemon.rb', line 133

def run
  startup
  
  trap("INT") do
    shutdown
  end
end

#runtime_directoryObject

Runtime data directory for the daemon.



77
78
79
# File 'lib/process/daemon.rb', line 77

def runtime_directory
  File.join(working_directory, "run")
end

#shutdownObject

The main function to stop the daemon



128
129
130
131
# File 'lib/process/daemon.rb', line 128

def shutdown
  # Interrupt all children processes, preferably to stop them so that they are not left behind.
  Process.kill(0, :INT)
end

#startupObject

The main function to start the daemon



124
125
# File 'lib/process/daemon.rb', line 124

def startup
end

#tail_log(output) ⇒ Object

Prints some information relating to daemon startup problems.



94
95
96
97
98
99
100
# File 'lib/process/daemon.rb', line 94

def tail_log(output)
  lines = LogFile.open(log_file_path).tail_log do |line|
    line.match("=== Log Marked") || line.match("=== Daemon Exception Backtrace")
  end
  
  output.puts lines
end

#working_directoryObject

The directory the daemon will run in.



62
63
64
# File 'lib/process/daemon.rb', line 62

def working_directory
  @base_directory
end