Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git://github.com/mojombo/god into mojombo/ma…

…ster
  • Loading branch information...
commit fd9887f35b3825b1f3cd8c12ced6f18f7b612141 2 parents d8ed21f + a1c2c50
@pjhyett authored
View
1  .gitignore
@@ -1,3 +1,4 @@
+rdoc
coverage
pkg
*.log
View
10 History.txt
@@ -1,3 +1,13 @@
+== 0.10.1 / 2010-05-17
+ * Bug Fixes
+ * Fix date in gemspec
+
+== 0.10.0 / 2010-05-17
+ * Minor Enhancements
+ * Add stop_timeout and stop_signal options to Watch
+ * Bug Fixes
+ * Stop command string was being ignored
+
== 0.9.0 / 2010-04-03
* Minor Enhancements
* Allow kqueue for OpenBSD and NetBSD
View
154 Rakefile
@@ -2,11 +2,41 @@ require 'rubygems'
require 'rake'
require 'date'
+#############################################################################
+#
+# The name of the package
+#
+#############################################################################
+
+NAME = 'god'
+
+#############################################################################
+#
+# Helper functions
+#
+#############################################################################
+
def source_version
- line = File.read('lib/god.rb')[/^\s*VERSION = .*/]
- line.match(/.*VERSION = '(.*)'/)[1]
+ line = File.read("lib/#{NAME}.rb")[/^\s*VERSION\s*=\s*.*/]
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
+end
+
+def gemspec_file
+ "#{NAME}.gemspec"
end
+def gem_file
+ "#{NAME}-#{source_version}.gem"
+end
+
+#############################################################################
+#
+# Standard tasks
+#
+#############################################################################
+
+task :default => :test
+
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
@@ -14,13 +44,33 @@ Rake::TestTask.new(:test) do |test|
test.verbose = true
end
-task :default => :test
+desc "Generate and open coverage stats via rcov"
+task :coverage do
+ require 'rcov'
+ sh "rm -fr coverage"
+ sh "rcov test/test_*.rb"
+ sh "open coverage/index.html"
+end
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "#{NAME} #{source_version}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
desc "Open an irb session preloaded with this library"
task :console do
- sh "irb -rubygems -r ./lib/god.rb"
+ sh "irb -rubygems -r ./lib/#{NAME}.rb"
end
+#############################################################################
+#
+# Custom tasks (add your own tasks here)
+#
+#############################################################################
+
desc "Upload site to Rubyforge"
task :site do
sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god"
@@ -31,54 +81,62 @@ task :site_edge do
sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god/edge"
end
-desc "Run rcov"
-task :coverage do
- `rm -fr coverage`
- `rcov test/test_*.rb`
- `open coverage/index.html`
+#############################################################################
+#
+# Packaging tasks
+#
+#############################################################################
+
+task :release => :build do
+ unless `git branch` =~ /^\* master$/
+ puts "You must be on the master branch to release!"
+ exit!
+ end
+ sh "git commit --allow-empty -a -m 'up to #{source_version}'"
+ sh "git tag v#{source_version}"
+ sh "git push origin master --tags"
+ sh "gem push pkg/#{NAME}-#{source_version}.gem"
end
-require 'rake/rdoctask'
-Rake::RDocTask.new do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = "god #{source_version}"
- rdoc.rdoc_files.include('README*')
- rdoc.rdoc_files.include('lib/**/*.rb')
+task :build => :gemspec do
+ sh "mkdir -p pkg"
+ sh "gem build #{gemspec_file}"
+ sh "mv #{gem_file} pkg"
end
-if defined?(Gem)
- task :release => :build do
- sh "git commit --allow-empty -a -m 'up to #{source_version}'"
- sh "git tag v#{source_version}"
- sh "git push origin master"
- sh "gem push pkg/god-#{source_version}.gem"
- end
+task :gemspec => :validate do
+ # read spec file and split out manifest section
+ spec = File.read(gemspec_file)
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
- task :build => :gemspec do
- sh 'mkdir -p pkg'
- sh 'gem build god.gemspec'
- sh 'mv *.gem pkg'
- end
+ # replace version and date
+ head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
+
+ # determine file list from git ls-files
+ files = `git ls-files`.
+ split("\n").
+ sort.
+ reject { |file| file =~ /^\./ }.
+ reject { |file| file =~ /^(examples|ideas|init|site)/ }.
+ map { |file| " #{file}" }.
+ join("\n")
- task :gemspec do
- # read spec file and split out manifest section
- spec = File.read('god.gemspec')
- head, manifest, tail = spec.split(" # = MANIFEST =\n")
- # replace version and date
- head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
- head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
- # determine file list from git ls-files
- files = `git ls-files`.
- split("\n").
- sort.
- reject { |file| file =~ /^\./ }.
- reject { |file| file =~ /^(ideas|init|site)/ }.
- map { |file| " #{file}" }.
- join("\n")
- # piece file back together and write...
- manifest = " s.files = %w[\n#{files}\n ]\n"
- spec = [head, manifest, tail].join(" # = MANIFEST =\n")
- File.open('god.gemspec', 'w') { |io| io.write(spec) }
- puts "updated god.gemspec"
+ # piece file back together and write
+ manifest = " s.files = %w[\n#{files}\n ]\n"
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
+ puts "Updated #{gemspec_file}"
+end
+
+task :validate do
+ libfiles = Dir['lib/*'] - ["lib/#{NAME}.rb", "lib/#{NAME}"]
+ unless libfiles.empty?
+ puts "Directory `lib` should only contain a `#{NAME}.rb` file and `#{NAME}` dir."
+ exit!
end
-end
+ unless Dir['VERSION*'].empty?
+ puts "A `VERSION` file at root level violates Gem best practices."
+ exit!
+ end
+end
View
110 god.gemspec
@@ -1,18 +1,39 @@
Gem::Specification.new do |s|
- s.name = %q{god}
- s.version = '0.9.0'
-
+ s.specification_version = 2 if s.respond_to? :specification_version=
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.authors = ["Tom Preston-Werner"]
- s.date = %q{2009-11-30}
- s.default_executable = %q{god}
- s.description = %q{God is an easy to configure, easy to extend monitoring framework written in Ruby.}
- s.email = %q{tom@mojombo.com}
+
+ s.name = 'god'
+ s.version = '0.10.1'
+ s.date = '2010-05-17'
+
+ s.summary = "Process monitoring framework."
+ s.description = "An easy to configure, easy to extend monitoring framework written in Ruby."
+
+ s.authors = ["Tom Preston-Werner", "Kevin Clark", "Eric Lindvall"]
+ s.email = 'god-rb@googlegroups.com'
+ s.homepage = 'http://god.rubyforge.org/'
+
+ s.rubyforge_project = 'god'
+ s.rubygems_version = '1.3.5'
+ s.require_paths = %w[lib ext]
+
s.executables = ["god"]
- s.extensions = ["ext/god/extconf.rb", "ext/god/extconf.rb"]
- s.extra_rdoc_files = [
- "README.txt"
- ]
+ s.default_executable = 'god'
+ s.extensions = %w[ext/god/extconf.rb]
+
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.extra_rdoc_files = %w[README.txt]
+
+ s.add_development_dependency('twitter', [">= 0.3.7"])
+ s.add_development_dependency('prowly', [">= 0.2.1"])
+ s.add_development_dependency('tinder', [">= 1.3.1", "< 2.0.0"])
+ s.add_development_dependency('xmpp4r', [">= 0.4.0"])
+ s.add_development_dependency('dike', [">= 0.0.3"])
+ s.add_development_dependency('snapshot', [">= 1.0.0", "< 2.0.0"])
+ s.add_development_dependency('rcov', [">= 0.9.8"])
+ s.add_development_dependency('daemons', [">= 1.0.10", "< 2.0.0"])
+ s.add_development_dependency('mocha', [">= 0.9.1"])
+
# = MANIFEST =
s.files = %w[
Announce.txt
@@ -20,9 +41,6 @@ Gem::Specification.new do |s|
README.txt
Rakefile
bin/god
- examples/events.god
- examples/gravatar.god
- examples/single.god
ext/god/.gitignore
ext/god/extconf.rb
ext/god/kqueue_handler.c
@@ -102,6 +120,8 @@ Gem::Specification.new do |s|
test/configs/matias/matias.god
test/configs/real.rb
test/configs/running_load/running_load.god
+ test/configs/stop_options/simple_server.rb
+ test/configs/stop_options/stop_options.god
test/configs/stress/simple_server.rb
test/configs/stress/stress.god
test/configs/task/logs/.placeholder
@@ -140,64 +160,6 @@ Gem::Specification.new do |s|
test/test_webhook.rb
]
# = MANIFEST =
- s.homepage = %q{http://god.rubyforge.org/}
- s.rdoc_options = ["--charset=UTF-8"]
- s.require_paths = ["lib", "ext"]
- s.rubyforge_project = %q{god}
- s.rubygems_version = %q{1.3.5}
- s.summary = %q{Like monit, only awesome}
- s.test_files = [
- "test/configs/child_events/simple_server.rb",
- "test/configs/child_polls/simple_server.rb",
- "test/configs/complex/simple_server.rb",
- "test/configs/contact/simple_server.rb",
- "test/configs/daemon_events/simple_server.rb",
- "test/configs/daemon_events/simple_server_stop.rb",
- "test/configs/daemon_polls/simple_server.rb",
- "test/configs/degrading_lambda/tcp_server.rb",
- "test/configs/real.rb",
- "test/configs/stress/simple_server.rb",
- "test/configs/test.rb",
- "test/helper.rb",
- "test/suite.rb",
- "test/test_behavior.rb",
- "test/test_campfire.rb",
- "test/test_condition.rb",
- "test/test_conditions_disk_usage.rb",
- "test/test_conditions_http_response_code.rb",
- "test/test_conditions_process_running.rb",
- "test/test_conditions_tries.rb",
- "test/test_contact.rb",
- "test/test_dependency_graph.rb",
- "test/test_driver.rb",
- "test/test_email.rb",
- "test/test_event_handler.rb",
- "test/test_god.rb",
- "test/test_handlers_kqueue_handler.rb",
- "test/test_jabber.rb",
- "test/test_logger.rb",
- "test/test_metric.rb",
- "test/test_process.rb",
- "test/test_registry.rb",
- "test/test_socket.rb",
- "test/test_sugar.rb",
- "test/test_system_portable_poller.rb",
- "test/test_system_process.rb",
- "test/test_task.rb",
- "test/test_timeline.rb",
- "test/test_trigger.rb",
- "test/test_watch.rb",
- "test/test_webhook.rb"
- ]
-
- if s.respond_to? :specification_version then
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
- s.specification_version = 3
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
- else
- end
- else
- end
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
end
-
View
4 lib/god.rb
@@ -151,13 +151,15 @@ def safe_attr_accessor(*args)
end
module God
- VERSION = '0.9.0'
+ VERSION = '0.10.1'
LOG_BUFFER_SIZE_DEFAULT = 100
PID_FILE_DIRECTORY_DEFAULTS = ['/var/run/god', '~/.god/pids']
DRB_PORT_DEFAULT = 17165
DRB_ALLOW_DEFAULT = ['127.0.0.1']
LOG_LEVEL_DEFAULT = :info
TERMINATE_TIMEOUT_DEFAULT = 10
+ STOP_TIMEOUT_DEFAULT = 10
+ STOP_SIGNAL_DEFAULT = 'TERM'
class << self
# user configurable
View
23 lib/god/process.rb
@@ -2,8 +2,9 @@ module God
class Process
WRITES_PID = [:start, :restart]
- attr_accessor :name, :uid, :gid, :log, :log_cmd, :err_log, :err_log_cmd, :start, :stop, :restart,
- :unix_socket, :chroot, :env, :dir
+ attr_accessor :name, :uid, :gid, :log, :log_cmd, :err_log, :err_log_cmd,
+ :start, :stop, :restart, :unix_socket, :chroot, :env, :dir,
+ :stop_timeout, :stop_signal
def initialize
self.log = '/dev/null'
@@ -14,6 +15,8 @@ def initialize
@pid = nil
@unix_socket = nil
@log_cmd = nil
+ @stop_timeout = God::STOP_TIMEOUT_DEFAULT
+ @stop_signal = God::STOP_SIGNAL_DEFAULT
end
def alive?
@@ -203,11 +206,11 @@ def call_action(action)
command = lambda do
applog(self, :info, "#{self.name} stop: default lambda killer")
- ::Process.kill('TERM', pid) rescue nil
- applog(self, :info, "#{self.name} sent SIGTERM")
+ ::Process.kill(@stop_signal, pid) rescue nil
+ applog(self, :info, "#{self.name} sent SIG#{@stop_signal}")
# Poll to see if it's dead
- 5.times do
+ @stop_timeout.times do
begin
::Process.kill(0, pid)
rescue Errno::ESRCH
@@ -220,14 +223,14 @@ def call_action(action)
end
::Process.kill('KILL', pid) rescue nil
- applog(self, :info, "#{self.name} still alive; sent SIGKILL")
+ applog(self, :warn, "#{self.name} still alive after #{@stop_timeout}s; sent SIGKILL")
end
end
if command.kind_of?(String)
pid = nil
- if @tracking_pid
+ if [:start, :restart].include?(action) && @tracking_pid
# double fork god-daemonized processes
# we don't want to wait for them to finish
r, w = IO.pipe
@@ -326,13 +329,15 @@ def spawn(command)
#
# Returns nothing
def ensure_stop
+ applog(self, :warn, "#{self.name} ensuring stop...")
+
unless self.pid
applog(self, :warn, "#{self.name} stop called but pid is uknown")
return
end
# Poll to see if it's dead
- 10.times do
+ @stop_timeout.times do
begin
::Process.kill(0, self.pid)
rescue Errno::ESRCH
@@ -345,7 +350,7 @@ def ensure_stop
# last resort
::Process.kill('KILL', self.pid) rescue nil
- applog(self, :warn, "#{self.name} process still running 10 seconds after stop command returned. Force killing.")
+ applog(self, :warn, "#{self.name} still alive after #{@stop_timeout}s; sent SIGKILL")
end
private
View
11 lib/god/watch.rb
@@ -12,10 +12,13 @@ class Watch < Task
extend Forwardable
def_delegators :@process, :name, :uid, :gid, :start, :stop, :restart, :dir,
- :name=, :uid=, :gid=, :start=, :stop=, :restart=, :dir=,
- :pid_file, :pid_file=, :log, :log=, :log_cmd, :log_cmd=,
- :err_log, :err_log=, :err_log_cmd, :err_log_cmd=, :alive?, :pid,
- :unix_socket, :unix_socket=, :chroot, :chroot=, :env, :env=, :signal
+ :name=, :uid=, :gid=, :start=, :stop=, :restart=,
+ :dir=, :pid_file, :pid_file=, :log, :log=,
+ :log_cmd, :log_cmd=, :err_log, :err_log=,
+ :err_log_cmd, :err_log_cmd=, :alive?, :pid,
+ :unix_socket, :unix_socket=, :chroot, :chroot=,
+ :env, :env=, :signal, :stop_timeout=,
+ :stop_signal=
#
def initialize
super
View
12 test/configs/stop_options/simple_server.rb
@@ -0,0 +1,12 @@
+#! /usr/bin/env ruby
+
+trap :USR1 do
+
+end
+
+loop do
+ STDOUT.puts('server');
+ STDOUT.flush;
+
+ sleep 10
+end
View
39 test/configs/stop_options/stop_options.god
@@ -0,0 +1,39 @@
+God.watch do |w|
+ w.name = 'stop-options'
+ w.start = File.join(GOD_ROOT, *%w[test configs stop_options simple_server.rb])
+ w.stop_signal = 'USR1'
+ w.stop_timeout = 5
+ w.interval = 5
+ w.grace = 2
+
+ w.start_if do |start|
+ start.condition(:process_running) do |c|
+ c.running = false
+ end
+ end
+
+ w.restart_if do |restart|
+ restart.condition(:cpu_usage) do |c|
+ c.above = 30.percent
+ c.times = [3, 5]
+ end
+
+ restart.condition(:memory_usage) do |c|
+ c.above = 10.megabytes
+ c.times = [3, 5]
+ end
+ end
+
+ # lifecycle
+ w.lifecycle do |on|
+ on.condition(:flapping) do |c|
+ c.to_state = [:start, :restart]
+ c.times = 3
+ c.within = 60.seconds
+ c.transition = :unmonitored
+ c.retry_in = 10.seconds
+ c.retry_times = 2
+ c.retry_within = 5.minutes
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.