Class: Process::Daemon

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

Overview

Provides the infrastructure for spawning a daemon.

Defined Under Namespace

Modules: Privileges Classes: Controller, Listen, LogFile, Notification, ProcessFile

Constant Summary collapse

VERSION =
"1.0.1"
TIMEOUT =

Daemon startup timeout

5

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(working_directory = ".") ⇒ Daemon

Initialize the daemon in the given working root.



34
35
36
37
38
# File 'lib/process/daemon.rb', line 34

def initialize(working_directory = ".")
	@working_directory = working_directory
	
	@shutdown_notification = Notification.new
end

Instance Attribute Details

#titleObject

The process title of the daemon.



110
111
112
# File 'lib/process/daemon.rb', line 110

def title
  @title
end

#working_directoryObject (readonly)

The directory the daemon will run in.



46
47
48
# File 'lib/process/daemon.rb', line 46

def working_directory
  @working_directory
end

Class Method Details

.controller(options = {}) ⇒ Object

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



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

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

.daemonize(*args, **options) ⇒ Object

The main entry point for daemonized scripts.



177
178
179
180
181
# File 'lib/process/daemon.rb', line 177

def daemonize(*args, **options)
	args = ARGV if args.empty?
	
	controller(options).daemonize(args)
end

.instanceObject

A shared instance of the daemon.



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

def instance
	@instance ||= self.new
end

.startObject

Start the shared daemon instance.



184
185
186
# File 'lib/process/daemon.rb', line 184

def start
	controller.start
end

.statusObject

Check if the shared daemon instance is runnning or not.



194
195
196
# File 'lib/process/daemon.rb', line 194

def status
	controller.status
end

.stopObject

Stop the shared daemon instance.



189
190
191
# File 'lib/process/daemon.rb', line 189

def 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)


85
86
87
88
89
90
91
92
93
94
95
# File 'lib/process/daemon.rb', line 85

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

#log_directoryObject

Return the directory to store log files in.



49
50
51
# File 'lib/process/daemon.rb', line 49

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

#log_file_pathObject

Standard log file for stdout and stderr.



54
55
56
# File 'lib/process/daemon.rb', line 54

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

#mark_logObject

Mark the output log.



69
70
71
72
73
# File 'lib/process/daemon.rb', line 69

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

#nameObject

Return the name of the daemon



41
42
43
# File 'lib/process/daemon.rb', line 41

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

#preforkObject

The main function to setup any environment required by the daemon



98
99
100
101
102
103
104
105
106
107
# File 'lib/process/daemon.rb', line 98

def prefork
	# Ignore any previously setup signal handler for SIGINT:
	trap(:INT, :DEFAULT)
	
	# We update the working directory to a full path:
	@working_directory = File.expand_path(working_directory)
	
	FileUtils.mkdir_p(log_directory)
	FileUtils.mkdir_p(runtime_directory)
end

#process_file_pathObject

Standard location of process pid file.



64
65
66
# File 'lib/process/daemon.rb', line 64

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

#request_shutdownObject

Request that the sleep_until_interrupted function call returns.



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

def request_shutdown
	@shutdown_notification.signal
end

#runObject

If you want to implement a long running process you override this method. You may like to call super but it is not necessary to use the supplied interruption machinery.



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

def run
	sleep_until_interrupted
end

#runtime_directoryObject

Runtime data directory for the daemon.



59
60
61
# File 'lib/process/daemon.rb', line 59

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

#shutdownObject

This function should terminate any active processes in the daemon and return as quickly as possible.



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

def shutdown
end

#sleep_until_interruptedObject

Call this function to sleep until the daemon is sent SIGINT.



129
130
131
132
133
134
135
# File 'lib/process/daemon.rb', line 129

def sleep_until_interrupted
	trap(:INT) do
		self.request_shutdown
	end

	@shutdown_notification.wait
end

#spawnObject

The entry point from the newly forked process.



151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/process/daemon.rb', line 151

def spawn
	self.title = self.name
	
	self.startup
	
	begin
		self.run
	rescue Interrupt
		$stderr.puts "Daemon interrupted, proceeding to shutdown."
	end
	
	self.shutdown
end

#startupObject

This function must setup the daemon quickly and return.



138
139
# File 'lib/process/daemon.rb', line 138

def startup
end

#tail_log(output) ⇒ Object

Prints some information relating to daemon startup problems.



76
77
78
79
80
81
82
# File 'lib/process/daemon.rb', line 76

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