queso-daemon-kit 0.1.7.10

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.
Files changed (167) hide show
  1. data/Configuration.txt +110 -0
  2. data/Deployment.txt +113 -0
  3. data/History.txt +97 -0
  4. data/Logging.txt +92 -0
  5. data/Manifest.txt +166 -0
  6. data/PostInstall.txt +6 -0
  7. data/README.rdoc +130 -0
  8. data/Rakefile +37 -0
  9. data/RuoteParticipants.txt +113 -0
  10. data/TODO.txt +37 -0
  11. data/app_generators/daemon_kit/USAGE +7 -0
  12. data/app_generators/daemon_kit/daemon_kit_generator.rb +161 -0
  13. data/app_generators/daemon_kit/templates/README +48 -0
  14. data/app_generators/daemon_kit/templates/Rakefile +6 -0
  15. data/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
  16. data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  17. data/app_generators/daemon_kit/templates/config/boot.rb +68 -0
  18. data/app_generators/daemon_kit/templates/config/environment.rb +23 -0
  19. data/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
  20. data/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
  21. data/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
  22. data/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
  23. data/app_generators/daemon_kit/templates/config/pre-daemonize/readme +12 -0
  24. data/app_generators/daemon_kit/templates/lib/daemon.rb +2 -0
  25. data/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
  26. data/app_generators/daemon_kit/templates/script/console +3 -0
  27. data/app_generators/daemon_kit/templates/script/destroy +14 -0
  28. data/app_generators/daemon_kit/templates/script/generate +14 -0
  29. data/bin/daemon_kit +18 -0
  30. data/daemon_generators/amqp/USAGE +5 -0
  31. data/daemon_generators/amqp/amqp_generator.rb +65 -0
  32. data/daemon_generators/amqp/templates/config/amqp.yml +28 -0
  33. data/daemon_generators/amqp/templates/config/initializers/amqp.rb +7 -0
  34. data/daemon_generators/amqp/templates/libexec/daemon.rb +37 -0
  35. data/daemon_generators/cron/USAGE +5 -0
  36. data/daemon_generators/cron/cron_generator.rb +64 -0
  37. data/daemon_generators/cron/templates/config/initializers/cron.rb +11 -0
  38. data/daemon_generators/cron/templates/libexec/daemon.rb +43 -0
  39. data/daemon_generators/cucumber/USAGE +11 -0
  40. data/daemon_generators/cucumber/cucumber_generator.rb +38 -0
  41. data/daemon_generators/cucumber/templates/cucumber +8 -0
  42. data/daemon_generators/cucumber/templates/cucumber.rake +13 -0
  43. data/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
  44. data/daemon_generators/cucumber/templates/env.rb +7 -0
  45. data/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
  46. data/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
  47. data/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  48. data/daemon_generators/deploy_capistrano/templates/config/deploy.rb +53 -0
  49. data/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
  50. data/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
  51. data/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
  52. data/daemon_generators/jabber/USAGE +5 -0
  53. data/daemon_generators/jabber/jabber_generator.rb +65 -0
  54. data/daemon_generators/jabber/templates/config/initializers/jabber.rb +7 -0
  55. data/daemon_generators/jabber/templates/config/jabber.yml +26 -0
  56. data/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
  57. data/daemon_generators/nanite_agent/USAGE +5 -0
  58. data/daemon_generators/nanite_agent/nanite_agent_generator.rb +68 -0
  59. data/daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb +6 -0
  60. data/daemon_generators/nanite_agent/templates/config/nanite.yml +35 -0
  61. data/daemon_generators/nanite_agent/templates/lib/actors/sample.rb +11 -0
  62. data/daemon_generators/nanite_agent/templates/libexec/daemon.rb +31 -0
  63. data/daemon_generators/rspec/USAGE +5 -0
  64. data/daemon_generators/rspec/rspec_generator.rb +55 -0
  65. data/daemon_generators/rspec/templates/spec.rb +11 -0
  66. data/daemon_generators/rspec/templates/spec/spec.opts +1 -0
  67. data/daemon_generators/rspec/templates/spec/spec_helper.rb +21 -0
  68. data/daemon_generators/rspec/templates/tasks/rspec.rake +21 -0
  69. data/daemon_generators/ruote/USAGE +5 -0
  70. data/daemon_generators/ruote/ruote_generator.rb +67 -0
  71. data/daemon_generators/ruote/templates/config/amqp.yml +30 -0
  72. data/daemon_generators/ruote/templates/config/initializers/ruote.rb +13 -0
  73. data/daemon_generators/ruote/templates/config/ruote.yml +23 -0
  74. data/daemon_generators/ruote/templates/lib/daemon.rb +4 -0
  75. data/daemon_generators/ruote/templates/lib/sample.rb +26 -0
  76. data/daemon_generators/ruote/templates/libexec/daemon.rb +33 -0
  77. data/lib/daemon_kit.rb +62 -0
  78. data/lib/daemon_kit/abstract_logger.rb +235 -0
  79. data/lib/daemon_kit/amqp.rb +38 -0
  80. data/lib/daemon_kit/application.rb +187 -0
  81. data/lib/daemon_kit/arguments.rb +165 -0
  82. data/lib/daemon_kit/commands/console.rb +38 -0
  83. data/lib/daemon_kit/config.rb +108 -0
  84. data/lib/daemon_kit/console_daemon.rb +2 -0
  85. data/lib/daemon_kit/core_ext.rb +1 -0
  86. data/lib/daemon_kit/core_ext/configurable.rb +96 -0
  87. data/lib/daemon_kit/core_ext/string.rb +22 -0
  88. data/lib/daemon_kit/cron.rb +48 -0
  89. data/lib/daemon_kit/cucumber/world.rb +38 -0
  90. data/lib/daemon_kit/deployment/capistrano.rb +482 -0
  91. data/lib/daemon_kit/em.rb +43 -0
  92. data/lib/daemon_kit/error_handlers/base.rb +32 -0
  93. data/lib/daemon_kit/error_handlers/hoptoad.rb +60 -0
  94. data/lib/daemon_kit/error_handlers/mail.rb +85 -0
  95. data/lib/daemon_kit/exceptions.rb +15 -0
  96. data/lib/daemon_kit/initializer.rb +438 -0
  97. data/lib/daemon_kit/jabber.rb +170 -0
  98. data/lib/daemon_kit/nanite.rb +7 -0
  99. data/lib/daemon_kit/nanite/agent.rb +56 -0
  100. data/lib/daemon_kit/pid_file.rb +61 -0
  101. data/lib/daemon_kit/ruote_participants.rb +119 -0
  102. data/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
  103. data/lib/daemon_kit/ruote_workitem.rb +169 -0
  104. data/lib/daemon_kit/safety.rb +85 -0
  105. data/lib/daemon_kit/tasks.rb +2 -0
  106. data/lib/daemon_kit/tasks/environment.rake +10 -0
  107. data/lib/daemon_kit/tasks/framework.rake +120 -0
  108. data/lib/daemon_kit/tasks/god.rake +62 -0
  109. data/lib/daemon_kit/tasks/log.rake +8 -0
  110. data/lib/daemon_kit/tasks/monit.rake +29 -0
  111. data/script/console +10 -0
  112. data/script/destroy +14 -0
  113. data/script/generate +14 -0
  114. data/script/txt2html +71 -0
  115. data/spec/abstract_logger_spec.rb +126 -0
  116. data/spec/argument_spec.rb +70 -0
  117. data/spec/config_spec.rb +79 -0
  118. data/spec/configurable_spec.rb +56 -0
  119. data/spec/daemon_kit_spec.rb +7 -0
  120. data/spec/error_handlers_spec.rb +23 -0
  121. data/spec/fixtures/env.yml +15 -0
  122. data/spec/fixtures/noenv.yml +4 -0
  123. data/spec/initializer_spec.rb +26 -0
  124. data/spec/spec.opts +1 -0
  125. data/spec/spec_helper.rb +27 -0
  126. data/tasks/rspec.rake +21 -0
  127. data/templates/god/god.erb +69 -0
  128. data/templates/monit/monit.erb +14 -0
  129. data/test/test_amqp_generator.rb +48 -0
  130. data/test/test_cron_generator.rb +45 -0
  131. data/test/test_daemon-kit_generator.rb +84 -0
  132. data/test/test_daemon_kit_config.rb +28 -0
  133. data/test/test_deploy_capistrano_generator.rb +48 -0
  134. data/test/test_generator_helper.rb +29 -0
  135. data/test/test_helper.rb +7 -0
  136. data/test/test_jabber_generator.rb +49 -0
  137. data/test/test_nanite_agent_generator.rb +49 -0
  138. data/test/test_ruote_generator.rb +45 -0
  139. data/vendor/tmail-1.2.3/tmail.rb +5 -0
  140. data/vendor/tmail-1.2.3/tmail/address.rb +426 -0
  141. data/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
  142. data/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
  143. data/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
  144. data/vendor/tmail-1.2.3/tmail/config.rb +67 -0
  145. data/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
  146. data/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
  147. data/vendor/tmail-1.2.3/tmail/header.rb +960 -0
  148. data/vendor/tmail-1.2.3/tmail/index.rb +9 -0
  149. data/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
  150. data/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
  151. data/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
  152. data/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
  153. data/vendor/tmail-1.2.3/tmail/main.rb +6 -0
  154. data/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
  155. data/vendor/tmail-1.2.3/tmail/net.rb +248 -0
  156. data/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
  157. data/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
  158. data/vendor/tmail-1.2.3/tmail/port.rb +379 -0
  159. data/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
  160. data/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
  161. data/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
  162. data/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
  163. data/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
  164. data/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
  165. data/vendor/tmail-1.2.3/tmail/version.rb +39 -0
  166. data/vendor/tmail.rb +13 -0
  167. metadata +281 -0
