god 0.7.13 → 0.7.14
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/Announce.txt +135 -0
- data/History.txt +15 -0
- data/Rakefile +44 -11
- data/VERSION.yml +4 -0
- data/ext/god/.gitignore +5 -0
- data/ext/god/netlink_handler.c +1 -0
- data/god.gemspec +223 -0
- data/ideas/execve/execve.c +29 -0
- data/ideas/execve/extconf.rb +11 -0
- data/ideas/execve/go.rb +8 -0
- data/ideas/future.god +82 -0
- data/init/lsb_compliant_god +109 -0
- data/lib/god.rb +6 -3
- data/lib/god/cli/command.rb +2 -1
- data/lib/god/cli/version.rb +2 -2
- data/lib/god/contacts/campfire.rb +3 -2
- data/lib/god/contacts/jabber.rb +82 -20
- data/lib/god/logger.rb +5 -1
- data/lib/god/process.rb +0 -6
- data/site/images/banner.jpg +0 -0
- data/site/images/bg.gif +0 -0
- data/site/images/bg_grey.gif +0 -0
- data/site/images/bullet.jpg +0 -0
- data/site/images/corner_green.gif +0 -0
- data/site/images/corner_green.psd +0 -0
- data/site/images/corner_pink.gif +0 -0
- data/site/images/god_logo1.gif +0 -0
- data/site/images/header_bg.gif +0 -0
- data/site/images/header_bg.jpg +0 -0
- data/site/images/red_dot.gif +0 -0
- data/site/images/top_bg.gif +0 -0
- data/site/index.html +563 -0
- data/site/install.html +2 -0
- data/site/javascripts/code_highlighter.js +188 -0
- data/site/javascripts/ruby.js +18 -0
- data/site/stylesheets/layout.css +174 -0
- data/test/configs/lifecycle/lifecycle.god +25 -0
- data/test/test_god.rb +2 -2
- data/test/test_jabber.rb +36 -0
- data/test/test_logger.rb +4 -1
- metadata +56 -22
- data/Manifest.txt +0 -114
@@ -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
|
+
}
|
data/ideas/execve/go.rb
ADDED
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
|
|
data/lib/god/cli/command.rb
CHANGED
@@ -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
|
125
|
+
sleep 0.25
|
125
126
|
end
|
126
127
|
rescue God::NoSuchWatchError
|
127
128
|
puts "No such watch"
|
data/lib/god/cli/version.rb
CHANGED
@@ -6,12 +6,12 @@ module God
|
|
6
6
|
require 'god'
|
7
7
|
|
8
8
|
# print version
|
9
|
-
puts "Version #{God
|
9
|
+
puts "Version #{God.version}"
|
10
10
|
exit
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.version_extended
|
14
|
-
puts "Version: #{God
|
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
|
data/lib/god/contacts/jabber.rb
CHANGED
@@ -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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|