Permalink
Browse files

added state_file management

added restart (using state_file) and status commands
  • Loading branch information...
soulware authored and kennethkalmer committed Oct 12, 2009
1 parent d98cc2c commit c6d03caa820e085cd30f1f505fd49f7b159050d6
View
@@ -107,6 +107,7 @@ lib/daemon_kit/ruote_participants.rb
lib/daemon_kit/ruote_pseudo_participant.rb
lib/daemon_kit/ruote_workitem.rb
lib/daemon_kit/safety.rb
+lib/daemon_kit/state_file.rb
lib/daemon_kit/tasks.rb
lib/daemon_kit/tasks/environment.rake
lib/daemon_kit/tasks/framework.rake
View
@@ -21,6 +21,7 @@ module DaemonKit
autoload :Config, 'daemon_kit/config'
autoload :Safety, 'daemon_kit/safety'
autoload :PidFile, 'daemon_kit/pid_file'
+ autoload :StateFile, 'daemon_kit/state_file'
autoload :AbstractLogger, 'daemon_kit/abstract_logger'
autoload :EM, 'daemon_kit/em'
autoload :Configurable, 'daemon_kit/core_ext/configurable'
@@ -1,4 +1,5 @@
require 'timeout'
+require 'yaml'
module DaemonKit
@@ -13,22 +14,63 @@ def exec( file )
DaemonKit.configuration.daemon_name ||= File.basename( file )
+ # if configuration owns the args - they get set in configuration
+ # TODO - what if configuration does not own the args?
+ parsed_configs = {
+ :pid_file => DaemonKit.configuration.pid_file,
+ :log_path => DaemonKit.configuration.log_path,
+ :environment => DaemonKit.configuration.environment
+ }
+
command, configs, args = Arguments.parse( ARGV )
case command
when :run
parse_arguments( args )
- run( file )
+
+ run( file, parsed_configs, args )
when :start
parse_arguments( args )
- start( file )
+
+ start( file, parsed_configs, args )
when :stop
stop
+ when :restart
+ state = StateFile.state
+ configs = state[:configs] rescue {}
+ args = state[:args] rescue []
+
+ parse_arguments( args )
+
+ DaemonKit.configuration.update_environment_in_a_dangerous_way(configs[:environment]) if configs[:environment]
+ DaemonKit.configuration.pid_file = configs[:pid_file] if configs[:pid_file]
+ DaemonKit.configuration.log_path = configs[:log_path] if configs[:log_path]
+
+ puts "environment: #{DaemonKit.configuration.environment}"
+ puts "log_path: #{DaemonKit.configuration.log_path}"
+ puts "pid_file: #{DaemonKit.configuration.pid_file}"
+
+ stop
+ start( file, configs, args )
+ when :status
+ status
end
end
+ def status
+ @pid_file = PidFile.new( DaemonKit.configuration.pid_file )
+
+ puts @pid_file.running? ? "Process running with id #{@pid_file.pid}" : "Nothing running"
+ end
+
# Run the daemon in the foreground without daemonizing
- def run( file )
+ def run( file, configs, args )
+ @pid_file = PidFile.new( DaemonKit.configuration.pid_file )
+ @pid_file.ensure_stopped!
+ # @pid_file.write!
+
+ StateFile.write(configs, args)
+
self.chroot
self.clean_fd
self.redirect_io( true )
@@ -39,9 +81,12 @@ def run( file )
end
# Run our file properly
- def start( file )
+ def start( file, configs, args )
self.drop_privileges
self.daemonize
+
+ StateFile.write(configs, args)
+
self.chroot
self.clean_fd
self.redirect_io
@@ -63,6 +108,9 @@ def stop
puts "Sending TERM to #{target_pid}"
Process.kill( 'TERM', target_pid )
+ # otherwise restart never succeeds without force_kill_wait
+ sleep 0.5
+
if seconds = DaemonKit.configuration.force_kill_wait
begin
Timeout::timeout( seconds ) do
@@ -85,6 +133,8 @@ def stop
else
@pid_file.cleanup
end
+
+ StateFile.cleanup
end
# Call this from inside a daemonized process to complete the
@@ -16,7 +16,9 @@ class Arguments
@commands = [
'start',
'stop',
- 'run'
+ 'run',
+ 'restart',
+ 'status'
]
# this has to be handled outside the context of Arguments
@@ -123,9 +125,11 @@ def initialize
opts.separator ""
opts.separator "Command is one of the following:"
- opts.separator " run - Run the daemon without forking (default)"
- opts.separator " start - Run the daemon"
- opts.separator " stop - Stop the running daemon"
+ opts.separator " run - Run the daemon without forking (default)"
+ opts.separator " start - Run the daemon"
+ opts.separator " stop - Stop the running daemon"
+ opts.separator " restart - Restart the running daemon"
+ opts.separator " status - Get status of the running daemon"
opts.separator ""
@@ -353,12 +353,21 @@ def pid_file
@pid_file ||= "#{File.dirname(self.log_path)}/#{self.daemon_name}.pid"
end
+ def state_file
+ @state_file ||= "#{File.dirname(self.log_path)}/#{self.daemon_name}.state"
+ end
+
# Set the log level
def log_level=( level )
@log_level = level
DaemonKit.logger.level = @log_level if DaemonKit.logger
end
+ def update_environment_in_a_dangerous_way(new_env)
+ # why can't we simply call environment= here?
+ ::DAEMON_ENV.replace(new_env)
+ end
+
protected
def run_traps( signal )
@@ -0,0 +1,47 @@
+module DaemonKit
+
+ # Simple statefile (argv) handling for daemon processes
+ class StateFile
+
+ def initialize( path )
+ @path = path.to_absolute_path
+ end
+
+ def exists?
+ File.exists?( @path )
+ end
+
+ def state
+ return nil unless self.exists?
+
+ YAML.load_file(@path)
+ end
+
+ def cleanup
+ File.delete( @path ) rescue Errno::ENOENT
+ end
+ alias zap cleanup
+
+ def write!(argv)
+ File.open( @path, 'w' ) { |f|
+ f.puts argv
+ }
+ end
+
+ def self.state
+ state_file = StateFile.new( DaemonKit.configuration.state_file )
+ state_file.state
+ end
+
+ def self.write(configs, args)
+ state_file = StateFile.new( DaemonKit.configuration.state_file )
+ state = {:configs => configs, :args => args}.to_yaml
+ state_file.write!(state)
+ end
+
+ def self.cleanup
+ state_file = StateFile.new( DaemonKit.configuration.state_file )
+ state_file.cleanup
+ end
+ end
+end

0 comments on commit c6d03ca

Please sign in to comment.