@@ -0,0 +1,4 @@
1
+ # Your starting point for daemon specific classes. This directory is
2
+ # already included in your load path, so no need to specify it.
3
+
4
+ require 'sample'
@@ -0,0 +1,26 @@
1
+ require 'open-uri'
2
+
3
+ # Sample pseudo participant
4
+ #
5
+ # See http://gist.github.com/144861 for a test engine
6
+ class Sample < DaemonKit::RuotePseudoParticipant
7
+
8
+ on_exception :dammit
9
+
10
+ on_complete do |workitem|
11
+ workitem['success'] = true
12
+ end
13
+
14
+ def quote
15
+ workitem["quote"] = open("http://www.iheartquotes.com/api/v1/random").read
16
+ end
17
+
18
+ def err
19
+ raise ArgumentError, "Does not compute"
20
+ end
21
+
22
+ def dammit( exception )
23
+ workitem["error"] = exception.message
24
+ end
25
+
26
+ end
@@ -0,0 +1,33 @@
1
+ # Generated remote participant for the ruote workflow engine
2
+ # (http://openwferu.rubyforge.org)
3
+
4
+ # Do your post daemonization configuration here
5
+ # At minimum you need just the first line (without the block), or a lot
6
+ # of strange things might start happening...
7
+ DaemonKit::Application.running! do |config|
8
+ # Trap signals with blocks or procs
9
+ # config.trap( 'INT' ) do
10
+ # # do something clever
11
+ # end
12
+ # config.trap( 'TERM', Proc.new { puts 'Going down' } )
13
+ end
14
+
15
+ # IMPORTANT CONFIGURATION NOTE
16
+ #
17
+ # Please review and update 'config/amqp.yml' accordingly if you wish to use
18
+ # AMQP as a transport mechanism for workitems sent between ruote and this
19
+ # daemon.
20
+
21
+ # Configuration of the remote participant shell
22
+ DaemonKit::RuoteParticipants.configure do |config|
23
+ # Use AMQP as a workitem transport mechanism
24
+ config.use :amqp
25
+
26
+ # Register your classes as pseudo-participants, with work being delegated
27
+ # according to the 'command' parameter passed in the process definition
28
+ config.register Sample
29
+ end
30
+
31
+ DaemonKit::RuoteParticipants.run do
32
+ # Place any additional daemon-specific code in here...
33
+ end
data/lib/daemon_kit.rb ADDED
@@ -0,0 +1,62 @@
1
+ # TODO: Strip this out eventually so we can run without rubygems
2
+ require 'rubygems'
3
+
4
+ # Seems in 1.9 we need to load openssl before em or there is failures all around.
5
+ # But we need to consider that people might not have ssl in the first place.
6
+ if RUBY_VERSION >= "1.9"
7
+ begin
8
+ require 'openssl'
9
+ rescue LoadError
10
+ end
11
+ end
12
+ require 'eventmachine'
13
+
14
+ require File.dirname(__FILE__) + '/daemon_kit/core_ext'
15
+ require File.dirname(__FILE__) + '/daemon_kit/exceptions'
16
+
17
+ $:.unshift( File.dirname(__FILE__).to_absolute_path ) unless
18
+ $:.include?( File.dirname(__FILE__).to_absolute_path )
19
+
20
+ module DaemonKit
21
+ VERSION = '0.1.7.10'
22
+
23
+ autoload :Initializer, 'daemon_kit/initializer'
24
+ autoload :Application, 'daemon_kit/application'
25
+ autoload :Arguments, 'daemon_kit/arguments'
26
+ autoload :Config, 'daemon_kit/config'
27
+ autoload :Safety, 'daemon_kit/safety'
28
+ autoload :PidFile, 'daemon_kit/pid_file'
29
+ autoload :AbstractLogger, 'daemon_kit/abstract_logger'
30
+ autoload :EM, 'daemon_kit/em'
31
+ autoload :Configurable, 'daemon_kit/core_ext/configurable'
32
+
33
+ autoload :Cron, 'daemon_kit/cron'
34
+ autoload :Jabber, 'daemon_kit/jabber'
35
+ autoload :AMQP, 'daemon_kit/amqp'
36
+ autoload :Nanite, 'daemon_kit/nanite'
37
+ autoload :RuoteParticipants, 'daemon_kit/ruote_participants'
38
+ autoload :RuoteWorkitem, 'daemon_kit/ruote_workitem'
39
+ autoload :RuotePseudoParticipant, 'daemon_kit/ruote_pseudo_participant'
40
+
41
+ class << self
42
+ def logger
43
+ @logger
44
+ end
45
+
46
+ def logger=( logger )
47
+ @logger = logger
48
+ end
49
+
50
+ def root
51
+ DAEMON_ROOT
52
+ end
53
+
54
+ def env
55
+ DAEMON_ENV
56
+ end
57
+
58
+ def framework_root
59
+ @framework_root ||= File.join( File.dirname(__FILE__), '..' ).to_absolute_path
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,235 @@
1
+ require 'logger'
2
+
3
+ module DaemonKit
4
+ # One of the key parts of succesful background processes is adequate
5
+ # logging. The AbstractLogger aims to simplify logging from inside
6
+ # daemon processes by providing additional useful information with
7
+ # each log line, including calling file name and line number and
8
+ # support for cleanly logging exceptions.
9
+ #
10
+ # The logger can be accessed through #DaemonKit.logger.
11
+ #
12
+ # AbstractLogger provides an interface that is fully compatible with
13
+ # the Logger class provided by Ruby's Standard Library, and is
14
+ # extended with some additional conveniences.
15
+ #
16
+ # The AbstractLogger supports different backends, by default it uses
17
+ # a Logger instance, but can by swapped out for a SysLogLogger
18
+ # logger as well.
19
+ class AbstractLogger
20
+
21
+ attr_accessor :copy_to_stdout
22
+
23
+ @severities = {
24
+ :debug => Logger::DEBUG,
25
+ :info => Logger::INFO,
26
+ :warn => Logger::WARN,
27
+ :error => Logger::ERROR,
28
+ :fatal => Logger::FATAL,
29
+ :unknown => Logger::UNKNOWN
30
+ }
31
+
32
+ @silencer = true
33
+
34
+ class << self
35
+ attr_reader :severities
36
+ attr_accessor :silencer
37
+ end
38
+
39
+ # Optional log path, defaults to
40
+ # <em>DAEMON_ROOT/log/DAEMON_ENV.log</em>
41
+ def initialize( log_path = nil )
42
+ if log_path.to_s == "syslog"
43
+ @backend = :syslog
44
+ else
45
+ @logger_file = log_path || "#{DAEMON_ROOT}/log/#{DAEMON_ENV}.log"
46
+ @backend = :logger
47
+ end
48
+
49
+ @copy_to_stdout = false
50
+ end
51
+
52
+ # Silence the logger for the duration of the block.
53
+ def silence( temporary_level = :error )
54
+ if self.class.silencer
55
+ begin
56
+ old_level, self.level = self.level, temporary_level
57
+ yield self
58
+ ensure
59
+ self.level = old_level
60
+ end
61
+ else
62
+ yield self
63
+ end
64
+ end
65
+
66
+ def debug( msg )
67
+ add( :debug, msg )
68
+ end
69
+
70
+ def debug?
71
+ self.level == :debug
72
+ end
73
+
74
+ def info( msg )
75
+ add( :info, msg )
76
+ end
77
+
78
+ def info?
79
+ self.level == :info
80
+ end
81
+
82
+ def warn( msg )
83
+ add( :warn, msg )
84
+ end
85
+
86
+ def warn?
87
+ self.level == :warn
88
+ end
89
+
90
+ def error( msg )
91
+ add( :error, msg )
92
+ end
93
+
94
+ def error?
95
+ self.level == :error
96
+ end
97
+
98
+ def fatal( msg )
99
+ add( :fatal, msg )
100
+ end
101
+
102
+ def fatal?
103
+ self.level == :fatal
104
+ end
105
+
106
+ def unknown( msg )
107
+ add( :unknown, msg )
108
+ end
109
+
110
+ def unknown?
111
+ self.level == :unknown
112
+ end
113
+
114
+ def exception( e )
115
+ message = "EXCEPTION: #{e.message}: #{clean_trace( e.backtrace )}"
116
+ self.add( :error, message, true )
117
+ end
118
+
119
+ def add( severity, message, skip_caller = false )
120
+ message = "#{called(caller)}: #{message}" unless skip_caller
121
+
122
+ self.logger.add( self.class.severities[ severity ] ) { message }
123
+
124
+ STDOUT.puts( message ) if self.copy_to_stdout
125
+ end
126
+
127
+ def level
128
+ self.class.severities.invert[ @logger.level ]
129
+ end
130
+
131
+ def level=( level )
132
+ level = ( Symbol === level ? self.class.severities[ level ] : level )
133
+ self.logger.level = level
134
+ end
135
+
136
+ def logger
137
+ @logger ||= create_logger
138
+ end
139
+
140
+ def logger=( logger )
141
+ if logger.is_a?( Symbol )
142
+ @backend = logger
143
+ @logger.close rescue nil
144
+ @logger = create_logger
145
+ else
146
+ @logger.close rescue nil
147
+ @logger = logger
148
+ end
149
+ end
150
+
151
+ def clean_trace( trace )
152
+ trace = trace.map { |l| l.gsub(DAEMON_ROOT, '') }
153
+ trace = trace.reject { |l| l =~ /gems\/daemon[\-_]kit/ }
154
+ trace = trace.reject { |l| l =~ /vendor\/daemon[\-_]kit/ }
155
+ trace
156
+ end
157
+
158
+ def close
159
+ case @backend
160
+ when :logger
161
+ self.logger.close
162
+ @logger = nil
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ def called( trace )
169
+ l = trace.detect('unknown:0') { |l| l.index('abstract_logger.rb').nil? }
170
+ file, num, _ = l.split(':')
171
+
172
+ [ File.basename(file), num ].join(':')
173
+ end
174
+
175
+ def create_logger
176
+ case @backend
177
+ when :logger
178
+ create_standard_logger
179
+ when :syslog
180
+ create_syslog_logger
181
+ end
182
+ end
183
+
184
+ def create_standard_logger
185
+ log_path = File.dirname( @logger_file )
186
+ unless File.directory?( log_path )
187
+ begin
188
+ FileUtils.mkdir_p( log_path )
189
+ rescue
190
+ STDERR.puts "#{log_path} not writable, using STDERR for logging"
191
+ @logger_file = STDERR
192
+ end
193
+ end
194
+
195
+ l = Logger.new( @logger_file )
196
+ l.formatter = Formatter.new
197
+ l.progname = if DaemonKit.configuration
198
+ DaemonKit.configuration.daemon_name
199
+ else
200
+ File.basename($0)
201
+ end
202
+ l
203
+ end
204
+
205
+ def create_syslog_logger
206
+ begin
207
+ require 'syslog_logger'
208
+ SyslogLogger.new( DaemonKit.configuration ? DaemonKit.configuration.daemon_name : File.basename($0) )
209
+ rescue LoadError
210
+ self.logger = :logger
211
+ self.error( "Couldn't load syslog_logger gem, reverting to standard logger" )
212
+ end
213
+ end
214
+
215
+ class Formatter
216
+
217
+ # YYYY:MM:DD HH:MM:SS.MS daemon_name(pid) level: message
218
+ @format = "%s %s(%d) [%s] %s\n"
219
+
220
+ class << self
221
+ attr_accessor :format
222
+ end
223
+
224
+ def call(severity, time, progname, msg)
225
+ self.class.format % [ format_time( time ), progname, $$, severity, msg.to_s ]
226
+ end
227
+
228
+ private
229
+
230
+ def format_time( time )
231
+ time.strftime( "%Y-%m-%d %H:%M:%S." ) + time.usec.to_s
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,38 @@
1
+ require 'yaml'
2
+
3
+ module DaemonKit
4
+ # Thin wrapper around the amqp gem, specifically designed to ease
5
+ # configuration of a AMQP consumer daemon and provide some added
6
+ # simplicity
7
+ class AMQP
8
+
9
+ @@instance = nil
10
+
11
+ class << self
12
+
13
+ def instance
14
+ @instance ||= new
15
+ end
16
+
17
+ private :new
18
+
19
+ def run(&block)
20
+ instance.run(&block)
21
+ end
22
+ end
23
+
24
+ def initialize( config = {} )
25
+ @config = DaemonKit::Config.load('amqp').to_h( true )
26
+ end
27
+
28
+ def run(&block)
29
+ # Ensure graceful shutdown of the connection to the broker
30
+ DaemonKit.trap('INT') { ::AMQP.stop { ::EM.stop } }
31
+ DaemonKit.trap('TERM') { ::AMQP.stop { ::EM.stop } }
32
+
33
+ # Start our event loop and AMQP client
34
+ DaemonKit.logger.debug("AMQP.start(#{@config.inspect})")
35
+ ::AMQP.start(@config, &block)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,187 @@
1
+ require 'timeout'
2
+
3
+ module DaemonKit
4
+
5
+ # Class responsible for making the daemons run and keep them running.
6
+ class Application
7
+
8
+ class << self
9
+
10
+ # Run the specified file as a daemon process.
11
+ def exec( file )
12
+ raise DaemonNotFound.new( file ) unless File.exist?( file )
13
+
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
+ DaemonKit.configuration.log_stdout = true
37
+
38
+ require file
39
+ end
40
+
41
+ # Run our file properly
42
+ def start( file )
43
+ self.drop_privileges
44
+ self.daemonize
45
+ self.chroot
46
+ self.clean_fd
47
+ self.redirect_io
48
+
49
+ require file
50
+ end
51
+
52
+ def stop
53
+ @pid_file = PidFile.new( DaemonKit.configuration.pid_file )
54
+
55
+ unless @pid_file.running?
56
+ @pid_file.cleanup
57
+ puts "Nothing to stop"
58
+ exit
59
+ end
60
+
61
+ target_pid = @pid_file.pid
62
+
63
+ puts "Sending TERM to #{target_pid}"
64
+ Process.kill( 'TERM', target_pid )
65
+
66
+ if seconds = DaemonKit.configuration.force_kill_wait
67
+ begin
68
+ Timeout::timeout( seconds ) do
69
+ loop do
70
+ puts "Waiting #{seconds} seconds for #{target_pid} before sending KILL"
71
+
72
+ break unless @pid_file.running?
73
+
74
+ seconds -= 1
75
+ sleep 1
76
+ end
77
+ end
78
+ rescue Timeout::Error
79
+ Process.kill( 'KILL', target_pid )
80
+ end
81
+ end
82
+
83
+ if @pid_file.running?
84
+ puts "Process still running, leaving pidfile behind! Consider using configuration.force_kill_wait."
85
+ else
86
+ @pid_file.cleanup
87
+ end
88
+ end
89
+
90
+ # Call this from inside a daemonized process to complete the
91
+ # initialization process
92
+ def running!
93
+ Initializer.continue!
94
+
95
+ yield DaemonKit.configuration if block_given?
96
+ end
97
+
98
+ # Exit the daemon
99
+ # TODO: Make configurable callback chain
100
+ # TODO: Hook into at_exit()
101
+ def exit!( code = 0 )
102
+ end
103
+
104
+ protected
105
+
106
+ def parse_arguments( args )
107
+ DaemonKit.arguments = Arguments.new
108
+ DaemonKit.arguments.parse( args )
109
+ end
110
+
111
+ # Daemonize the process
112
+ def daemonize
113
+ @pid_file = PidFile.new( DaemonKit.configuration.pid_file )
114
+ @pid_file.ensure_stopped!
115
+
116
+ if RUBY_VERSION < "1.9"
117
+ exit if fork
118
+ Process.setsid
119
+ exit if fork
120
+ else
121
+ Process.daemon( true, true )
122
+ end
123
+
124
+ @pid_file.write!
125
+
126
+ # TODO: Convert into shutdown hook
127
+ at_exit { @pid_file.cleanup }
128
+ end
129
+
130
+ # Release the old working directory and insure a sensible umask
131
+ # TODO: Make chroot directory configurable
132
+ def chroot
133
+ Dir.chdir '/'
134
+ File.umask 0000
135
+ end
136
+
137
+ # Make sure all file descriptors are closed (with the exception
138
+ # of STDIN, STDOUT & STDERR)
139
+ def clean_fd
140
+ ObjectSpace.each_object(IO) do |io|
141
+ unless [STDIN, STDOUT, STDERR].include?(io)
142
+ begin
143
+ unless io.closed?
144
+ io.close
145
+ end
146
+ rescue ::Exception
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ # Redirect our IO
153
+ # TODO: make this configurable
154
+ def redirect_io( simulate = false )
155
+ begin
156
+ STDIN.reopen '/dev/null'
157
+ rescue ::Exception
158
+ end
159
+
160
+ unless simulate
161
+ STDOUT.reopen '/dev/null', 'a'
162
+ STDERR.reopen '/dev/null', 'a'
163
+ end
164
+ end
165
+
166
+ def drop_privileges
167
+ if DaemonKit.configuration.group
168
+ begin
169
+ group = Etc.getgrnam( DaemonKit.configuration.group )
170
+ Process::Sys.setgid( group.gid.to_i )
171
+ rescue => e
172
+ $stderr.puts "Caught exception while trying to drop group privileges: #{e.message}"
173
+ end
174
+ end
175
+ if DaemonKit.configuration.user
176
+ begin
177
+ user = Etc.getpwnam( DaemonKit.configuration.user )
178
+ Process::Sys.setuid( user.uid.to_i )
179
+ rescue => e
180
+ $stderr.puts "Caught exception while trying to drop user privileges: #{e.message}"
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ end
187
+ end