apphunkd 0.9.0
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/.document +5 -0
- data/.gitignore +22 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +78 -0
- data/TODO +1 -0
- data/VERSION +1 -0
- data/apphunkd.gemspec +258 -0
- data/bin/apphunkd +4 -0
- data/config/arguments.rb +12 -0
- data/config/boot.rb +68 -0
- data/config/environment.rb +23 -0
- data/config/environments/development.rb +2 -0
- data/config/environments/production.rb +2 -0
- data/config/environments/test.rb +2 -0
- data/config/post-daemonize/readme +5 -0
- data/config/pre-daemonize/readme +12 -0
- data/config/pre-daemonize/requires.rb +2 -0
- data/lib/apphunkd.rb +25 -0
- data/lib/apphunkd/api.rb +5 -0
- data/lib/apphunkd/api/service.rb +27 -0
- data/lib/apphunkd/queue.rb +96 -0
- data/lib/apphunkd/remote.rb +29 -0
- data/lib/apphunkd/remote/result.rb +15 -0
- data/libexec/apphunkd-daemon.rb +13 -0
- data/script/console +3 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/lib/apphunkd/api/service_spec.rb +47 -0
- data/spec/lib/apphunkd/queue_spec.rb +129 -0
- data/spec/lib/apphunkd/remote_spec.rb +61 -0
- data/spec/lib/apphunkd_spec.rb +50 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +13 -0
- data/support/apphunkd.initd +47 -0
- data/support/apphunkd.monitrc +3 -0
- data/tasks/rspec.rake +21 -0
- data/vendor/daemon-kit/Configuration.txt +102 -0
- data/vendor/daemon-kit/Deployment.txt +113 -0
- data/vendor/daemon-kit/History.txt +97 -0
- data/vendor/daemon-kit/Logging.txt +92 -0
- data/vendor/daemon-kit/Manifest.txt +166 -0
- data/vendor/daemon-kit/PostInstall.txt +6 -0
- data/vendor/daemon-kit/README.rdoc +130 -0
- data/vendor/daemon-kit/Rakefile +37 -0
- data/vendor/daemon-kit/RuoteParticipants.txt +113 -0
- data/vendor/daemon-kit/TODO.txt +37 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/USAGE +7 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/daemon_kit_generator.rb +161 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/README +48 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/Rakefile +6 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/boot.rb +68 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environment.rb +23 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/pre-daemonize/readme +12 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/lib/daemon.rb +2 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/console +3 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/destroy +14 -0
- data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/generate +14 -0
- data/vendor/daemon-kit/bin/daemon_kit +18 -0
- data/vendor/daemon-kit/daemon_generators/amqp/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/amqp/amqp_generator.rb +65 -0
- data/vendor/daemon-kit/daemon_generators/amqp/templates/config/amqp.yml +28 -0
- data/vendor/daemon-kit/daemon_generators/amqp/templates/config/initializers/amqp.rb +7 -0
- data/vendor/daemon-kit/daemon_generators/amqp/templates/libexec/daemon.rb +37 -0
- data/vendor/daemon-kit/daemon_generators/cron/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/cron/cron_generator.rb +64 -0
- data/vendor/daemon-kit/daemon_generators/cron/templates/config/initializers/cron.rb +11 -0
- data/vendor/daemon-kit/daemon_generators/cron/templates/libexec/daemon.rb +43 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/USAGE +11 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/cucumber_generator.rb +38 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber +8 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber.rake +13 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
- data/vendor/daemon-kit/daemon_generators/cucumber/templates/env.rb +7 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy.rb +53 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
- data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
- data/vendor/daemon-kit/daemon_generators/jabber/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/jabber/jabber_generator.rb +65 -0
- data/vendor/daemon-kit/daemon_generators/jabber/templates/config/initializers/jabber.rb +7 -0
- data/vendor/daemon-kit/daemon_generators/jabber/templates/config/jabber.yml +26 -0
- data/vendor/daemon-kit/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/nanite_agent_generator.rb +68 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb +6 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/nanite.yml +35 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/lib/actors/sample.rb +11 -0
- data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/libexec/daemon.rb +31 -0
- data/vendor/daemon-kit/daemon_generators/rspec/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/rspec/rspec_generator.rb +55 -0
- data/vendor/daemon-kit/daemon_generators/rspec/templates/spec.rb +11 -0
- data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec.opts +1 -0
- data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec_helper.rb +21 -0
- data/vendor/daemon-kit/daemon_generators/rspec/templates/tasks/rspec.rake +21 -0
- data/vendor/daemon-kit/daemon_generators/ruote/USAGE +5 -0
- data/vendor/daemon-kit/daemon_generators/ruote/ruote_generator.rb +67 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/config/amqp.yml +30 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/config/initializers/ruote.rb +13 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/config/ruote.yml +23 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/daemon.rb +4 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/sample.rb +26 -0
- data/vendor/daemon-kit/daemon_generators/ruote/templates/libexec/daemon.rb +33 -0
- data/vendor/daemon-kit/lib/daemon_kit.rb +54 -0
- data/vendor/daemon-kit/lib/daemon_kit/abstract_logger.rb +235 -0
- data/vendor/daemon-kit/lib/daemon_kit/amqp.rb +38 -0
- data/vendor/daemon-kit/lib/daemon_kit/application.rb +187 -0
- data/vendor/daemon-kit/lib/daemon_kit/arguments.rb +165 -0
- data/vendor/daemon-kit/lib/daemon_kit/commands/console.rb +38 -0
- data/vendor/daemon-kit/lib/daemon_kit/config.rb +108 -0
- data/vendor/daemon-kit/lib/daemon_kit/console_daemon.rb +2 -0
- data/vendor/daemon-kit/lib/daemon_kit/core_ext.rb +1 -0
- data/vendor/daemon-kit/lib/daemon_kit/core_ext/configurable.rb +96 -0
- data/vendor/daemon-kit/lib/daemon_kit/core_ext/string.rb +22 -0
- data/vendor/daemon-kit/lib/daemon_kit/cron.rb +48 -0
- data/vendor/daemon-kit/lib/daemon_kit/cucumber/world.rb +38 -0
- data/vendor/daemon-kit/lib/daemon_kit/deployment/capistrano.rb +482 -0
- data/vendor/daemon-kit/lib/daemon_kit/em.rb +43 -0
- data/vendor/daemon-kit/lib/daemon_kit/error_handlers/base.rb +32 -0
- data/vendor/daemon-kit/lib/daemon_kit/error_handlers/hoptoad.rb +61 -0
- data/vendor/daemon-kit/lib/daemon_kit/error_handlers/mail.rb +85 -0
- data/vendor/daemon-kit/lib/daemon_kit/exceptions.rb +8 -0
- data/vendor/daemon-kit/lib/daemon_kit/initializer.rb +438 -0
- data/vendor/daemon-kit/lib/daemon_kit/jabber.rb +170 -0
- data/vendor/daemon-kit/lib/daemon_kit/nanite.rb +7 -0
- data/vendor/daemon-kit/lib/daemon_kit/nanite/agent.rb +56 -0
- data/vendor/daemon-kit/lib/daemon_kit/pid_file.rb +61 -0
- data/vendor/daemon-kit/lib/daemon_kit/ruote_participants.rb +119 -0
- data/vendor/daemon-kit/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
- data/vendor/daemon-kit/lib/daemon_kit/ruote_workitem.rb +169 -0
- data/vendor/daemon-kit/lib/daemon_kit/safety.rb +85 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks.rb +2 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks/environment.rake +10 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks/framework.rake +120 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks/god.rake +62 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks/log.rake +8 -0
- data/vendor/daemon-kit/lib/daemon_kit/tasks/monit.rake +29 -0
- data/vendor/daemon-kit/script/console +10 -0
- data/vendor/daemon-kit/script/destroy +14 -0
- data/vendor/daemon-kit/script/generate +14 -0
- data/vendor/daemon-kit/script/txt2html +71 -0
- data/vendor/daemon-kit/spec/abstract_logger_spec.rb +126 -0
- data/vendor/daemon-kit/spec/argument_spec.rb +70 -0
- data/vendor/daemon-kit/spec/config_spec.rb +79 -0
- data/vendor/daemon-kit/spec/configurable_spec.rb +56 -0
- data/vendor/daemon-kit/spec/daemon_kit_spec.rb +7 -0
- data/vendor/daemon-kit/spec/error_handlers_spec.rb +23 -0
- data/vendor/daemon-kit/spec/fixtures/env.yml +15 -0
- data/vendor/daemon-kit/spec/fixtures/noenv.yml +4 -0
- data/vendor/daemon-kit/spec/initializer_spec.rb +26 -0
- data/vendor/daemon-kit/spec/spec.opts +1 -0
- data/vendor/daemon-kit/spec/spec_helper.rb +27 -0
- data/vendor/daemon-kit/tasks/rspec.rake +21 -0
- data/vendor/daemon-kit/templates/god/god.erb +69 -0
- data/vendor/daemon-kit/templates/monit/monit.erb +14 -0
- data/vendor/daemon-kit/test/test_amqp_generator.rb +48 -0
- data/vendor/daemon-kit/test/test_cron_generator.rb +45 -0
- data/vendor/daemon-kit/test/test_daemon-kit_generator.rb +84 -0
- data/vendor/daemon-kit/test/test_daemon_kit_config.rb +28 -0
- data/vendor/daemon-kit/test/test_deploy_capistrano_generator.rb +48 -0
- data/vendor/daemon-kit/test/test_generator_helper.rb +29 -0
- data/vendor/daemon-kit/test/test_helper.rb +7 -0
- data/vendor/daemon-kit/test/test_jabber_generator.rb +49 -0
- data/vendor/daemon-kit/test/test_nanite_agent_generator.rb +49 -0
- data/vendor/daemon-kit/test/test_ruote_generator.rb +45 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail.rb +5 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/address.rb +426 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/config.rb +67 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/header.rb +960 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/index.rb +9 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/main.rb +6 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/net.rb +248 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/port.rb +379 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
- data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/version.rb +39 -0
- data/vendor/daemon-kit/vendor/tmail.rb +13 -0
- metadata +281 -0
|
@@ -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
|
|
@@ -0,0 +1,165 @@
|
|
|
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
|
+
# -l path or --log path => /path/to/log/file
|
|
62
|
+
#
|
|
63
|
+
def configuration( argv )
|
|
64
|
+
configs = []
|
|
65
|
+
|
|
66
|
+
i = 0
|
|
67
|
+
while i < argv.size
|
|
68
|
+
if argv[i] == "--config"
|
|
69
|
+
argv.delete_at( i )
|
|
70
|
+
configs << argv.delete_at(i)
|
|
71
|
+
next
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if argv[i] == "-e" || argv[i] == "--env"
|
|
75
|
+
argv.delete_at( i )
|
|
76
|
+
configs << "environment=#{argv.delete_at(i)}"
|
|
77
|
+
next
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
if argv[i] == "-l" || argv[i] == "--log"
|
|
81
|
+
argv.delete_at( i )
|
|
82
|
+
configs << "log_path=#{argv.delete_at(i)}"
|
|
83
|
+
next
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if argv[i] == "--pid"
|
|
87
|
+
argv.delete_at( i )
|
|
88
|
+
configs << "pid_file=#{argv.delete_at(i)}"
|
|
89
|
+
next
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
i += 1
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
return configs, argv
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Return the arguments remaining after running through #configuration
|
|
99
|
+
def arguments( argv )
|
|
100
|
+
self.configuration( argv ).last
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
attr_reader :options
|
|
105
|
+
|
|
106
|
+
def initialize
|
|
107
|
+
@options = {}
|
|
108
|
+
|
|
109
|
+
@parser = OptionParser.new do |opts|
|
|
110
|
+
opts.banner = "Usage: #{File.basename($0)} [command] [options]"
|
|
111
|
+
|
|
112
|
+
opts.separator ""
|
|
113
|
+
|
|
114
|
+
opts.separator "Command is one of the following:"
|
|
115
|
+
opts.separator " run - Run the daemon without forking (default)"
|
|
116
|
+
opts.separator " start - Run the daemon"
|
|
117
|
+
opts.separator " stop - Stop the running daemon"
|
|
118
|
+
|
|
119
|
+
opts.separator ""
|
|
120
|
+
|
|
121
|
+
opts.separator "Options can be:"
|
|
122
|
+
|
|
123
|
+
arg_file = File.join( DaemonKit.root, 'config', 'arguments.rb' )
|
|
124
|
+
eval(IO.read(arg_file), binding, arg_file) if File.exists?( arg_file )
|
|
125
|
+
|
|
126
|
+
opts.on("-e", "--env ENVIRONMENT", "Environment for the process", "Defaults to development") do
|
|
127
|
+
# Nothing, just here for show
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
opts.on("--pidfile PATH", "Path to the pidfile", "Defaults to log/#{DaemonKit.configuration.daemon_name}.pid") do
|
|
131
|
+
# Nothing, just here for show
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
opts.on("-l", "--log /path/to/logfile", "Path to the log file", "Defaults to log/[environment].log") do
|
|
135
|
+
# Nothing, just here for show
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
opts.separator ""
|
|
139
|
+
opts.separator "Advanced configurations:"
|
|
140
|
+
opts.on("--config ATTRIBUTE=VALUE",
|
|
141
|
+
"Change values of the daemon-kit Configuration instance",
|
|
142
|
+
"Example: log_dir=/path/to/log-directory") do
|
|
143
|
+
# Nothing, just here for show
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
opts.separator ""
|
|
147
|
+
|
|
148
|
+
opts.separator "Common options:"
|
|
149
|
+
opts.on("-v", "--version", "Show version information and exit") do
|
|
150
|
+
puts "daemon-kit #{DaemonKit::VERSION} (http://github.com/kennethkalmer/daemon-kit)"
|
|
151
|
+
exit
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
155
|
+
puts opts
|
|
156
|
+
exit
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def parse( argv )
|
|
162
|
+
@parser.parse!( argv )
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
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"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module DaemonKit
|
|
2
|
+
|
|
3
|
+
# Simplify simple config file loading for daemons. Assumes the
|
|
4
|
+
# config files all live in DAEMON_ROOT/config and are YAML
|
|
5
|
+
# files. Loaded configs are accessed like a hash with string
|
|
6
|
+
# keys.
|
|
7
|
+
#
|
|
8
|
+
# Config files can either be keyed by environment (default behavior)
|
|
9
|
+
# or be a normal hash.
|
|
10
|
+
#
|
|
11
|
+
# Load a config by passing the filename (with or without the .yml
|
|
12
|
+
# extension) to #load.
|
|
13
|
+
#
|
|
14
|
+
# At this stage the configs are read-only.
|
|
15
|
+
#
|
|
16
|
+
# Any of the keys can be called as methods as well.
|
|
17
|
+
class Config
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
|
|
21
|
+
# Load the +config+.yml file from DAEMON_ROOT/config
|
|
22
|
+
def load( config )
|
|
23
|
+
config = config.to_s
|
|
24
|
+
config += '.yml' unless config =~ /\.yml$/
|
|
25
|
+
|
|
26
|
+
path = File.join( DAEMON_ROOT, 'config', config )
|
|
27
|
+
|
|
28
|
+
raise ArgumentError, "Can't find #{path}" unless File.exists?( path )
|
|
29
|
+
|
|
30
|
+
new( YAML.load_file( path ) )
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Return the +config+.yml file as a raw hash.
|
|
34
|
+
def hash( config, symbolize = false )
|
|
35
|
+
self.load( config ).to_h( symbolize )
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Expects a hash, looks for DAEMON_ENV key
|
|
41
|
+
def initialize( config_data ) #:nodoc:
|
|
42
|
+
if config_data.has_key?( DAEMON_ENV )
|
|
43
|
+
self.data = config_data[ DAEMON_ENV ]
|
|
44
|
+
else
|
|
45
|
+
self.data = config_data
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Pick out a config by name
|
|
50
|
+
def []( key )
|
|
51
|
+
@data[ key.to_s ]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Return the internal hash structure used, optionally symbolizing
|
|
55
|
+
# the first level of keys in the hash
|
|
56
|
+
def to_h( symbolize = false )
|
|
57
|
+
symbolize ? @data.symbolize_keys : @data
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def method_missing( method_name, *args ) #:nodoc:
|
|
61
|
+
unless method_name.to_s =~ /[\w_]+=$/
|
|
62
|
+
if @data.keys.include?( method_name.to_s )
|
|
63
|
+
return @data.send( method_name.to_s )
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def data=( hash )
|
|
71
|
+
@data = hash
|
|
72
|
+
class << @data
|
|
73
|
+
def symbolize_keys( hash = self )
|
|
74
|
+
hash.inject({}) { |result, (key, value)|
|
|
75
|
+
new_key = case key
|
|
76
|
+
when String then key.to_sym
|
|
77
|
+
else key
|
|
78
|
+
end
|
|
79
|
+
new_value = case value
|
|
80
|
+
when Hash then symbolize_keys(value)
|
|
81
|
+
else value
|
|
82
|
+
end
|
|
83
|
+
result[new_key] = new_value
|
|
84
|
+
result
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
extend_hash( @data )
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def extend_hash( hash )
|
|
93
|
+
hash.keys.each do |k|
|
|
94
|
+
hash.instance_eval <<-KEY
|
|
95
|
+
def #{k}
|
|
96
|
+
fetch("#{k}")
|
|
97
|
+
end
|
|
98
|
+
KEY
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
hash.each do |(key, value)|
|
|
102
|
+
case value
|
|
103
|
+
when Hash then extend_hash( value )
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|