god 0.13.4 → 0.13.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/History.txt +13 -0
- data/doc/god.asciidoc +50 -8
- data/ext/god/extconf.rb +1 -0
- data/ext/god/kqueue_handler.c +9 -1
- data/ext/god/netlink_handler.c +17 -0
- data/god.gemspec +12 -3
- data/lib/god.rb +3 -1
- data/lib/god/contacts/slack.rb +100 -0
- data/lib/god/contacts/statsd.rb +46 -0
- data/lib/god/contacts/webhook.rb +1 -0
- data/lib/god/process.rb +10 -5
- data/test/helper.rb +8 -3
- data/test/test_airbrake.rb +1 -1
- data/test/test_behavior.rb +2 -2
- data/test/test_campfire.rb +1 -1
- data/test/test_condition.rb +3 -3
- data/test/test_conditions_disk_usage.rb +1 -1
- data/test/test_conditions_http_response_code.rb +1 -1
- data/test/test_conditions_process_running.rb +1 -1
- data/test/test_conditions_socket_responding.rb +1 -1
- data/test/test_conditions_tries.rb +3 -3
- data/test/test_contact.rb +9 -9
- data/test/test_driver.rb +4 -3
- data/test/test_email.rb +1 -1
- data/test/test_event_handler.rb +2 -2
- data/test/test_god.rb +9 -7
- data/test/test_handlers_kqueue_handler.rb +1 -1
- data/test/test_hipchat.rb +1 -1
- data/test/test_jabber.rb +1 -1
- data/test/test_logger.rb +3 -3
- data/test/test_metric.rb +1 -1
- data/test/test_process.rb +7 -3
- data/test/test_prowl.rb +1 -1
- data/test/test_registry.rb +1 -1
- data/test/test_slack.rb +56 -0
- data/test/test_socket.rb +1 -1
- data/test/test_statsd.rb +22 -0
- data/test/test_sugar.rb +1 -1
- data/test/test_system_portable_poller.rb +1 -1
- data/test/test_system_process.rb +1 -1
- data/test/test_task.rb +4 -4
- data/test/test_timeline.rb +1 -1
- data/test/test_trigger.rb +5 -1
- data/test/test_watch.rb +1 -1
- data/test/test_webhook.rb +1 -1
- metadata +240 -223
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4e92e64f9fc2eaea16ace1b200c266186acbfe80
|
4
|
+
data.tar.gz: 3f1a94de8fa67f06e41b96e1176faf71e02ee7ab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97bc476662014ecdd34126fc2a1e1fa0352e477c5e7770eca6440b63770fed590d97f1e0e0326b00f8715b9b6db4ab7771b35cfe00583b6ea0f8aa86b9d8bc5c
|
7
|
+
data.tar.gz: 8f36cbb7934ee98a1b2c78af71740ed2a502ccd08479b0a01f15d233224873d7ff15cdf7874282713e99a4aa2b02e02bf70b4a630f4d5a3e0518179dfdf2c54f
|
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 0.13.5 / 2015-01-09
|
2
|
+
* Minor Enhancements
|
3
|
+
* statsd notifier (#144)
|
4
|
+
* Slack notifier (#172)
|
5
|
+
* Bug fixes
|
6
|
+
* Add support for Ruby 2.2.0 (#206)
|
7
|
+
* Fix tests for Ruby 2.0 (#205)
|
8
|
+
* Make group assignment more like login (#159)
|
9
|
+
* Flush file descriptors to prevent too many processes from being started (#141)
|
10
|
+
* Allow SSL URLs (#168)
|
11
|
+
* Documentation fixes
|
12
|
+
* Clarify Hipchat privilege requirements (#176)
|
13
|
+
|
1
14
|
== 0.13.4 / 2014-03-05
|
2
15
|
* Minor Enhancements
|
3
16
|
* Hipchat reporter (#162)
|
data/doc/god.asciidoc
CHANGED
@@ -436,8 +436,8 @@ A `watch` represents a single process that has concrete start, stop, and/or
|
|
436
436
|
restart operations. You can define as many watches as you like. In the example
|
437
437
|
above, I've got some Rails instances running in Mongrels that I need to keep
|
438
438
|
alive. Every watch must have a unique `name` so that it can be identified
|
439
|
-
later on. The `start` and `stop` attributes specify the commands to start
|
440
|
-
and stop the process. If no `restart` attribute is set, restart will be
|
439
|
+
later on. The `start` and `stop` attributes specify the commands to start
|
440
|
+
and stop the process. If no `restart` attribute is set, restart will be
|
441
441
|
represented by a call to stop followed by a call to start. The
|
442
442
|
optional `grace` attribute sets the amount of time following a
|
443
443
|
start/stop/restart command to wait before resuming normal monitoring
|
@@ -575,7 +575,7 @@ Watching Non-Daemon Processes
|
|
575
575
|
Need to watch a script that doesn't have built in daemonization? No problem!
|
576
576
|
God will daemonize and keep track of your process for you. If you don't
|
577
577
|
specify a `pid_file` attribute for a watch, it will be auto-daemonized and a
|
578
|
-
PID file will be stored for it in `/var/run/god`.
|
578
|
+
PID file will be stored for it in `/var/run/god`.
|
579
579
|
|
580
580
|
|
581
581
|
```ruby
|
@@ -585,9 +585,9 @@ God.pid_file_directory = '/home/tom/pids'
|
|
585
585
|
God.watch do |w|
|
586
586
|
w.name = 'mongrel'
|
587
587
|
w.pid_file = w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
|
588
|
-
|
588
|
+
|
589
589
|
w.start = "mongrel_rails start -P #{RAILS_ROOT}/log/mongrel.pid -d"
|
590
|
-
|
590
|
+
|
591
591
|
# ...
|
592
592
|
end
|
593
593
|
|
@@ -595,15 +595,15 @@ end
|
|
595
595
|
God.watch do |w|
|
596
596
|
w.name = 'worker'
|
597
597
|
# w.pid_file = is not set
|
598
|
-
|
598
|
+
|
599
599
|
w.start = "rake resque:worker"
|
600
|
-
|
600
|
+
|
601
601
|
# ...
|
602
602
|
end
|
603
603
|
```
|
604
604
|
|
605
605
|
|
606
|
-
If you'd rather have the PID file stored in a different location, you can
|
606
|
+
If you'd rather have the PID file stored in a different location, you can
|
607
607
|
set it at the top of your config:
|
608
608
|
|
609
609
|
```ruby
|
@@ -1022,6 +1022,8 @@ ssl - A Boolean determining whether or not to use SSL
|
|
1022
1022
|
from - The String representing who the message should be sent as.
|
1023
1023
|
```
|
1024
1024
|
|
1025
|
+
NOTE: in Hipchat you must have a token with 'admin' privileges. 'Notification' privileges will not be enough.
|
1026
|
+
|
1025
1027
|
Email
|
1026
1028
|
~~~~~
|
1027
1029
|
|
@@ -1243,6 +1245,46 @@ end
|
|
1243
1245
|
apikey - The String API key.
|
1244
1246
|
```
|
1245
1247
|
|
1248
|
+
Slack
|
1249
|
+
~~~~~
|
1250
|
+
|
1251
|
+
Send a message to a channel in Slack (https://slack.com/).
|
1252
|
+
|
1253
|
+
First, set up an Incoming Webhook in your Slack account.
|
1254
|
+
|
1255
|
+
Then, in your God configuration, set the defaults:
|
1256
|
+
|
1257
|
+
```ruby
|
1258
|
+
God::Contacts::Slack.defaults do |d|
|
1259
|
+
d.account = "foo"
|
1260
|
+
d.token = "abc123abc123abc123"
|
1261
|
+
c.notify_channel = true
|
1262
|
+
c.format = '%{host} alert: %{message}'
|
1263
|
+
end
|
1264
|
+
```
|
1265
|
+
|
1266
|
+
`account` is the name of your Slack account; if you view slack at
|
1267
|
+
"foo.slack.com", then your account is "foo". `token` is from your
|
1268
|
+
newly-created webhook, and will be a string of unintelligible
|
1269
|
+
characters.
|
1270
|
+
|
1271
|
+
The `notify_channel` and `format` settings are optional. The first
|
1272
|
+
controls whether the message includes `@channel` (sending notifications
|
1273
|
+
to everyone in the channel); the second controls how the message is
|
1274
|
+
formatted. Acceptable values within the format are `priority`, `host`,
|
1275
|
+
`message`, `category`, and `time`.
|
1276
|
+
|
1277
|
+
Once you've set the defaults, create contacts for the channels that you
|
1278
|
+
want to notify. You can create as many as you like, and they'll look
|
1279
|
+
something like this:
|
1280
|
+
|
1281
|
+
```ruby
|
1282
|
+
God.contact(:slack) do |c|
|
1283
|
+
c.name = '#ops'
|
1284
|
+
c.channel = '#ops'
|
1285
|
+
end
|
1286
|
+
```
|
1287
|
+
|
1246
1288
|
/////////////////////////////////////////////////////////////////////////////
|
1247
1289
|
/////////////////////////////////////////////////////////////////////////////
|
1248
1290
|
|
data/ext/god/extconf.rb
CHANGED
data/ext/god/kqueue_handler.c
CHANGED
@@ -5,6 +5,10 @@
|
|
5
5
|
#include <sys/time.h>
|
6
6
|
#include <errno.h>
|
7
7
|
|
8
|
+
#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
|
9
|
+
#include <ruby/io.h>
|
10
|
+
#endif
|
11
|
+
|
8
12
|
static VALUE mGod;
|
9
13
|
static VALUE cKQueueHandler;
|
10
14
|
static VALUE cEventHandler;
|
@@ -63,6 +67,10 @@ kqh_handle_events()
|
|
63
67
|
{
|
64
68
|
int nevents, i, num_to_fetch;
|
65
69
|
struct kevent *events;
|
70
|
+
|
71
|
+
#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
|
72
|
+
rb_wait_for_single_fd(kq, RB_WAITFD_IN, NULL);
|
73
|
+
#else
|
66
74
|
fd_set read_set;
|
67
75
|
|
68
76
|
FD_ZERO(&read_set);
|
@@ -70,7 +78,7 @@ kqh_handle_events()
|
|
70
78
|
|
71
79
|
// Don't actually run this method until we've got an event
|
72
80
|
rb_thread_select(kq + 1, &read_set, NULL, NULL, NULL);
|
73
|
-
|
81
|
+
#endif
|
74
82
|
// Grabbing num_events once for thread safety
|
75
83
|
num_to_fetch = num_events;
|
76
84
|
events = (struct kevent*)malloc(num_to_fetch * sizeof(struct kevent));
|
data/ext/god/netlink_handler.c
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
#ifdef __linux__ /* only build on linux */
|
2
2
|
|
3
3
|
#include <ruby.h>
|
4
|
+
|
5
|
+
#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
|
6
|
+
#include <ruby/io.h>
|
7
|
+
#endif
|
8
|
+
|
9
|
+
|
4
10
|
#include <sys/types.h>
|
5
11
|
#include <unistd.h>
|
6
12
|
#include <sys/socket.h>
|
@@ -31,6 +37,16 @@ nlh_handle_events()
|
|
31
37
|
|
32
38
|
VALUE extra_data;
|
33
39
|
|
40
|
+
#ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
|
41
|
+
int ret;
|
42
|
+
if((ret = rb_wait_for_single_fd(nl_sock, RB_WAITFD_IN, NULL)) < 0){
|
43
|
+
rb_raise(rb_eStandardError, "%s", strerror(errno));
|
44
|
+
}
|
45
|
+
/* If there were no events detected, return */
|
46
|
+
if(!(ret & RB_WAITFD_IN)){
|
47
|
+
return INT2FIX(0);
|
48
|
+
}
|
49
|
+
#else
|
34
50
|
fd_set fds;
|
35
51
|
|
36
52
|
FD_ZERO(&fds);
|
@@ -44,6 +60,7 @@ nlh_handle_events()
|
|
44
60
|
if (! FD_ISSET(nl_sock, &fds)) {
|
45
61
|
return INT2FIX(0);
|
46
62
|
}
|
63
|
+
#endif
|
47
64
|
|
48
65
|
/* if there are events, make calls */
|
49
66
|
if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) {
|
data/god.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'god'
|
6
|
-
s.version = '0.13.
|
7
|
-
s.date = '
|
6
|
+
s.version = '0.13.5'
|
7
|
+
s.date = '2015-01-09'
|
8
8
|
|
9
9
|
s.summary = "Process monitoring framework."
|
10
10
|
s.description = "An easy to configure, easy to extend monitoring framework written in Ruby."
|
@@ -25,18 +25,23 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.add_development_dependency('json', '~> 1.6')
|
27
27
|
s.add_development_dependency('rake')
|
28
|
+
s.add_development_dependency('minitest')
|
28
29
|
s.add_development_dependency('rdoc', '~> 3.10')
|
29
30
|
s.add_development_dependency('twitter', '~> 4.0')
|
30
31
|
s.add_development_dependency('prowly', '~> 0.3')
|
31
32
|
s.add_development_dependency('xmpp4r', '~> 0.5')
|
32
33
|
s.add_development_dependency('dike', '~> 0.0.3')
|
33
|
-
|
34
|
+
# s.add_development_dependency('rcov', '~> 0.9')
|
34
35
|
s.add_development_dependency('daemons', '~> 1.1')
|
35
36
|
s.add_development_dependency('mocha', '~> 0.10')
|
36
37
|
s.add_development_dependency('gollum', '~> 1.3.1')
|
38
|
+
#the last version to support 1.8.7 is 0.99.6
|
39
|
+
s.add_development_dependency('mustache', ['~> 0.99.0', '< 0.99.7'])
|
37
40
|
s.add_development_dependency('airbrake', '~> 3.1.7')
|
38
41
|
s.add_development_dependency('nokogiri', '~> 1.5.0')
|
39
42
|
s.add_development_dependency('activesupport', [ '>= 2.3.10', '< 4.0.0' ])
|
43
|
+
s.add_development_dependency('statsd-ruby')
|
44
|
+
s.add_development_dependency('i18n', '< 0.7.0')
|
40
45
|
# = MANIFEST =
|
41
46
|
s.files = %w[
|
42
47
|
Announce.txt
|
@@ -87,6 +92,8 @@ Gem::Specification.new do |s|
|
|
87
92
|
lib/god/contacts/jabber.rb
|
88
93
|
lib/god/contacts/prowl.rb
|
89
94
|
lib/god/contacts/scout.rb
|
95
|
+
lib/god/contacts/slack.rb
|
96
|
+
lib/god/contacts/statsd.rb
|
90
97
|
lib/god/contacts/twitter.rb
|
91
98
|
lib/god/contacts/webhook.rb
|
92
99
|
lib/god/driver.rb
|
@@ -162,7 +169,9 @@ Gem::Specification.new do |s|
|
|
162
169
|
test/test_process.rb
|
163
170
|
test/test_prowl.rb
|
164
171
|
test/test_registry.rb
|
172
|
+
test/test_slack.rb
|
165
173
|
test/test_socket.rb
|
174
|
+
test/test_statsd.rb
|
166
175
|
test/test_sugar.rb
|
167
176
|
test/test_system_portable_poller.rb
|
168
177
|
test/test_system_process.rb
|
data/lib/god.rb
CHANGED
@@ -90,9 +90,11 @@ load_contact(:email)
|
|
90
90
|
load_contact(:jabber)
|
91
91
|
load_contact(:prowl)
|
92
92
|
load_contact(:scout)
|
93
|
+
load_contact(:statsd)
|
93
94
|
load_contact(:twitter)
|
94
95
|
load_contact(:webhook)
|
95
96
|
load_contact(:airbrake)
|
97
|
+
load_contact(:slack)
|
96
98
|
|
97
99
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. ext god])
|
98
100
|
|
@@ -158,7 +160,7 @@ end
|
|
158
160
|
|
159
161
|
module God
|
160
162
|
# The String version number for this package.
|
161
|
-
VERSION = '0.13.
|
163
|
+
VERSION = '0.13.5'
|
162
164
|
|
163
165
|
# The Integer number of lines of backlog to keep for the logger.
|
164
166
|
LOG_BUFFER_SIZE_DEFAULT = 100
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Send a message to a Slack channel
|
2
|
+
#
|
3
|
+
# account - The name of your Slack account (visible in URL, e.g. foo.slack.com)
|
4
|
+
# token - The token of the webhook created in Slack
|
5
|
+
# channel - The name of the channel to send the message to, prefixed with #
|
6
|
+
# notify_channel - Whether to send an "@channel" in the message, to alert everyone in the channel
|
7
|
+
# format - An optional format string to change how the alert is displayed
|
8
|
+
|
9
|
+
require 'net/http'
|
10
|
+
require 'uri'
|
11
|
+
|
12
|
+
CONTACT_DEPS[:slack] = ['json']
|
13
|
+
CONTACT_DEPS[:slack].each do |d|
|
14
|
+
require d
|
15
|
+
end
|
16
|
+
|
17
|
+
module God
|
18
|
+
module Contacts
|
19
|
+
|
20
|
+
class Slack < Contact
|
21
|
+
class << self
|
22
|
+
attr_accessor :account, :token, :channel, :notify_channel, :format, :username, :emoji
|
23
|
+
end
|
24
|
+
|
25
|
+
self.channel = "#general"
|
26
|
+
self.notify_channel = false
|
27
|
+
self.format = "%{priority} alert on %{host}: %{message} (%{category}, %{time})"
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
valid = true
|
31
|
+
valid &= complain("Attribute 'account' must be specified", self) unless arg(:account)
|
32
|
+
valid &= complain("Attribute 'token' must be specified", self) unless arg(:token)
|
33
|
+
valid
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :account, :token, :channel, :notify_channel, :format, :username, :emoji
|
37
|
+
|
38
|
+
def text(data)
|
39
|
+
text = ""
|
40
|
+
text << "<!channel> " if arg(:notify_channel)
|
41
|
+
|
42
|
+
if RUBY_VERSION =~ /^1\.8/
|
43
|
+
text << arg(:format).gsub(/%\{(\w+)\}/) do |match|
|
44
|
+
data[$1.to_sym]
|
45
|
+
end
|
46
|
+
else
|
47
|
+
text << arg(:format) % data
|
48
|
+
end
|
49
|
+
|
50
|
+
text
|
51
|
+
end
|
52
|
+
|
53
|
+
def notify(message, time, priority, category, host)
|
54
|
+
text = text({
|
55
|
+
:message => message,
|
56
|
+
:time => time,
|
57
|
+
:priority => priority,
|
58
|
+
:category => category,
|
59
|
+
:host => host
|
60
|
+
})
|
61
|
+
|
62
|
+
request(text)
|
63
|
+
end
|
64
|
+
|
65
|
+
def api_url
|
66
|
+
URI.parse("https://#{arg(:account)}.slack.com/services/hooks/incoming-webhook?token=#{arg(:token)}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def request(text)
|
70
|
+
http = Net::HTTP.new(api_url.host, api_url.port)
|
71
|
+
http.use_ssl = true
|
72
|
+
|
73
|
+
req = Net::HTTP::Post.new(api_url.request_uri)
|
74
|
+
req.body = {
|
75
|
+
:link_names => 1,
|
76
|
+
:text => text,
|
77
|
+
:channel => arg(:channel)
|
78
|
+
}.tap { |payload|
|
79
|
+
payload[:username] = arg(:username) if arg(:username)
|
80
|
+
payload[:icon_emoji] = arg(:emoji) if arg(:emoji)
|
81
|
+
}.to_json
|
82
|
+
|
83
|
+
res = http.request(req)
|
84
|
+
|
85
|
+
case res
|
86
|
+
when Net::HTTPSuccess
|
87
|
+
self.info = "successfully notified slack on channel #{arg(:channel)}"
|
88
|
+
else
|
89
|
+
self.info = "failed to send webhook to #{arg(:url)}: #{res.error!}"
|
90
|
+
end
|
91
|
+
rescue Object => e
|
92
|
+
applog(nil, :info, "failed to send webhook to #{arg(:url)}: #{e.message}")
|
93
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Send a notice to statsd
|
2
|
+
#
|
3
|
+
# host - statsd host
|
4
|
+
# port - statsd port (optional)
|
5
|
+
|
6
|
+
require 'statsd-ruby'
|
7
|
+
|
8
|
+
module God
|
9
|
+
module Contacts
|
10
|
+
|
11
|
+
class Statsd < Contact
|
12
|
+
class << self
|
13
|
+
attr_accessor :host, :port
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_accessor :host, :port
|
17
|
+
|
18
|
+
def valid?
|
19
|
+
valid = true
|
20
|
+
valid &= complain("Attribute 'statsd_host' must be specified", self) unless arg(:host)
|
21
|
+
valid
|
22
|
+
end
|
23
|
+
|
24
|
+
def notify(message, time, priority, category, hostname)
|
25
|
+
statsd = ::Statsd.new host, (port ? port.to_i : 8125) # 8125 is the default statsd port
|
26
|
+
|
27
|
+
hostname.gsub! /\./, '_'
|
28
|
+
app = message.gsub /([^\s]*).*/, '\1'
|
29
|
+
|
30
|
+
[
|
31
|
+
'cpu out of bounds',
|
32
|
+
'memory out of bounds',
|
33
|
+
'process is flapping'
|
34
|
+
].each do |event_type|
|
35
|
+
statsd.increment "god.#{event_type.gsub(/\s/, '_')}.#{hostname}.#{app}" if message.include? event_type
|
36
|
+
end
|
37
|
+
|
38
|
+
self.info = 'sent statsd alert'
|
39
|
+
rescue => e
|
40
|
+
applog(nil, :info, "failed to send statsd alert: #{e.message}")
|
41
|
+
applog(nil, :debug, e.backtrace.join("\n"))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
data/lib/god/contacts/webhook.rb
CHANGED
data/lib/god/process.rb
CHANGED
@@ -32,16 +32,18 @@ module God
|
|
32
32
|
begin
|
33
33
|
uid_num = Etc.getpwnam(self.uid).uid if self.uid
|
34
34
|
gid_num = Etc.getgrnam(self.gid).gid if self.gid
|
35
|
+
gid_num = Etc.getpwnam(self.uid).gid if self.gid.nil? && self.uid
|
35
36
|
|
36
37
|
::Dir.chroot(self.chroot) if self.chroot
|
37
|
-
::Process.groups = [gid_num] if
|
38
|
-
::Process
|
38
|
+
::Process.groups = [gid_num] if gid_num
|
39
|
+
::Process.initgroups(self.uid, gid_num) if self.uid && gid_num
|
40
|
+
::Process::Sys.setgid(gid_num) if gid_num
|
39
41
|
::Process::Sys.setuid(uid_num) if self.uid
|
40
42
|
rescue ArgumentError, Errno::EPERM, Errno::ENOENT
|
41
43
|
exit(1)
|
42
44
|
end
|
43
45
|
|
44
|
-
File.writable?(file_in_chroot(file)) ? exit(0) : exit(1)
|
46
|
+
File.writable?(file_in_chroot(file)) ? exit!(0) : exit!(1)
|
45
47
|
end
|
46
48
|
|
47
49
|
wpid, status = ::Process.waitpid2(pid)
|
@@ -246,6 +248,7 @@ module God
|
|
246
248
|
r.close
|
247
249
|
pid = self.spawn(command)
|
248
250
|
puts pid.to_s # send pid back to forker
|
251
|
+
exit!(0)
|
249
252
|
end
|
250
253
|
|
251
254
|
::Process.waitpid(opid, 0)
|
@@ -295,11 +298,13 @@ module God
|
|
295
298
|
File.umask self.umask if self.umask
|
296
299
|
uid_num = Etc.getpwnam(self.uid).uid if self.uid
|
297
300
|
gid_num = Etc.getgrnam(self.gid).gid if self.gid
|
301
|
+
gid_num = Etc.getpwnam(self.uid).gid if self.gid.nil? && self.uid
|
298
302
|
|
299
303
|
::Dir.chroot(self.chroot) if self.chroot
|
300
304
|
::Process.setsid
|
301
|
-
::Process.groups = [gid_num] if
|
302
|
-
::Process
|
305
|
+
::Process.groups = [gid_num] if gid_num
|
306
|
+
::Process.initgroups(self.uid, gid_num) if self.uid && gid_num
|
307
|
+
::Process::Sys.setgid(gid_num) if gid_num
|
303
308
|
::Process::Sys.setuid(uid_num) if self.uid
|
304
309
|
self.dir ||= '/'
|
305
310
|
Dir.chdir self.dir
|