god 0.13.4 → 0.13.5
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.
- 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
|