god 0.7.13 → 0.7.14

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.
@@ -0,0 +1,29 @@
1
+ #include "ruby.h"
2
+
3
+ static VALUE mKernel;
4
+ void Init_execve();
5
+ VALUE method_execve(VALUE self, VALUE cmd, VALUE env);
6
+
7
+ void Init_execve() {
8
+ mKernel = rb_const_get(rb_cObject, rb_intern("Kernel"));
9
+ rb_define_method(mKernel, "execve", method_execve, 2);
10
+ }
11
+
12
+ VALUE method_execve(VALUE self, VALUE r_cmd, VALUE r_env) {
13
+ char *shell = (char *)dln_find_exe("sh", 0);
14
+ char *arg[] = { "sh", "-c", StringValuePtr(r_cmd), (char *)0 };
15
+
16
+ struct RArray *env_array;
17
+ env_array = RARRAY(r_env);
18
+ char *env[env_array->len + 1];
19
+
20
+ int i;
21
+ for(i = 0; i < env_array->len; i++) {
22
+ env[i] = StringValuePtr(env_array->ptr[i]);
23
+ }
24
+
25
+ env[env_array->len] = (char *)0;
26
+
27
+ execve(shell, arg, env);
28
+ return Qnil;
29
+ }
@@ -0,0 +1,11 @@
1
+ # Loads mkmf which is used to make makefiles for Ruby extensions
2
+ require 'mkmf'
3
+
4
+ # Give it a name
5
+ extension_name = 'execve'
6
+
7
+ # The destination
8
+ dir_config(extension_name)
9
+
10
+ # Do the work
11
+ create_makefile(extension_name)
@@ -0,0 +1,8 @@
1
+ require 'execve'
2
+
3
+ my_env = ENV.to_hash.merge('HOME' => '/foo')
4
+ # my_env = ENV.to_hash
5
+
6
+ env = my_env.keys.inject([]) { |acc, k| acc << "#{k}=#{my_env[k]}"; acc }
7
+
8
+ execve(%Q{ruby -e "puts ENV['HOME']"}, env)
data/ideas/future.god ADDED
@@ -0,0 +1,82 @@
1
+ # This example shows how you might keep a local development Rails server up
2
+ # and running on your Mac.
3
+
4
+ # Run with:
5
+ # god -c /path/to/events.god
6
+
7
+ RAILS_ROOT = "/Users/tom/dev/helloworld"
8
+
9
+ God::Contacts::Email.delivery_method = :smtp
10
+ God::Contacts::Email.server_settings = {}
11
+
12
+ God.contact(:email) do |c|
13
+ c.name = 'tom'
14
+ c.email = 'tom@powerset.com'
15
+ c.group = 'developers'
16
+ c.throttle = 30.minutes
17
+ end
18
+
19
+ God.watch do |w|
20
+ w.name = "local-3000"
21
+ w.interval = 5.seconds
22
+ w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -d"
23
+ w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
24
+ w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
25
+
26
+ # clean pid files before start if necessary
27
+ w.behavior(:clean_pid_file)
28
+
29
+ # determine the state on startup
30
+ w.transition(:init, { true => :up, false => :start }) do |on|
31
+ on.condition(:process_running) do |c|
32
+ c.running = true
33
+ end
34
+ end
35
+
36
+ # determine when process has finished starting
37
+ w.transition([:start, :restart], :up) do |on|
38
+ on.condition(:process_running) do |c|
39
+ c.running = true
40
+ end
41
+ end
42
+
43
+ # start if process is not running
44
+ w.transition(:up, :start) do |on|
45
+ on.condition(:process_exits)
46
+ end
47
+
48
+ # restart if memory or cpu is too high
49
+ w.transition(:up, :restart) do |on|
50
+ on.condition(:memory_usage) do |c|
51
+ c.interval = 20
52
+ c.above = 50.megabytes
53
+ c.times = [3, 5]
54
+ end
55
+
56
+ on.condition(:cpu_usage) do |c|
57
+ c.interval = 10
58
+ c.above = 10.percent
59
+ c.times = [3, 5]
60
+ end
61
+ end
62
+
63
+ # lifecycle
64
+ w.lifecycle do |on|
65
+ on.condition(:flapping) do |c|
66
+ c.to_state = [:start, :restart]
67
+ c.times = 5
68
+ c.within = 30.seconds
69
+ c.transition = nil
70
+ c.retry = 60.seconds
71
+ c.giveup_tries = 5
72
+ c.notify = 'tom'
73
+ end
74
+
75
+ on.condition(:memory_usage) do |c|
76
+ c.interval = 20
77
+ c.above = 40.megabytes
78
+ c.times = [3, 5]
79
+ c.notify = 'tom'
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # see http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
4
+
5
+ PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
6
+ DESC="god daemon"
7
+ NAME="god"
8
+ DAEMON="/usr/bin/#{NAME}"
9
+ CONFIGFILE="/etc/god/god.conf"
10
+ PIDFILE="/var/run/#{NAME}.pid"
11
+ SCRIPTNAME="/etc/init.d/#{NAME}"
12
+ START_FLAGS="--no-syslog -P #{PIDFILE}"
13
+
14
+ ENV["PATH"] = PATH
15
+
16
+ def read_pid
17
+ begin
18
+ @pid = File.read(PIDFILE).to_i
19
+ @pid = nil if @pid == 0
20
+ rescue
21
+ @pid = nil
22
+ end
23
+ end
24
+
25
+ def kill(code)
26
+ Process.kill(code, @pid)
27
+ true
28
+ rescue
29
+ false
30
+ end
31
+
32
+ def running?
33
+ @pid && kill(0)
34
+ end
35
+
36
+ def dead?
37
+ @pid && !kill(0)
38
+ end
39
+
40
+ def start
41
+ if running?
42
+ puts "already running (#{@pid})"
43
+ exit
44
+ end
45
+
46
+ if dead?
47
+ clean_pid
48
+ end
49
+
50
+ puts "starting #{NAME}"
51
+ system("#{DAEMON} -c #{CONFIGFILE} #{START_FLAGS}")
52
+ end
53
+
54
+ def stop
55
+ if not running?
56
+ puts "not running"
57
+ exit
58
+ end
59
+
60
+ system("god quit")
61
+ end
62
+
63
+ def restart
64
+ if running?
65
+ stop
66
+ read_pid
67
+ end
68
+ start
69
+ end
70
+
71
+ def force_reload
72
+ if running?
73
+ restart
74
+ end
75
+ end
76
+
77
+ def clean_pid
78
+ File.delete(PIDFILE)
79
+ end
80
+
81
+ read_pid
82
+ case ARGV[0]
83
+ when 'start'
84
+ start
85
+ when 'stop'
86
+ stop
87
+ when 'restart'
88
+ if not running?
89
+ start
90
+ else
91
+ restart
92
+ end
93
+ when 'force-reload'
94
+ force_reload
95
+ when 'status'
96
+ if running?
97
+ puts "running (#{@pid})"
98
+ elsif dead?
99
+ puts "dead (#{@pid})"
100
+ exit!(1)
101
+ else
102
+ puts "not running"
103
+ exit!(3)
104
+ end
105
+ else
106
+ puts "Usage: #{SCRIPTNAME} start|stop|restart|force-reload|status"
107
+ end
108
+
109
+ exit
data/lib/god.rb CHANGED
@@ -148,8 +148,6 @@ class Module
148
148
  end
