GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Fork of mojombo/god
Description: Ruby process monitor
Homepage: http://god.rubyforge.org
Clone URL: git://github.com/auser/god.git
add host to notifications; check dir permissions on startup
mojombo (author)
Wed Oct 03 17:40:11 -0700 2007
commit  1b46be3d747b64dbe4e74adad9d39c9e38c99229
tree    079b862c40dd0feaee315cd68b933b5a8c48ae71
parent  16c54f66117b6365c0d5c3aad9f1803bf7ef7089
...
216
217
218
219
220
221
222
 
 
 
 
 
 
 
 
223
224
225
...
256
257
258
259
260
261
262
 
 
 
 
 
 
 
 
263
264
265
...
287
288
289
 
290
291
292
...
216
217
218
 
 
 
 
219
220
221
222
223
224
225
226
227
228
229
...
260
261
262
 
 
 
 
263
264
265
266
267
268
269
270
271
272
273
...
295
296
297
298
299
300
301
0
@@ -216,10 +216,14 @@ begin
0
         
0
         begin
0
           load File.expand_path(options[:config])
0
- rescue => e
0
- puts e.message
0
- puts e.backtrace.join("\n")
0
- abort "There was an error in your configuration file (see above)"
0
+ rescue Exception => e
0
+ if e.instance_of?(SystemExit)
0
+ raise
0
+ else
0
+ puts e.message
0
+ puts e.backtrace.join("\n")
0
+ abort "There was an error in your configuration file (see above)"
0
+ end
0
         end
0
       end
0
     else
0
@@ -256,10 +260,14 @@ begin
0
             
0
             begin
0
               load File.expand_path(options[:config])
0
- rescue => e
0
- puts e.message
0
- puts e.backtrace.join("\n")
0
- abort "There was an error in your configuration file (see above)"
0
+ rescue Exception => e
0
+ if e.instance_of?(SystemExit)
0
+ raise
0
+ else
0
+ puts e.message
0
+ puts e.backtrace.join("\n")
0
+ abort "There was an error in your configuration file (see above)"
0
+ end
0
             end
0
           end
0
           
0
@@ -287,6 +295,7 @@ rescue Exception => e
0
   if e.instance_of?(SystemExit)
0
     raise
0
   else
0
+ puts 'Uncaught exception'
0
     puts e.message
0
     puts e.backtrace.join("\n")
0
   end
...
90
91
92
93
 
 
94
95
96
...
90
91
92
 
93
94
95
96
97
0
@@ -90,7 +90,8 @@ module God
0
     # +time+ is the Time at which the notification was made
0
     # +priority+ is the arbitrary priority String
0
     # +category+ is the arbitrary category String
0
- def notify(message, time, priority, category)
0
+ # +host+ is the hostname of the server
0
+ def notify(message, time, priority, category, host)
0
       raise AbstractMethodNotOverriddenError.new("Contact#notify must be overridden in subclasses")
0
     end
0
     
...
20
21
22
23
 
24
25
26
...
29
30
31
 
32
33
34
...
42
43
44
45
 
46
47
 
48
49
50
...
20
21
22
 
23
24
25
26
...
29
30
31
32
33
34
35
...
43
44
45
 
46
47
 
48
49
50
51
0
@@ -20,7 +20,7 @@ module God
0
                             # :password
0
                             # :authentication
0
       
0
- self.format = lambda do |name, email, message, time, priority, category|
0
+ self.format = lambda do |name, email, message, time, priority, category, host|
0
         <<-EOF
0
 From: god <#{self.message_settings[:from]}>
0
 To: #{name} <#{email}>
0
@@ -29,6 +29,7 @@ Date: #{Time.now.httpdate}
0
 Message-Id: <unique.message.id.string@example.com>
0
 
0
 Message: #{message}
0
+Host: #{host}
0
 Priority: #{priority}
0
 Category: #{category}
0
         EOF
0
@@ -42,9 +43,9 @@ Category: #{category}
0
         valid
0
       end
0
       
