god 0.7.13 → 0.7.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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