149
149
 
150
150
  module God
151
- VERSION = '0.7.13'
152
-
153
151
  LOG_BUFFER_SIZE_DEFAULT = 100
154
152
  PID_FILE_DIRECTORY_DEFAULTS = ['/var/run/god', '~/.god/pids']
155
153
  DRB_PORT_DEFAULT = 17165
@@ -626,6 +624,11 @@ module God
626
624
  self.main.join
627
625
  end
628
626
 
627
+ def self.version
628
+ yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
629
+ "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
630
+ end
631
+
629
632
  # To be called on program exit to start god
630
633
  #
631
634
  # Returns nothing
@@ -654,7 +657,7 @@ module God
654
657
 
655
658
  list.select do |item|
656
659
  item =~ Regexp.new(regex)
657
- end
660
+ end.sort_by { |x| x.size }
658
661
  end
659
662
  end
660
663
 
@@ -117,11 +117,12 @@ module God
117
117
  exit!
118
118
  end
119
119
 
120
+ puts "Please wait..."
120
121
  t = Time.at(0)
121
122
  loop do
122
123
  print @server.running_log(name, t)
123
124
  t = Time.now
124
- sleep 1
125
+ sleep 0.25
125
126
  end
126
127
  rescue God::NoSuchWatchError
127
128
  puts "No such watch"
@@ -6,12 +6,12 @@ module God
6
6
  require 'god'
7
7
 
8
8
  # print version
9
- puts "Version #{God::VERSION}"
9
+ puts "Version #{God.version}"
10
10
  exit
11
11
  end
12
12
 
13
13
  def self.version_extended
14
- puts "Version: #{God::VERSION}"
14
+ puts "Version: #{God.version}"
15
15
  puts "Polls: enabled"
16
16
  puts "Events: " + God::EventHandler.event_system
17
17
 
@@ -39,7 +39,8 @@ module God
39
39
  self.server_settings = {:subdomain => '',
40
40
  :user_name => '',
41
41
  :password => '',
42
- :room => ''}
42
+ :room => '',
43
+ :ssl => false}
43
44
 
