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.
- data/Configuration.txt +110 -0
- data/Deployment.txt +113 -0
- data/History.txt +97 -0
- data/Logging.txt +92 -0
- data/Manifest.txt +166 -0
- data/PostInstall.txt +6 -0
- data/README.rdoc +130 -0
- data/Rakefile +37 -0
- data/RuoteParticipants.txt +113 -0
- data/TODO.txt +37 -0
- data/app_generators/daemon_kit/USAGE +7 -0
- data/app_generators/daemon_kit/daemon_kit_generator.rb +161 -0
- data/app_generators/daemon_kit/templates/README +48 -0
- data/app_generators/daemon_kit/templates/Rakefile +6 -0
- data/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
- data/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
- data/app_generators/daemon_kit/templates/config/boot.rb +68 -0
- data/app_generators/daemon_kit/templates/config/environment.rb +23 -0
- data/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
- data/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
- data/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
- data/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
- data/app_generators/daemon_kit/templates/config/pre-daemonize/readme +12 -0
- data/app_generators/daemon_kit/templates/lib/daemon.rb +2 -0
- data/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
- 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/bin/daemon_kit +18 -0
- data/daemon_generators/amqp/USAGE +5 -0
- data/daemon_generators/amqp/amqp_generator.rb +65 -0
- data/daemon_generators/amqp/templates/config/amqp.yml +28 -0
- data/daemon_generators/amqp/templates/config/initializers/amqp.rb +7 -0
- data/daemon_generators/amqp/templates/libexec/daemon.rb +37 -0
- data/daemon_generators/cron/USAGE +5 -0
- data/daemon_generators/cron/cron_generator.rb +64 -0
- data/daemon_generators/cron/templates/config/initializers/cron.rb +11 -0
- data/daemon_generators/cron/templates/libexec/daemon.rb +43 -0
- data/daemon_generators/cucumber/USAGE +11 -0
- data/daemon_generators/cucumber/cucumber_generator.rb +38 -0
- data/daemon_generators/cucumber/templates/cucumber +8 -0
- data/daemon_generators/cucumber/templates/cucumber.rake +13 -0
- data/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
- data/daemon_generators/cucumber/templates/env.rb +7 -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.rb +53 -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/environments/staging.rb +0 -0
- data/daemon_generators/jabber/USAGE +5 -0
- data/daemon_generators/jabber/jabber_generator.rb +65 -0
- data/daemon_generators/jabber/templates/config/initializers/jabber.rb +7 -0
- data/daemon_generators/jabber/templates/config/jabber.yml +26 -0
- data/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
- data/daemon_generators/nanite_agent/USAGE +5 -0
- data/daemon_generators/nanite_agent/nanite_agent_generator.rb +68 -0
- data/daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb +6 -0
- data/daemon_generators/nanite_agent/templates/config/nanite.yml +35 -0
- data/daemon_generators/nanite_agent/templates/lib/actors/sample.rb +11 -0
- data/daemon_generators/nanite_agent/templates/libexec/daemon.rb +31 -0
- data/daemon_generators/rspec/USAGE +5 -0
- data/daemon_generators/rspec/rspec_generator.rb +55 -0
- data/daemon_generators/rspec/templates/spec.rb +11 -0
- data/daemon_generators/rspec/templates/spec/spec.opts +1 -0
- data/daemon_generators/rspec/templates/spec/spec_helper.rb +21 -0
- data/daemon_generators/rspec/templates/tasks/rspec.rake +21 -0
- data/daemon_generators/ruote/USAGE +5 -0
- data/daemon_generators/ruote/ruote_generator.rb +67 -0
- data/daemon_generators/ruote/templates/config/amqp.yml +30 -0
- data/daemon_generators/ruote/templates/config/initializers/ruote.rb +13 -0
- data/daemon_generators/ruote/templates/config/ruote.yml +23 -0
- data/daemon_generators/ruote/templates/lib/daemon.rb +4 -0
- data/daemon_generators/ruote/templates/lib/sample.rb +26 -0
- data/daemon_generators/ruote/templates/libexec/daemon.rb +33 -0
- data/lib/daemon_kit.rb +62 -0
- data/lib/daemon_kit/abstract_logger.rb +235 -0
- data/lib/daemon_kit/amqp.rb +38 -0
- data/lib/daemon_kit/application.rb +187 -0
- data/lib/daemon_kit/arguments.rb +165 -0
- data/lib/daemon_kit/commands/console.rb +38 -0
- data/lib/daemon_kit/config.rb +108 -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/configurable.rb +96 -0
- data/lib/daemon_kit/core_ext/string.rb +22 -0
- data/lib/daemon_kit/cron.rb +48 -0
- data/lib/daemon_kit/cucumber/world.rb +38 -0
- data/lib/daemon_kit/deployment/capistrano.rb +482 -0
- data/lib/daemon_kit/em.rb +43 -0
- data/lib/daemon_kit/error_handlers/base.rb +32 -0
- data/lib/daemon_kit/error_handlers/hoptoad.rb +60 -0
- data/lib/daemon_kit/error_handlers/mail.rb +85 -0
- data/lib/daemon_kit/exceptions.rb +15 -0
- data/lib/daemon_kit/initializer.rb +438 -0
- data/lib/daemon_kit/jabber.rb +170 -0
- data/lib/daemon_kit/nanite.rb +7 -0
- data/lib/daemon_kit/nanite/agent.rb +56 -0
- data/lib/daemon_kit/pid_file.rb +61 -0
- data/lib/daemon_kit/ruote_participants.rb +119 -0
- data/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
- data/lib/daemon_kit/ruote_workitem.rb +169 -0
- data/lib/daemon_kit/safety.rb +85 -0
- data/lib/daemon_kit/tasks.rb +2 -0
- data/lib/daemon_kit/tasks/environment.rake +10 -0
- data/lib/daemon_kit/tasks/framework.rake +120 -0
- 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/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/spec/abstract_logger_spec.rb +126 -0
- data/spec/argument_spec.rb +70 -0
- data/spec/config_spec.rb +79 -0
- data/spec/configurable_spec.rb +56 -0
- data/spec/daemon_kit_spec.rb +7 -0
- 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 +26 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +27 -0
- data/tasks/rspec.rake +21 -0
- data/templates/god/god.erb +69 -0
- data/templates/monit/monit.erb +14 -0
- data/test/test_amqp_generator.rb +48 -0
- data/test/test_cron_generator.rb +45 -0
- data/test/test_daemon-kit_generator.rb +84 -0
- data/test/test_daemon_kit_config.rb +28 -0
- data/test/test_deploy_capistrano_generator.rb +48 -0
- data/test/test_generator_helper.rb +29 -0
- data/test/test_helper.rb +7 -0
- data/test/test_jabber_generator.rb +49 -0
- data/test/test_nanite_agent_generator.rb +49 -0
- data/test/test_ruote_generator.rb +45 -0
- 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 +281 -0
|
@@ -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
|