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.
- 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
|