kennethkalmer-daemon-kit 0.1.6 → 0.1.7.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|