44
45
  self.format = lambda do |message, host|
45
46
  <<-EOF
@@ -70,7 +71,7 @@ module God
70
71
  unless @room
71
72
  applog(nil,:debug, "initializing campfire connection using credentials: #{Campfire.server_settings.inspect}")
72
73
 
73
- campfire = Tinder::Campfire.new Campfire.server_settings[:subdomain]
74
+ campfire = Tinder::Campfire.new Campfire.server_settings[:subdomain], :ssl => Campfire.server_settings[:ssl]
74
75
  campfire.login Campfire.server_settings[:user_name], Campfire.server_settings[:password]
75
76
  @room = campfire.find_room_by_name(Campfire.server_settings[:room])
76
77
  end
@@ -19,7 +19,7 @@ module God
19
19
  module Contacts
20
20
  class Jabber < Contact
21
21
  class << self
22
- attr_accessor :settings, :format
22
+ attr_accessor :settings, :format, :client
23
23
  end
24
24
 
25
25
  self.format = lambda do |message, priority, category, host|
@@ -37,29 +37,91 @@ module God
37
37
  end
38
38
 
39
39
  def notify(message, time, priority, category, host)
40
+ connect
41
+
42
+ body = Jabber.format.call message, priority, category, host
43
+
44
+ message = XMPP4R::Message::new self.jabber_id, body
45
+ message.set_type :normal
46
+ message.set_id '1'
47
+ message.set_subject 'God'
48
+
49
+ self.send!(message)
50
+
51
+ self.info = "sent jabber message to #{self.jabber_id}"
52
+ rescue => e
53
+ puts e.message
54
+ puts e.backtrace.join("\n")
55
+
56
+ self.info = "failed to send jabber message to #{self.jabber_id}: #{e.message}"
57
+ end
58
+
59
+ def send!(msg)
60
+ attempts = 0
40
61
  begin
41
- jabber_id = XMPP4R::JID::new "#{Jabber.settings[:jabber_id]}/God"
42
- jabber_client = XMPP4R::Client::new jabber_id
43
- jabber_client.connect
44
- jabber_client.auth Jabber.settings[:password]
45
-
46
- body = Jabber.format.call message, priority, category, host
47
-
48
- message = XMPP4R::Message::new self.jabber_id, body
49
- message.set_type :normal
50
- message.set_id '1'
51
- message.set_subject 'God'
52
- jabber_client.send message
62
+ attempts += 1
63
+ client.send(msg)
64
+ rescue Errno::EPIPE, IOError => e
65
+ sleep 1
66
+ disconnect!
67
+ reconnect!
68
+ retry unless attempts > 3
69
+ raise e
70
+ rescue Errno::ECONNRESET => e
71
+ sleep (attempts^2) * 60 + 60
72
+ disconnect!
73
+ reconnect!
74
+ retry unless attempts > 3
75
+ raise e
76
+ end
77
+ end
78
+
79
+ def connect
80
+ connect! unless connected?
81
+ end
82
+
83
+ def connected?
84
+ connected = client.respond_to?(:is_connected?) && client.is_connected?
85
+ return connected
86
+ end
87
+
88
+ def connect!
89
+ disconnect! if connected?
53
90
 
54
- self.info = "sent jabber message to #{self.jabber_id}"
55
- rescue => e
56
- puts e.message
57
- puts e.backtrace.join("\n")
58
-
59
- self.info = "failed to send jabber message to #{self.jabber_id}: #{e.message}"
91
+ @connect_mutex ||= Mutex.new
92
+ # don't try to connect if another thread is already connecting.
93
+ return if @connect_mutex.locked?
94
+ @connect_mutex.lock
95
+
96
+ jabber_id = XMPP4R::JID::new "#{Jabber.settings[:jabber_id]}/God"
97
+ jabber_client = XMPP4R::Client::new jabber_id
98
+ jabber_client.connect Jabber.settings[:host]
99
+ jabber_client.auth Jabber.settings[:password]
100
+ self.client = jabber_client
101
+
102
+ @connect_mutex.unlock
103
+ end
104
+
105
+ def disconnect!
106
+ if client.respond_to?(:is_connected?) && client.is_connected?
107
+ begin
108
+ client.close
109
+ rescue Errno::EPIPE, IOError => e
110
+ self.info "Failed to disconnect: #{e}"
111
+ nil
112
+ end
60
113
  end
114
+ client = nil
115
+ end
116
+
117
+ def client
118
+ Jabber.client
119
+ end
120
+
121
+ def client=(jc)
122
+ Jabber.client = jc
61
123
  end
124
+
62
125
  end
63
-
64
126
  end
65
127
  end