kennethkalmer-daemon-kit 0.1.6 → 0.1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Configuration.txt +58 -0
- data/History.txt +16 -0
- data/Manifest.txt +29 -2
- data/PostInstall.txt +1 -1
- data/{README.textile → README.rdoc} +31 -19
- data/Rakefile +2 -4
- data/TODO.txt +6 -5
- data/app_generators/daemon_kit/daemon_kit_generator.rb +29 -0
- data/app_generators/daemon_kit/templates/Rakefile +3 -1
- data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
- data/app_generators/daemon_kit/templates/config/boot.rb +2 -2
- data/app_generators/daemon_kit/templates/script/console +3 -0
- data/app_generators/daemon_kit/templates/script/destroy +14 -0
- data/app_generators/daemon_kit/templates/script/generate +14 -0
- data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
- data/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
- data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
- data/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
- data/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
- data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +51 -0
- data/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
- data/lib/daemon_kit/application.rb +135 -11
- data/lib/daemon_kit/arguments.rb +151 -0
- data/lib/daemon_kit/commands/console.rb +38 -0
- data/lib/daemon_kit/config.rb +1 -0
- data/lib/daemon_kit/console_daemon.rb +2 -0
- data/lib/daemon_kit/core_ext/string.rb +22 -0
- data/lib/daemon_kit/core_ext.rb +1 -0
- data/lib/daemon_kit/deployment/capistrano.rb +485 -0
- data/lib/daemon_kit/initializer.rb +87 -25
- data/lib/daemon_kit/pid_file.rb +61 -0
- data/lib/daemon_kit/tasks/environment.rake +5 -4
- data/lib/daemon_kit/tasks/framework.rake +15 -1
- data/lib/daemon_kit/tasks/god.rake +62 -0
- data/lib/daemon_kit/tasks/monit.rake +29 -0
- data/lib/daemon_kit.rb +11 -5
- data/rubygems_generators/install_rspec/templates/spec/spec_helper.rb +1 -1
- data/spec/argument_spec.rb +51 -0
- data/spec/config_spec.rb +77 -0
- data/spec/daemon_kit_spec.rb +2 -2
- data/spec/fixtures/env.yml +15 -0
- data/spec/fixtures/noenv.yml +4 -0
- data/spec/initializer_spec.rb +4 -3
- data/spec/spec_helper.rb +8 -11
- data/templates/god/god.erb +69 -0
- data/templates/monit/monit.erb +14 -0
- data/test/test_daemon-kit_generator.rb +15 -1
- data/test/test_deploy_capistrano_generator.rb +48 -0
- metadata +41 -21
- data/lib/daemon_kit/patches/force_kill_wait.rb +0 -120
@@ -3,7 +3,15 @@ require 'pathname'
|
|
3
3
|
|
4
4
|
DAEMON_ENV = (ENV['DAEMON_ENV'] || 'development').dup unless defined?(DAEMON_ENV)
|
5
5
|
|
6
|
-
|
6
|
+
# Absolute paths to the daemon_kit libraries added to $:
|
7
|
+
incdir = ( File.dirname(__FILE__) + '/..' )
|
8
|
+
absincdir = if RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
9
|
+
File.expand_path( incdir )
|
10
|
+
else
|
11
|
+
File.expand_path( Pathname.new( incdir ).realpath.to_s )
|
12
|
+
end
|
13
|
+
$:.unshift absincdir unless $:.include?( absincdir )
|
14
|
+
|
7
15
|
require 'daemon_kit'
|
8
16
|
|
9
17
|
module DaemonKit
|
@@ -26,17 +34,29 @@ module DaemonKit
|
|
26
34
|
@configuration = configuration
|
27
35
|
end
|
28
36
|
|
37
|
+
def arguments
|
38
|
+
@arguments
|
39
|
+
end
|
40
|
+
|
41
|
+
def arguments=( args )
|
42
|
+
@arguments = args
|
43
|
+
end
|
44
|
+
|
29
45
|
def trap( *args, &block )
|
30
46
|
self.configuration.trap( *args, &block )
|
31
47
|
end
|
32
48
|
|
33
49
|
def framework_root
|
34
|
-
File.join( File.dirname(__FILE__), '..', '..' )
|
50
|
+
@framework_root ||= File.join( File.dirname(__FILE__), '..', '..' ).to_absolute_path
|
35
51
|
end
|
36
52
|
|
37
53
|
def root
|
38
54
|
DAEMON_ROOT
|
39
55
|
end
|
56
|
+
|
57
|
+
def env
|
58
|
+
DAEMON_ENV
|
59
|
+
end
|
40
60
|
end
|
41
61
|
|
42
62
|
|
@@ -46,7 +66,9 @@ module DaemonKit
|
|
46
66
|
|
47
67
|
attr_reader :configuration
|
48
68
|
|
49
|
-
def self.run
|
69
|
+
def self.run
|
70
|
+
configuration = DaemonKit.configuration || Configuration.new
|
71
|
+
|
50
72
|
yield configuration if block_given?
|
51
73
|
initializer = new configuration
|
52
74
|
initializer.before_daemonize
|
@@ -83,6 +105,8 @@ module DaemonKit
|
|
83
105
|
|
84
106
|
include_core_lib
|
85
107
|
load_postdaemonize_configs
|
108
|
+
|
109
|
+
set_process_name
|
86
110
|
end
|
87
111
|
|
88
112
|
def set_load_path
|
@@ -96,9 +120,7 @@ module DaemonKit
|
|
96
120
|
end
|
97
121
|
|
98
122
|
def load_patches
|
99
|
-
|
100
|
-
require 'daemon_kit/patches/force_kill_wait'
|
101
|
-
end
|
123
|
+
|
102
124
|
end
|
103
125
|
|
104
126
|
def load_environment
|
@@ -159,6 +181,10 @@ module DaemonKit
|
|
159
181
|
require core_lib
|
160
182
|
end
|
161
183
|
end
|
184
|
+
|
185
|
+
def set_process_name
|
186
|
+
$0 = configuration.daemon_name
|
187
|
+
end
|
162
188
|
end
|
163
189
|
|
164
190
|
# Holds our various configuration values
|
@@ -175,21 +201,15 @@ module DaemonKit
|
|
175
201
|
# Path to the log file, defaults to 'log/<environment>.log'
|
176
202
|
attr_accessor :log_path
|
177
203
|
|
178
|
-
# :system,
|
179
|
-
attr_accessor :dir_mode
|
180
|
-
|
181
|
-
# Path to the log file, defaults to 'log/<environment>.log'
|
182
|
-
attr_accessor :dir
|
183
|
-
|
184
204
|
# Provide a custom logger to use
|
185
205
|
attr_accessor :logger
|
186
206
|
|
207
|
+
# Path to the pid file, defaults to 'log/<daemon_name>.pid'
|
208
|
+
attr_accessor :pid_file
|
209
|
+
|
187
210
|
# The application name
|
188
211
|
attr_accessor :daemon_name
|
189
212
|
|
190
|
-
# Allow multiple copies to run?
|
191
|
-
attr_accessor :multiple
|
192
|
-
|
193
213
|
# Use the force kill patch? Give the number of seconds
|
194
214
|
attr_accessor :force_kill_wait
|
195
215
|
|
@@ -200,6 +220,8 @@ module DaemonKit
|
|
200
220
|
attr_accessor :safety_net
|
201
221
|
|
202
222
|
def initialize
|
223
|
+
parse_arguments!
|
224
|
+
|
203
225
|
set_root_path!
|
204
226
|
set_daemon_defaults!
|
205
227
|
|
@@ -207,7 +229,6 @@ module DaemonKit
|
|
207
229
|
self.log_level = default_log_level
|
208
230
|
self.log_path = default_log_path
|
209
231
|
|
210
|
-
self.multiple = false
|
211
232
|
self.force_kill_wait = false
|
212
233
|
|
213
234
|
self.safety_net = DaemonKit::Safety.instance
|
@@ -240,6 +261,10 @@ module DaemonKit
|
|
240
261
|
@signal_traps[signal].unshift( proc || block )
|
241
262
|
end
|
242
263
|
|
264
|
+
def pid_file
|
265
|
+
@pid_file ||= "#{File.dirname(self.log_path)}/#{self.daemon_name}.pid"
|
266
|
+
end
|
267
|
+
|
243
268
|
protected
|
244
269
|
|
245
270
|
def run_traps( signal )
|
@@ -255,28 +280,55 @@ module DaemonKit
|
|
255
280
|
Signal.trap( signal, Proc.new { self.run_traps( signal ) } )
|
256
281
|
end
|
257
282
|
|
283
|
+
def parse_arguments!
|
284
|
+
configs = Arguments.configuration( ARGV ).first
|
285
|
+
@unused_arguments = {}
|
286
|
+
|
287
|
+
configs.each do |c|
|
288
|
+
k,v = c.split('=')
|
289
|
+
|
290
|
+
if v.nil?
|
291
|
+
error( "#{k} has no value" )
|
292
|
+
next
|
293
|
+
end
|
294
|
+
|
295
|
+
begin
|
296
|
+
if self.respond_to?( k )
|
297
|
+
self.send( "#{k}=", v ) # pid_file = /var/run/foo.pid
|
298
|
+
else
|
299
|
+
@unused_arguments[ k ] = v
|
300
|
+
end
|
301
|
+
rescue => e
|
302
|
+
error( "Couldn't set `#{k}' to `#{v}': #{e.message}" )
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# DANGEROUS: Change the value of DAEMON_ENV
|
308
|
+
def environment=( env )
|
309
|
+
::DAEMON_ENV.replace( env )
|
310
|
+
end
|
311
|
+
|
258
312
|
def set_root_path!
|
259
313
|
raise "DAEMON_ROOT is not set" unless defined?(::DAEMON_ROOT)
|
260
|
-
raise "DAEMON_ROOT is not a directory" unless
|
314
|
+
raise "DAEMON_ROOT is not a directory" unless File.directory?(::DAEMON_ROOT)
|
261
315
|
|
262
|
-
@root_path =
|
316
|
+
@root_path = ::DAEMON_ROOT.to_absolute_path
|
263
317
|
# Pathname is incompatible with Windows, but Windows doesn't have
|
264
318
|
# real symlinks so File.expand_path is safe.
|
265
|
-
if RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
266
|
-
|
319
|
+
#if RUBY_PLATFORM =~ /(:?mswin|mingw)/
|
320
|
+
# File.expand_path(::DAEMON_ROOT)
|
267
321
|
|
268
322
|
# Otherwise use Pathname#realpath which respects symlinks.
|
269
|
-
else
|
270
|
-
|
271
|
-
end
|
323
|
+
#else
|
324
|
+
# File.expand_path( Pathname.new(::DAEMON_ROOT).realpath.to_s )
|
325
|
+
#end
|
272
326
|
|
273
327
|
Object.const_set(:RELATIVE_DAEMON_ROOT, ::DAEMON_ROOT.dup) unless defined?(::RELATIVE_DAEMON_ROOT)
|
274
328
|
::DAEMON_ROOT.replace @root_path
|
275
329
|
end
|
276
330
|
|
277
331
|
def set_daemon_defaults!
|
278
|
-
self.dir_mode = :normal
|
279
|
-
self.dir = File.join( DAEMON_ROOT, 'log' )
|
280
332
|
end
|
281
333
|
|
282
334
|
def default_load_paths
|
@@ -290,6 +342,16 @@ module DaemonKit
|
|
290
342
|
def default_log_level
|
291
343
|
environment == 'production' ? Logger::INFO : Logger::DEBUG
|
292
344
|
end
|
345
|
+
|
346
|
+
def error( msg )
|
347
|
+
msg = "[E] Configuration: #{msg}"
|
348
|
+
|
349
|
+
if DaemonKit.logger
|
350
|
+
DaemonKit.logger.error( msg )
|
351
|
+
else
|
352
|
+
STDERR.puts msg
|
353
|
+
end
|
354
|
+
end
|
293
355
|
end
|
294
356
|
|
295
357
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DaemonKit
|
2
|
+
|
3
|
+
# Simple pidfile handling for daemon processes
|
4
|
+
class PidFile
|
5
|
+
|
6
|
+
def initialize( path )
|
7
|
+
@path = path.to_absolute_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def exists?
|
11
|
+
File.exists?( @path )
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns true if the process is running
|
15
|
+
def running?
|
16
|
+
return false unless self.exists?
|
17
|
+
|
18
|
+
# Check if process is in existence
|
19
|
+
# The simplest way to do this is to send signal '0'
|
20
|
+
# (which is a single system call) that doesn't actually
|
21
|
+
# send a signal
|
22
|
+
begin
|
23
|
+
Process.kill(0, self.pid)
|
24
|
+
return true
|
25
|
+
rescue Errno::ESRCH
|
26
|
+
return false
|
27
|
+
rescue ::Exception # for example on EPERM (process exists but does not belong to us)
|
28
|
+
return true
|
29
|
+
#rescue Errno::EPERM
|
30
|
+
# return false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return the pid contained in the pidfile, or nil
|
35
|
+
def pid
|
36
|
+
return nil unless self.exists?
|
37
|
+
|
38
|
+
File.open( @path ) { |f|
|
39
|
+
return f.gets.to_i
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def ensure_stopped!
|
44
|
+
if self.running?
|
45
|
+
puts "Process already running with id #{self.pid}"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def cleanup
|
51
|
+
File.delete( @path ) rescue Errno::ENOENT
|
52
|
+
end
|
53
|
+
alias zap cleanup
|
54
|
+
|
55
|
+
def write!
|
56
|
+
File.open( @path, 'w' ) { |f|
|
57
|
+
f.puts Process.pid
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
task :environment do
|
2
|
-
# This relies on the fact that rake changes the currect working
|
3
|
-
# directory to the directory where the Rakefile is located, thus
|
4
|
-
# implying DAEMON_ROOT.
|
5
|
-
DAEMON_ROOT = '.'
|
6
2
|
$daemon_kit_rake_task = true
|
7
3
|
|
8
4
|
require 'config/environment'
|
9
5
|
end
|
6
|
+
|
7
|
+
task "Execute system commands in other tasks with sudo"
|
8
|
+
task :sudo do
|
9
|
+
$RAKE_USE_SUDO = true
|
10
|
+
end
|
@@ -76,7 +76,7 @@ namespace :daemon_kit do
|
|
76
76
|
desc "Upgrade your local files for a daemon after upgrading daemon-kit"
|
77
77
|
task :upgrade => 'environment' do
|
78
78
|
# Run these
|
79
|
-
%w{ initializers }.each do |t|
|
79
|
+
%w{ initializers rakefile scripts }.each do |t|
|
80
80
|
Rake::Task["daemon_kit:upgrade:#{t}"].invoke
|
81
81
|
end
|
82
82
|
|
@@ -87,6 +87,8 @@ namespace :daemon_kit do
|
|
87
87
|
namespace :upgrade do
|
88
88
|
# Upgrade the initializers
|
89
89
|
task :initializers do
|
90
|
+
copy_framework_template( 'config/boot.rb', 'config/boot.rb' )
|
91
|
+
|
90
92
|
if File.directory?( File.join(DaemonKit.root, 'config', 'initializers') )
|
91
93
|
mv File.join(DaemonKit.root, 'config', 'initializers'), File.join(DAEMON_ROOT, 'config', 'pre-daemonize')
|
92
94
|
copy_framework_template( 'config', 'pre-daemonize', 'readme' )
|
@@ -97,6 +99,18 @@ namespace :daemon_kit do
|
|
97
99
|
copy_framework_template( 'config', 'post-daemonize', 'readme' )
|
98
100
|
end
|
99
101
|
end
|
102
|
+
|
103
|
+
# Upgrade the Rakefile
|
104
|
+
task :rakefile do
|
105
|
+
copy_framework_template( 'Rakefile' )
|
106
|
+
end
|
107
|
+
|
108
|
+
# Upgrade the scripts
|
109
|
+
task :scripts do
|
110
|
+
%w{ console destroy generate }.each do |s|
|
111
|
+
copy_framework_template( "script", s )
|
112
|
+
end
|
113
|
+
end
|
100
114
|
end
|
101
115
|
end
|
102
116
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
namespace :god do
|
4
|
+
desc "Generate a stub god config file template for the daemon"
|
5
|
+
task :template => 'environment' do
|
6
|
+
# Preserve local changes
|
7
|
+
if File.exists?( "#{DaemonKit.root}/config/god.erb" ) && ENV['FORCE'].nil?
|
8
|
+
puts "Template already exists, use FORCE=1 to overwrite."
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
|
12
|
+
cp "#{DaemonKit.framework_root}/templates/god/god.erb", "#{DaemonKit.root}/config/god.erb"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Parse the god config template into a god config file"
|
16
|
+
task :generate => 'environment' do
|
17
|
+
|
18
|
+
unless File.exists?( "#{DaemonKit.root}/config/god.erb" )
|
19
|
+
Rake::Task["god:template"].invoke
|
20
|
+
end
|
21
|
+
|
22
|
+
name = DaemonKit.configuration.daemon_name
|
23
|
+
|
24
|
+
File.open( "#{DaemonKit.root}/config/#{name}.god", "w+" ) do |f|
|
25
|
+
t = File.read( "#{DaemonKit.root}/config/god.erb" )
|
26
|
+
f.write( ERB.new( t ).result( binding ) )
|
27
|
+
end
|
28
|
+
|
29
|
+
puts "Monit config generated in config/#{name}.god"
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Load the god file into god"
|
33
|
+
task :load => 'environment' do
|
34
|
+
name = DaemonKit.configuration.daemon_name
|
35
|
+
|
36
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god load #{DaemonKit.root}/config/#{name}.god"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Refresh the god config file in the running god"
|
40
|
+
task :refresh => 'environment' do
|
41
|
+
name = DaemonKit.configuration.daemon_name
|
42
|
+
|
43
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god unmonitor #{name}"
|
44
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god remove #{name}"
|
45
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god load #{DaemonKit.root}/config/#{name}.god"
|
46
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god monitor #{name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Start god monitoring of the config file"
|
50
|
+
task :monitor => 'environment' do
|
51
|
+
name = DaemonKit.configuration.daemon_name
|
52
|
+
|
53
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god monitor #{name}"
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Stop god monitoring of the config file"
|
57
|
+
task :unmonitor => 'environment' do
|
58
|
+
name = DaemonKit.configuration.daemon_name
|
59
|
+
|
60
|
+
sh "#{$RAKE_USE_SUDO ? 'sudo' : ''} god unmonitor #{name}"
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
namespace :monit do
|
4
|
+
desc "Generate a stub monit config file template for the daemon"
|
5
|
+
task :template => 'environment' do
|
6
|
+
# Preserve local changes
|
7
|
+
if File.exists?( "#{DaemonKit.root}/config/monit.erb" ) && ENV['FORCE'].nil?
|
8
|
+
puts "Template already exists, use FORCE=1 to overwrite."
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
|
12
|
+
cp "#{DaemonKit.framework_root}/templates/monit/monit.erb", "#{DaemonKit.root}/config/monit.erb"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Parse the monit config template into a monit config file"
|
16
|
+
task :generate => 'environment' do
|
17
|
+
|
18
|
+
unless File.exists?( "#{DaemonKit.root}/config/monit.erb" )
|
19
|
+
Rake::Task["monit:template"].invoke
|
20
|
+
end
|
21
|
+
|
22
|
+
File.open( "#{DaemonKit.root}/config/monit.conf", "w+" ) do |f|
|
23
|
+
t = File.read( "#{DaemonKit.root}/config/monit.erb" )
|
24
|
+
f.write( ERB.new( t ).result( binding ) )
|
25
|
+
end
|
26
|
+
|
27
|
+
puts "Monit config generated in config/monit.conf"
|
28
|
+
end
|
29
|
+
end
|
data/lib/daemon_kit.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
-
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
1
|
+
# TODO: Strip this out eventually so we can run without rubygems
|
4
2
|
require 'rubygems'
|
5
3
|
|
4
|
+
require File.dirname(__FILE__) + '/daemon_kit/core_ext'
|
5
|
+
|
6
|
+
$:.unshift( File.dirname(__FILE__).to_absolute_path ) unless
|
7
|
+
$:.include?( File.dirname(__FILE__).to_absolute_path )
|
8
|
+
|
6
9
|
module DaemonKit
|
7
|
-
VERSION = '0.1.
|
10
|
+
VERSION = '0.1.7.3'
|
8
11
|
|
9
12
|
autoload :Initializer, 'daemon_kit/initializer'
|
10
13
|
autoload :Application, 'daemon_kit/application'
|
14
|
+
autoload :Arguments, 'daemon_kit/arguments'
|
11
15
|
autoload :Config, 'daemon_kit/config'
|
16
|
+
autoload :Safety, 'daemon_kit/safety'
|
17
|
+
autoload :PidFile, 'daemon_kit/pid_file'
|
18
|
+
|
12
19
|
autoload :Cron, 'daemon_kit/cron'
|
13
20
|
autoload :Jabber, 'daemon_kit/jabber'
|
14
21
|
autoload :AMQP, 'daemon_kit/amqp'
|
15
22
|
autoload :Nanite, 'daemon_kit/nanite'
|
16
|
-
autoload :Safety, 'daemon_kit/safety'
|
17
23
|
end
|