0
- def notify(message, time, priority, category)
0
+ def notify(message, time, priority, category, host)
0
         begin
0
- body = Email.format.call(self.name, self.email, message, time, priority, category)
0
+ body = Email.format.call(self.name, self.email, message, time, priority, category, host)
0
           
0
           args = [Email.server_settings[:address], Email.server_settings[:port]]
0
           if Email.server_settings[:authentication]
...
215
216
217
218
 
 
219
220
221
...
215
216
217
 
218
219
220
221
222
0
@@ -215,7 +215,8 @@ module God
0
       
0
       # notify each contact
0
       resolved_contacts.each do |c|
0
- c.notify(message, Time.now, spec[:priority], spec[:category])
0
+ host = `hostname`.chomp rescue 'none'
0
+ c.notify(message, Time.now, spec[:priority], spec[:category], host)
0
       
0
         msg = "#{condition.watch.name} #{c.info ? c.info : "notification sent for contact: #{c.name}"} (#{c.base_name})"
0
       
...
31
32
33
 
34
35
36
...
31
32
33
34
35
36
37
0
@@ -31,6 +31,7 @@ module God
0
       # push onto capture and timeline for the given watch
0
       buf = StringIO.new
0
       templog = ::Logger.new(buf)
0
+ templog.level = Logger::INFO
0
       templog.send(level, text)
0
       @mutex.synchronize do
0
         @capture.puts(buf.string) if @capture
...
22
23
24
 
 
 
 
 
 
 
 
 
 
 
 
25
26
27
...
61
62
63
64
 
65
66
67
68
 
 
 
 
 
 
69
70
71
72
73
74
 
 
 
 
 
 
75
76
77
...
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
...
73
74
75
 
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
0
@@ -22,6 +22,18 @@ module God
0
       end
0
     end
0
     
0
+ def file_writable?(file)
0
+ pid = fork do
0
+ ::Process::Sys.setgid(Etc.getgrnam(self.gid).gid) if self.gid
0
+ ::Process::Sys.setuid(Etc.getpwnam(self.uid).uid) if self.uid
0
+
0
+ File.writable?(file) ? exit(0) : exit(1)
0
+ end
0
+
0
+ wpid, status = ::Process.waitpid2(pid)
0
+ status.exitstatus == 0 ? true : false
0
+ end
0
+
0
     def valid?
0
       # determine if we're tracking pid or not
0
       self.pid_file
0
@@ -61,17 +73,29 @@ module God
0
       end
0
       
0
       # pid dir must exist if specified
0
- if self.pid_file && !File.exist?(File.dirname(self.pid_file))
0
+ if !@tracking_pid && !File.exist?(File.dirname(self.pid_file))
0
         valid = false
0
         LOG.log(self, :error, "PID file directory '#{File.dirname(self.pid_file)}' does not exist")
0
       end
0
       
0
+ # pid dir must be writable if specified
0
+ if !@tracking_pid && !file_writable?(File.dirname(self.pid_file))
0
+ valid = false
0
+ LOG.log(self, :error, "PID file directory '#{File.dirname(self.pid_file)}' is not writable by #{self.uid || Etc.getlogin}")
0
+ end
0
+
0
       # log dir must exist if specified
0
       if self.log && !File.exist?(File.dirname(self.log))
0
         valid = false
0
         LOG.log(self, :error, "Log directory '#{File.dirname(self.log)}' does not exist")
0
       end
0
       
0
+ # log dir must be writable if specified
0
+ if self.log && !file_writable?(File.dirname(self.log))
0
+ valid = false
0
+ LOG.log(self, :error, "Log directory '#{File.dirname(self.log)}' is not writable by #{self.uid || Etc.getlogin}")
0
+ end
0
+
0
       valid
0
     end
0
     
...
28
29
30
 
 
 
31
32
33
...
28
29
30
31
32
33
34
35
36
0
@@ -28,6 +28,9 @@ God.watch do |w|
0
   w.name = "contact"
0
   w.interval = 5.seconds
0
   w.start = "ruby " + File.join(File.dirname(__FILE__), *%w[simple_server.rb])
