Skip to content

Commit

Permalink
Added a soft stop and switched old one to kill.
Browse files Browse the repository at this point in the history
  • Loading branch information
DAddYE committed Aug 26, 2011
1 parent 057bb48 commit 3159efa
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 41 deletions.
4 changes: 0 additions & 4 deletions Gemfile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,7 +2,3 @@ source "http://rubygems.org"


# Specify your gem's dependencies in forever.gemspec # Specify your gem's dependencies in forever.gemspec
gemspec gemspec

gem 'guard'
gem 'guard-rspec'
gem 'growl'
5 changes: 0 additions & 5 deletions Guardfile

This file was deleted.

4 changes: 2 additions & 2 deletions Rakefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ end


desc "Bump version on github" desc "Bump version on github"
task :bump do task :bump do
puts "\e[31mNothing to commit (working directory clean)\e[0m" and return unless `git status -s`.chomp! puts "\e[31mNothing to commit (working directory clean)\e[0m" and return unless `git status -s`.strip == ""
version = Bundler.load_gemspec(Dir[File.expand_path('../*.gemspec', __FILE__)].first).version version = Bundler.load_gemspec(Dir[File.expand_path('../*.gemspec', __FILE__)].first).version
sh "git add .; git commit -a -m \"Bump to version #{version}\"" sh "git add .; git commit -a -m \"Bump to version #{version}\""
end end
Expand All @@ -24,4 +24,4 @@ RSpec::Core::RakeTask.new("spec") do |t|
t.rspec_opts = %w(-fs --color --fail-fast) t.rspec_opts = %w(-fs --color --fail-fast)
end end


task :default => :spec task :default => :spec
19 changes: 18 additions & 1 deletion bin/foreverb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -50,6 +50,23 @@ class CLI < Thor
end end
end end


desc "kill [DAEMON] [--all] [--yes]", "Kill one or more matching daemons"
method_option :all, :type => :boolean, :aliases => "-a", :desc => "All matching daemons"
method_option :yes, :type => :boolean, :aliases => "-y", :desc => "Don't ask permission to kill daemon"
def kill(daemon=nil)
find(daemon, :multiple => options.all).each do |conf|
if options.yes || yes?("Do you want really kill \e[1m#{conf[:file]}\e[0m?")
say_status "KILLING", conf[:file]
begin
pid = File.read(conf[:pid]).to_i
Process.kill(:INT, pid)
rescue Exception => e
say_status "ERROR", e.message, :red
end
end
end
end

desc "start [DAEMON] [--all] [--yes]", "Start one or more matching daemons" desc "start [DAEMON] [--all] [--yes]", "Start one or more matching daemons"
method_option :all, :type => :boolean, :aliases => "-a", :desc => "All matching daemons" method_option :all, :type => :boolean, :aliases => "-a", :desc => "All matching daemons"
method_option :yes, :type => :boolean, :aliases => "-y", :desc => "Don't ask permission to start the daemon" method_option :yes, :type => :boolean, :aliases => "-y", :desc => "Don't ask permission to start the daemon"
Expand Down Expand Up @@ -122,4 +139,4 @@ class CLI < Thor
end end


ARGV << "-h" if ARGV.empty? ARGV << "-h" if ARGV.empty?
CLI.start(ARGV) CLI.start(ARGV)
6 changes: 5 additions & 1 deletion examples/sample
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ require 'forever'
Forever.run do Forever.run do
dir File.expand_path('../', __FILE__) # Default is ../../__FILE__ dir File.expand_path('../', __FILE__) # Default is ../../__FILE__


every 5.seconds do
puts 'every 5 seconds'
end

on_ready do on_ready do
puts "All jobs will will wait me for 1 second"; sleep 1 puts "All jobs will will wait me for 1 second"; sleep 1
end end
Expand Down Expand Up @@ -50,4 +54,4 @@ Forever.run do
on_exit do on_exit do
puts "Bye bye" puts "Bye bye"
end end
end end
112 changes: 89 additions & 23 deletions lib/forever/base.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -16,20 +16,37 @@ def initialize(options={}, &block)


write_config! write_config!


