daemon-kit 0.1.7 → 0.1.7.4
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 +24 -0
- data/Manifest.txt +50 -2
- data/PostInstall.txt +1 -1
- data/README.rdoc +7 -9
- data/Rakefile +2 -4
- data/TODO.txt +6 -5
- data/app_generators/daemon_kit/daemon_kit_generator.rb +5 -0
- data/app_generators/daemon_kit/templates/Rakefile +3 -1
- data/app_generators/daemon_kit/templates/bin/daemon.erb +1 -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/amqp/templates/config/amqp.yml +5 -5
- data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +4 -23
- data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
- data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +3 -1
- data/lib/daemon_kit.rb +33 -5
- data/lib/daemon_kit/amqp.rb +2 -1
- data/lib/daemon_kit/application.rb +136 -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.rb +1 -0
- data/lib/daemon_kit/core_ext/string.rb +22 -0
- data/lib/daemon_kit/deployment/capistrano.rb +6 -9
- data/lib/daemon_kit/error_handlers/mail.rb +52 -15
- data/lib/daemon_kit/initializer.rb +95 -41
- 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/log.rake +8 -0
- data/lib/daemon_kit/tasks/monit.rake +29 -0
- data/spec/argument_spec.rb +51 -0
- data/spec/config_spec.rb +77 -0
- data/spec/daemon_kit_spec.rb +2 -2
- data/spec/error_handlers_spec.rb +23 -0
- 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 +6 -1
- data/test/test_deploy_capistrano_generator.rb +1 -2
- data/vendor/tmail-1.2.3/tmail.rb +5 -0
- data/vendor/tmail-1.2.3/tmail/address.rb +426 -0
- data/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
- data/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
- data/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
- data/vendor/tmail-1.2.3/tmail/config.rb +67 -0
- data/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
- data/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
- data/vendor/tmail-1.2.3/tmail/header.rb +960 -0
- data/vendor/tmail-1.2.3/tmail/index.rb +9 -0
- data/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
- data/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
- data/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
- data/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
- data/vendor/tmail-1.2.3/tmail/main.rb +6 -0
- data/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
- data/vendor/tmail-1.2.3/tmail/net.rb +248 -0
- data/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
- data/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
- data/vendor/tmail-1.2.3/tmail/port.rb +379 -0
- data/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
- data/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
- data/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
- data/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
- data/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
- data/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
- data/vendor/tmail-1.2.3/tmail/version.rb +39 -0
- data/vendor/tmail.rb +13 -0
- metadata +57 -18
- data/daemon_generators/deploy_capistrano/USAGE +0 -5
- data/lib/daemon_kit/patches/force_kill_wait.rb +0 -120
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
Capistrano deployment configuration generator completed
|
3
|
+
|
4
|
+
Usage:
|
5
|
+
Review the configuration files in config/deploy.rb and
|
6
|
+
config/deploy/*.rb
|
7
|
+
|
8
|
+
Once you're happy with the configurations, you can review
|
9
|
+
a list of available capistrano commands by running `cap -T'
|
10
|
+
|
@@ -34,7 +34,9 @@ set :config_files, %w{}
|
|
34
34
|
set :shared_children, %w{log tmp}
|
35
35
|
|
36
36
|
# Record our dependencies
|
37
|
-
|
37
|
+
unless File.directory?( "#{DaemonKit.root}/vendor/daemon_kit" )
|
38
|
+
depend :remote, :gem, "daemon-kit", ">=#{DaemonKit::VERSION}"
|
39
|
+
end
|
38
40
|
|
39
41
|
# Hook into capistrano's events
|
40
42
|
before "deploy:update_code", "deploy:check"
|
data/lib/daemon_kit.rb
CHANGED
@@ -1,17 +1,45 @@
|
|
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.7'
|
10
|
+
VERSION = '0.1.7.4'
|
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
|
-
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def logger
|
26
|
+
@logger
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger=( logger )
|
30
|
+
@logger = logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def root
|
34
|
+
DAEMON_ROOT
|
35
|
+
end
|
36
|
+
|
37
|
+
def env
|
38
|
+
DAEMON_ENV
|
39
|
+
end
|
40
|
+
|
41
|
+
def framework_root
|
42
|
+
@framework_root ||= File.join( File.dirname(__FILE__), '..' ).to_absolute_path
|
43
|
+
end
|
44
|
+
end
|
17
45
|
end
|
data/lib/daemon_kit/amqp.rb
CHANGED
@@ -30,7 +30,8 @@ module DaemonKit
|
|
30
30
|
DaemonKit.trap('INT') { ::AMQP.stop { ::EM.stop } }
|
31
31
|
DaemonKit.trap('TERM') { ::AMQP.stop { ::EM.stop } }
|
32
32
|
|
33
|
-
# Start our event loop
|
33
|
+
# Start our event loop and AMQP client
|
34
|
+
DaemonKit.logger.debug("AMQP.start(#{@config.inspect})")
|
34
35
|
::AMQP.start(@config, &block)
|
35
36
|
end
|
36
37
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'timeout'
|
2
2
|
|
3
3
|
module DaemonKit
|
4
4
|
|
@@ -7,29 +7,154 @@ module DaemonKit
|
|
7
7
|
|
8
8
|
class << self
|
9
9
|
|
10
|
-
# Run the file as a daemon
|
11
|
-
def
|
10
|
+
# Run the specified file as a daemon process.
|
11
|
+
def exec( file )
|
12
12
|
raise DaemonNotFound.new( file ) unless File.exist?( file )
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
DaemonKit.configuration.daemon_name ||= File.basename( file )
|
15
|
+
|
16
|
+
command, configs, args = Arguments.parse( ARGV )
|
17
|
+
|
18
|
+
case command
|
19
|
+
when :run
|
20
|
+
parse_arguments( args )
|
21
|
+
run( file )
|
22
|
+
when :start
|
23
|
+
parse_arguments( args )
|
24
|
+
start( file )
|
25
|
+
when :stop
|
26
|
+
stop
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Run the daemon in the foreground without daemonizing
|
31
|
+
def run( file )
|
32
|
+
self.chroot
|
33
|
+
self.clean_fd
|
34
|
+
self.redirect_io( true )
|
35
|
+
|
36
|
+
require file
|
37
|
+
end
|
38
|
+
|
39
|
+
# Run our file properly
|
40
|
+
def start( file )
|
41
|
+
self.daemonize
|
42
|
+
self.chroot
|
43
|
+
self.clean_fd
|
44
|
+
self.redirect_io
|
45
|
+
|
46
|
+
require file
|
47
|
+
end
|
48
|
+
|
49
|
+
def stop
|
50
|
+
@pid_file = PidFile.new( DaemonKit.configuration.pid_file )
|
51
|
+
|
52
|
+
unless @pid_file.running?
|
53
|
+
@pid_file.cleanup
|
54
|
+
puts "Nothing to stop"
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
target_pid = @pid_file.pid
|
59
|
+
|
60
|
+
puts "Sending TERM to #{target_pid}"
|
61
|
+
Process.kill( 'TERM', target_pid )
|
62
|
+
|
63
|
+
if seconds = DaemonKit.configuration.force_kill_wait
|
64
|
+
begin
|
65
|
+
Timeout::timeout( seconds ) do
|
66
|
+
loop do
|
67
|
+
puts "Waiting #{seconds} seconds for #{target_pid} before sending KILL"
|
68
|
+
|
69
|
+
break unless @pid_file.running?
|
16
70
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
71
|
+
seconds -= 1
|
72
|
+
sleep 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
rescue Timeout::Error
|
76
|
+
Process.kill( 'KILL', target_pid )
|
77
|
+
end
|
78
|
+
end
|
21
79
|
|
22
|
-
|
80
|
+
@pid_file.cleanup
|
23
81
|
end
|
24
82
|
|
25
83
|
# Call this from inside a daemonized process to complete the
|
26
84
|
# initialization process
|
27
85
|
def running!
|
28
|
-
|
86
|
+
Initializer.continue!
|
29
87
|
|
30
88
|
yield DaemonKit.configuration if block_given?
|
31
89
|
end
|
32
90
|
|
91
|
+
# Exit the daemon
|
92
|
+
# TODO: Make configurable callback chain
|
93
|
+
# TODO: Hook into at_exit()
|
94
|
+
def exit!( code = 0 )
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def parse_arguments( args )
|
100
|
+
DaemonKit.arguments = Arguments.new
|
101
|
+
DaemonKit.arguments.parse( args )
|
102
|
+
end
|
103
|
+
|
104
|
+
# Daemonize the process
|
105
|
+
def daemonize
|
106
|
+
@pid_file = PidFile.new( DaemonKit.configuration.pid_file )
|
107
|
+
@pid_file.ensure_stopped!
|
108
|
+
|
109
|
+
if RUBY_VERSION < "1.9"
|
110
|
+
exit if fork
|
111
|
+
Process.setsid
|
112
|
+
exit if fork
|
113
|
+
else
|
114
|
+
Process.daemon( true, true )
|
115
|
+
end
|
116
|
+
|
117
|
+
@pid_file.write!
|
118
|
+
|
119
|
+
# TODO: Convert into shutdown hook
|
120
|
+
at_exit { @pid_file.cleanup }
|
121
|
+
end
|
122
|
+
|
123
|
+
# Release the old working directory and insure a sensible umask
|
124
|
+
# TODO: Make chroot directory configurable
|
125
|
+
def chroot
|
126
|
+
Dir.chdir '/'
|
127
|
+
File.umask 0000
|
128
|
+
end
|
129
|
+
|
130
|
+
# Make sure all file descriptors are closed (with the exception
|
131
|
+
# of STDIN, STDOUT & STDERR)
|
132
|
+
def clean_fd
|
133
|
+
ObjectSpace.each_object(IO) do |io|
|
134
|
+
unless [STDIN, STDOUT, STDERR].include?(io)
|
135
|
+
begin
|
136
|
+
unless io.closed?
|
137
|
+
io.close
|
138
|
+
end
|
139
|
+
rescue ::Exception
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Redirect our IO
|
146
|
+
# TODO: make this configurable
|
147
|
+
def redirect_io( simulate = false )
|
148
|
+
begin
|
149
|
+
STDIN.reopen '/dev/null'
|
150
|
+
rescue ::Exception
|
151
|
+
end
|
152
|
+
|
153
|
+
unless simulate
|
154
|
+
STDOUT.reopen '/dev/null', 'a'
|
155
|
+
STDERR.reopen '/dev/null', 'a'
|
156
|
+
end
|
157
|
+
end
|
33
158
|
end
|
34
159
|
|
35
160
|
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module DaemonKit
|
4
|
+
|
5
|
+
# A wrapper around OptParse for setting up arguments to the daemon
|
6
|
+
# process.
|
7
|
+
#
|
8
|
+
# TODO: Set rules for basic options that go for all daemons
|
9
|
+
# TODO: Load options from config/arguments.rb
|
10
|
+
class Arguments
|
11
|
+
|
12
|
+
# Default command
|
13
|
+
@default_command = 'run'
|
14
|
+
|
15
|
+
# Valid commands
|
16
|
+
@commands = [
|
17
|
+
'start',
|
18
|
+
'stop',
|
19
|
+
'run'
|
20
|
+
]
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
attr_reader :default_command, :commands
|
25
|
+
|
26
|
+
# Parse the argument values and return an array with the command
|
27
|
+
# name, config values and argument values
|
28
|
+
def parse( argv )
|
29
|
+
cmd, argv = self.command( argv )
|
30
|
+
|
31
|
+
return cmd, *self.configuration( argv )
|
32
|
+
end
|
33
|
+
|
34
|
+
# Parse the provided argument array for a given command, or
|
35
|
+
# return the default command and the remaining arguments
|
36
|
+
def command( argv )
|
37
|
+
# extract command or set default
|
38
|
+
cmd = self.commands.include?( argv[0] ) ? argv.shift : self.default_command
|
39
|
+
|
40
|
+
return cmd.to_sym, argv
|
41
|
+
end
|
42
|
+
|
43
|
+
# Extracts any values for arguments matching '--config' as well
|
44
|
+
# as some implication arguments like '-e'. Returns an array with
|
45
|
+
# the configs as the first value and the remaing args as the
|
46
|
+
# last value.
|
47
|
+
#
|
48
|
+
# To set a value on the default #Configuration instance, use the
|
49
|
+
# following notation:
|
50
|
+
#
|
51
|
+
# --config attribute=value
|
52
|
+
#
|
53
|
+
# The above notation can be used several times to set different
|
54
|
+
# values.
|
55
|
+
#
|
56
|
+
# Special, or 'normal' arguments that are mapped to the default
|
57
|
+
# #Configuration instance are listed below:
|
58
|
+
#
|
59
|
+
# -e value or --env value => environment
|
60
|
+
# --pid pidfile => pid_file
|
61
|
+
#
|
62
|
+
def configuration( argv )
|
63
|
+
configs = []
|
64
|
+
|
65
|
+
i = 0
|
66
|
+
while i < argv.size
|
67
|
+
if argv[i] == "--config"
|
68
|
+
argv.delete_at( i )
|
69
|
+
configs << argv.delete_at(i)
|
70
|
+
end
|
71
|
+
|
72
|
+
if argv[i] == "-e" || argv[i] == "--env"
|
73
|
+
argv.delete_at( i )
|
74
|
+
configs << "environment=#{argv.delete_at(i)}"
|
75
|
+
end
|
76
|
+
|
77
|
+
if argv[i] == "--pid"
|
78
|
+
argv.delete_at( i )
|
79
|
+
configs << "pid_file=#{argv.delete_at(i)}"
|
80
|
+
end
|
81
|
+
|
82
|
+
i += 1
|
83
|
+
end
|
84
|
+
|
85
|
+
return configs, argv
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return the arguments remaining after running through #configuration
|
89
|
+
def arguments( argv )
|
90
|
+
self.configuration( argv ).last
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
attr_reader :options
|
95
|
+
|
96
|
+
def initialize
|
97
|
+
@options = {}
|
98
|
+
|
99
|
+
@parser = OptionParser.new do |opts|
|
100
|
+
opts.banner = "Usage: #{File.basename($0)} [command] [options]"
|
101
|
+
|
102
|
+
opts.separator ""
|
103
|
+
|
104
|
+
opts.separator "Command is one of the following:"
|
105
|
+
opts.separator " run - Run the daemon without forking (default)"
|
106
|
+
opts.separator " start - Run the daemon"
|
107
|
+
opts.separator " stop - Stop the running daemon"
|
108
|
+
|
109
|
+
opts.separator ""
|
110
|
+
|
111
|
+
opts.separator "Options can be:"
|
112
|
+
|
113
|
+
arg_file = File.join( DaemonKit.root, 'config', 'arguments.rb' )
|
114
|
+
eval(IO.read(arg_file), binding, arg_file) if File.exists?( arg_file )
|
115
|
+
|
116
|
+
opts.on("-e", "--env ENVIRONMENT", "Environment for the process", "Defaults to development") do
|
117
|
+
# Nothing, just here for show
|
118
|
+
end
|
119
|
+
|
120
|
+
opts.on("--pidfile PATH", "Path to the pidfile", "Defaults to log/#{DaemonKit.configuration.daemon_name}.pid") do
|
121
|
+
# Nothing, just here for show
|
122
|
+
end
|
123
|
+
|
124
|
+
opts.separator ""
|
125
|
+
opts.separator "Advanced configurations:"
|
126
|
+
opts.on("--config ATTRIBUTE=VALUE",
|
127
|
+
"Change values of the daemon-kit Configuration instance",
|
128
|
+
"Example: log_dir=/path/to/log-directory") do
|
129
|
+
# Nothing, just here for show
|
130
|
+
end
|
131
|
+
|
132
|
+
opts.separator ""
|
133
|
+
|
134
|
+
opts.separator "Common options:"
|
135
|
+
opts.on("-v", "--version", "Show version information and exit") do
|
136
|
+
puts "daemon-kit #{DaemonKit::VERSION} (http://github.com/kennethkalmer/daemon-kit)"
|
137
|
+
exit
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
141
|
+
puts opts
|
142
|
+
exit
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def parse( argv )
|
148
|
+
@parser.parse!( argv )
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = { :irb => irb }
|
6
|
+
OptionParser.new do |opt|
|
7
|
+
opt.banner = "Usage: console [environment] [options]"
|
8
|
+
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
|
9
|
+
opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
|
10
|
+
opt.parse!(ARGV)
|
11
|
+
end
|
12
|
+
|
13
|
+
libs = " -r irb/completion"
|
14
|
+
libs << %( -r "#{DAEMON_ROOT}/config/environment")
|
15
|
+
libs << " -r daemon_kit/console_daemon"
|
16
|
+
|
17
|
+
if options[:debugger]
|
18
|
+
begin
|
19
|
+
require 'ruby-debug'
|
20
|
+
libs << " -r ruby-debug"
|
21
|
+
puts "=> Debugger enabled"
|
22
|
+
rescue Exception
|
23
|
+
puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ENV['DAEMON_ENV'] = case ARGV.first
|
29
|
+
when "p"; "production"
|
30
|
+
when "d"; "development"
|
31
|
+
when "t"; "test"
|
32
|
+
else
|
33
|
+
ARGV.first || ENV['DAEMON_ENV'] || 'development'
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Loading #{ENV['DAEMON_ENV']} environment (daemon-kit #{DaemonKit::VERSION})"
|
37
|
+
|
38
|
+
exec "#{options[:irb]} #{libs} --simple-prompt"
|