0
+ w.uid = 'tom'
0
+ w.gid = 'tom'
0
+ w.log = "/Users/tom/contact.log"
0
   
0
   # determine the state on startup
0
   w.transition(:init, { true => :up, false => :start }) do |on|
...
103
104
105
106
 
107
108
109
110
...
103
104
105
 
106
107
108
109
110
0
@@ -103,7 +103,7 @@ class TestContact < Test::Unit::TestCase
0
   
0
   def test_notify_should_be_abstract
0
     assert_raise(AbstractMethodNotOverriddenError) do
0
- Contact.new.notify(:a, :b, :c, :d)
0
+ Contact.new.notify(:a, :b, :c, :d, :e)
0
     end
0
   end
0
 end
0
\ No newline at end of file
...
2
3
4
5
6
7
 
 
 
8
9
10
...
19
20
21
 
 
 
22
23
24
...
39
40
41
42
 
43
44
45
...
47
48
49
50
 
51
52
53
54
 
 
 
55
56
57
58
59
60
 
61
62
63
...
65
66
67
68
 
69
70
71
72
 
 
 
73
74
75
...
2
3
4
 
 
 
5
6
7
8
9
10
...
19
20
21
22
23
24
25
26
27
...
42
43
44
 
45
46
47
48
...
50
51
52
 
53
54
55
56
 
57
58
59
60
61
62
63
64
 
65
66
67
68
...
70
71
72
 
73
74
75
76
 
77
78
79
80
81
82
0
@@ -2,9 +2,9 @@ require File.dirname(__FILE__) + '/helper'
0
 
0
 module God
0
   class Process
0
- def fork
0
- raise "You forgot to stub fork"
0
- end
0
+ # def fork
0
+ # raise "You forgot to stub fork"
0
+ # end
0
     
0
     def exec(*args)
0
       raise "You forgot to stub exec"
0
@@ -19,6 +19,9 @@ class TestProcessChild < Test::Unit::TestCase
0
     @p.name = 'foo'
0
     @p.stubs(:test).returns true # so we don't try to mkdir_p
0
     Process.stubs(:detach) # because we stub fork
0
+
0
+ ::Process::Sys.stubs(:setuid).returns(true)
0
+ ::Process::Sys.stubs(:setgid).returns(true)
0
   end
0
   
0
   # valid?
0
@@ -39,7 +42,7 @@ class TestProcessChild < Test::Unit::TestCase
0
   
0
   def test_valid_should_return_true_if_uid_exists
0
     @p.start = 'qux'
0
- @p.log = 'bar'
0
+ @p.log = '/tmp/foo.log'
0
     @p.uid = 'root'
0
     
0
     assert @p.valid?
0
@@ -47,17 +50,19 @@ class TestProcessChild < Test::Unit::TestCase
0
   
0
   def test_valid_should_return_true_if_uid_does_not_exists
0
     @p.start = 'qux'
0
- @p.log = 'bar'
0
+ @p.log = '/tmp/foo.log'
0
     @p.uid = 'foobarbaz'
0
     
0
     no_stdout do
0
- assert !@p.valid?
0
+ no_stderr do
0
+ assert !@p.valid?
0
+ end
0
     end
0
   end
0
   
0
   def test_valid_should_return_true_if_gid_exists
0
     @p.start = 'qux'
0
- @p.log = 'bar'
0
+ @p.log = '/tmp/foo.log'
0
     @p.gid = 'wheel'
0
     
0
     assert @p.valid?
0
@@ -65,11 +70,13 @@ class TestProcessChild < Test::Unit::TestCase
0
   
0
   def test_valid_should_return_true_if_gid_does_not_exists
0
     @p.start = 'qux'
0
- @p.log = 'bar'
0
+ @p.log = '/tmp/foo.log'
0
     @p.gid = 'foobarbaz'
0
     
0
     no_stdout do
0
- assert !@p.valid?
0
+ no_stderr do
0
+ assert !@p.valid?
0
+ end
0
     end
0
   end
0
   

Comments

    No one has commented yet.