if ARGV.any? { |arg| arg == "config" } case ARGV[0]
print config.to_yaml when 'config'
return print config.to_yaml
exit
when 'start', 'restart', 'up', nil
stop
when 'stop'
stop
exit
when 'kill'
stop!
exit
when 'help', '-h'
print <<-RUBY.gsub(/ {10}/,'') % File.basename(file)
Usage: \e[1m./%s\e[0m [start|stop|kill|restart|config]
Commands:
start stop (if present) the daemon and perform a start
stop stop the daemon if a during when it is idle
restart same as start
kill force stop by sending a KILL signal to the process
config show the current daemons config
RUBY
exit
end end


return if ARGV.any? { |arg| arg == "up" }

stop!

return if ARGV.any? { |arg| arg == "stop" }

fork do fork do
$0 = "Forever: #{$0}" $0 = "Forever: #{$0}"
print "=> Process demonized with pid #{Process.pid} with Forever v.#{Forever::VERSION}\n" print "=> Process demonized with pid \e[1m#{Process.pid}\e[0m with Forever v.#{Forever::VERSION}\n"


%w(INT TERM KILL).each { |signal| trap(signal) { stop! } } %w(INT TERM KILL).each { |signal| trap(signal) { stop! } }
trap(:HUP) do trap(:HUP) do
Expand All @@ -46,12 +63,25 @@ def initialize(options={}, &block)


threads = [] threads = []
safe_call(on_ready) if on_ready safe_call(on_ready) if on_ready
started_at = Time.now

jobs.each do |job| jobs.each do |job|
threads << Thread.new do threads << Thread.new do
loop { job.time?(Time.now) ? safe_call(job) : sleep(1) } loop do
break if File.exist?(stop_txt) && File.mtime(stop_txt) > started_at
job.time?(Time.now) ? safe_call(job) : sleep(1)
end
end end
end end

# Launch our workers
threads.map(&:join) threads.map(&:join)

# If we are here it means we are exiting so we can remove the pid and pending stop.txt
FileUtils.rm_f(pid)
FileUtils.rm_f(stop_txt)

on_exit.call if on_exit
end end


self self
Expand Down Expand Up @@ -95,19 +125,30 @@ def pid(value=nil)
# Search if there is a running process and stop it # Search if there is a running process and stop it
# #
def stop! def stop!
if exists?(pid) FileUtils.rm_f(stop_txt)
_pid = File.read(pid).to_i if running?
print "=> Found pid #{_pid}...\n" pid_was = File.read(pid).to_i
FileUtils.rm_f(pid) FileUtils.rm_f(pid)
begin print "=> Killing process \e[1m%d\e[0m...\n" % pid_was
print "=> Killing process #{_pid}...\n" on_exit.call if on_exit
on_exit.call if on_exit Process.kill(:KILL, pid_was)
Process.kill(:KILL, _pid)
rescue Errno::ESRCH => e
puts "=> #{e.message}"
end
else else
print "=> Pid not found, process seems don't exist!\n" print "=> Process with \e[1mnot found\e[0m"
end
end

##
# Perform a soft stop
#
def stop
if running?
print '=> Waiting the daemon\'s death '
FileUtils.touch(stop_txt)
while running?(true)
print '.'; $stdout.flush
sleep 1
end
print " \e[1mDONE\e[0m\n"
end end
end end


Expand All @@ -132,6 +173,27 @@ def on_ready(&block)
block_given? ? @_on_ready = block : @_on_ready block_given? ? @_on_ready = block : @_on_ready
end end


##
# Returns true if the pid exist and the process is running
#
def running?(silent=false)
if exists?(pid)
current = File.read(pid).to_i
print "=> Found pid \e[1m%d\e[0m...\n" % current unless silent
else
print "=> Pid \e[1mnot found\e[0m, process seems don't exist!\n" unless silent
return false
end

is_running = begin
Process.kill(0, current)
rescue Errno::ESRCH
false
end

is_running
end

def to_s def to_s
"#<Forever dir:#{dir}, file:#{file}, log:#{log}, pid:#{pid} jobs:#{jobs.size}>" "#<Forever dir:#{dir}, file:#{file}, log:#{log}, pid:#{pid} jobs:#{jobs.size}>"
end end
Expand Down Expand Up @@ -161,5 +223,9 @@ def safe_call(block)
on_error[e] if on_error on_error[e] if on_error
end end
end end

def stop_txt
@_stop_txt ||= File.join(dir, 'stop.txt')
end
end # Base end # Base
end # Forever end # Forever
2 changes: 1 addition & 1 deletion lib/forever/version.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,3 @@
module Forever module Forever
VERSION = "0.2.4" unless defined?(Forever::VERSION) VERSION = "0.2.5" unless defined?(Forever::VERSION)
end end
11 changes: 10 additions & 1 deletion spec/cli_spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,4 +22,13 @@
result.should_not match(/ERROR/) result.should_not match(/ERROR/)
cli('list').should match(/NOT RUNNING/) cli('list').should match(/NOT RUNNING/)
end end
end
it "should kill daemons" do
run_example
cli('list').should match(/RUNNING/)
result = cli('kill -a -y')
result.should match(/KILLING/)
result.should_not match(/ERROR/)
cli('list').should match(/NOT RUNNING/)
end
end
5 changes: 3 additions & 2 deletions spec/foreverb_spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
describe Forever do describe Forever do


before :each do before :each do
$stdout = StringIO.new
ARGV << 'up' ARGV << 'up'
end end


Expand Down Expand Up @@ -41,7 +42,7 @@
sleep 0.1 while !File.exist?(@forever.pid) sleep 0.1 while !File.exist?(@forever.pid)
pid = File.read(@forever.pid).to_i pid = File.read(@forever.pid).to_i
Process.waitpid(pid) Process.waitpid(pid)
$stdout.string.should match(/pid not found/i) $stdout.string.should match(/not found/i)
$stdout = stdout_was $stdout = stdout_was
end end
end end
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ def cli(task)
end end
ARGV.clear ARGV.clear
end end
end end

0 comments on commit 3159efa

Please sign in to comment.