eye 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +1 -0
- data/CHANGES.md +19 -0
- data/Gemfile +1 -0
- data/README.md +10 -8
- data/bin/eye +30 -45
- data/examples/notify.eye +3 -2
- data/examples/puma.eye +2 -2
- data/examples/rbenv.eye +2 -2
- data/examples/sidekiq.eye +2 -2
- data/examples/thin-farm.eye +1 -0
- data/examples/unicorn.eye +1 -1
- data/eye.gemspec +1 -1
- data/lib/eye.rb +1 -1
- data/lib/eye/application.rb +1 -1
- data/lib/eye/checker.rb +10 -0
- data/lib/eye/controller/commands.rb +0 -5
- data/lib/eye/controller/helpers.rb +15 -1
- data/lib/eye/controller/load.rb +3 -0
- data/lib/eye/controller/send_command.rb +44 -14
- data/lib/eye/controller/status.rb +3 -8
- data/lib/eye/dsl/application_opts.rb +6 -2
- data/lib/eye/dsl/group_opts.rb +7 -6
- data/lib/eye/dsl/main.rb +1 -1
- data/lib/eye/dsl/opts.rb +22 -15
- data/lib/eye/dsl/process_opts.rb +3 -6
- data/lib/eye/dsl/pure_opts.rb +12 -1
- data/lib/eye/group.rb +1 -1
- data/lib/eye/logger.rb +4 -4
- data/lib/eye/process/scheduler.rb +4 -0
- data/lib/eye/process/validate.rb +9 -1
- data/lib/eye/process/watchers.rb +3 -3
- data/lib/eye/settings.rb +17 -5
- data/lib/eye/system.rb +9 -0
- data/lib/eye/utils/alive_array.rb +23 -1
- metadata +16 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f91b36c9b73d802f079d62a345bbf29fcb929768
|
4
|
+
data.tar.gz: 2953436d9e587ff52b0a2ee146c2ac52434e1662
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1569dabc95b8e86f63eaf7b3d921758638cd2183ea403610400f437f6824fe0d18d0b763c3ce2752ab6d2a63641d2755affd51137d134f6cf3adf2e6caa10869
|
7
|
+
data.tar.gz: 1e9d50a96ae0cc44d2ab218d45933ec4b3a49ec5686875351de2f6b5be10deaaa2e1843431bb88b89eb783c59a0c1f76d1ccda46ad915d11fc4e5da2c27640f1
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGES.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
0.3.3.dev
|
2
|
+
---------
|
3
|
+
|
4
|
+
0.3.2
|
5
|
+
---------
|
6
|
+
* improve matching targers
|
7
|
+
* possibility to add many checkers with the same type per process (ex: checks :http_2, ...)
|
8
|
+
* add uid,gid options (only for ruby 2.0)
|
9
|
+
|
10
|
+
0.3.1
|
11
|
+
-----
|
12
|
+
* load multiple configs (folder,...) now not breaks on first error (each config loads separately)
|
13
|
+
* load ~/.eyeconfig with first eye load
|
14
|
+
* some concurrency fixes
|
15
|
+
* custom checker
|
16
|
+
|
17
|
+
0.3
|
18
|
+
---
|
19
|
+
* stable version
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
Eye
|
1
|
+
Eye
|
2
2
|
===
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/eye.png)](http://rubygems.org/gems/eye)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/kostya/eye.png?branch=master)](http://travis-ci.org/kostya/eye)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/kostya/eye/badge.png?branch=master)](https://coveralls.io/r/kostya/eye?branch=master)
|
3
6
|
|
4
7
|
Process monitoring tool. An alternative to God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.3-p194. Uses Celluloid and Celluloid::IO.
|
5
8
|
|
@@ -150,6 +153,10 @@ Check config syntax:
|
|
150
153
|
|
151
154
|
$ eye c(heck) examples/test.eye
|
152
155
|
|
156
|
+
Config explain (for debug):
|
157
|
+
|
158
|
+
$ eye e(xplain) examples/test.eye
|
159
|
+
|
153
160
|
Log tracing:
|
154
161
|
|
155
162
|
$ eye trace
|
@@ -160,11 +167,6 @@ Quit monitoring:
|
|
160
167
|
|
161
168
|
$ eye q(uit)
|
162
169
|
|
163
|
-
Config
|
164
|
-
|
165
|
-
$ eye explain examples/test.eye
|
166
|
-
|
167
|
-
|
168
|
-
### Config api:
|
170
|
+
### Config options:
|
169
171
|
|
170
|
-
Waiting for pull requests ..., until that you can read `examples` and `spec/dsl` folders.
|
172
|
+
Waiting for pull requests here..., until that you can read `examples` and `spec/dsl` folders.
|
data/bin/eye
CHANGED
@@ -10,9 +10,7 @@ class Cli < Thor
|
|
10
10
|
|
11
11
|
desc "info [MASK]", "show process statuses"
|
12
12
|
def info(mask = nil)
|
13
|
-
|
14
|
-
puts res if res && !res.empty?
|
15
|
-
puts
|
13
|
+
print cmd(:info, mask)
|
16
14
|
end
|
17
15
|
|
18
16
|
desc "status ", "show process statuses"
|
@@ -25,31 +23,22 @@ class Cli < Thor
|
|
25
23
|
method_option :config, :type => :boolean, :aliases => "-c"
|
26
24
|
method_option :show_processes, :type => :boolean, :aliases => "-p"
|
27
25
|
def xinfo
|
28
|
-
|
29
|
-
puts res if res && !res.empty?
|
30
|
-
puts
|
26
|
+
print cmd(:xinfo, options[:config], options[:show_processes])
|
31
27
|
end
|
32
28
|
|
33
29
|
desc "oinfo", "onelined info"
|
34
30
|
def oinfo
|
35
|
-
|
36
|
-
puts res if res && !res.empty?
|
37
|
-
puts
|
31
|
+
print cmd(:oinfo)
|
38
32
|
end
|
39
33
|
|
40
34
|
desc "load [CONF, ...]", "load config (and start server if needed) (-f for foregraund start)"
|
41
35
|
method_option :foregraund, :type => :boolean, :aliases => "-f"
|
42
|
-
method_option :logger, :type => :string, :aliases => "-l"
|
43
36
|
def load(*configs)
|
44
37
|
configs.map!{ |c| File.expand_path(c) } if !configs.empty?
|
45
38
|
|
46
39
|
if options[:foregraund]
|
47
40
|
# in foregraund we stop another server, and run just 1 current config version
|
48
|
-
if configs.size != 1
|
49
|
-
say "foregraund expected only one config", :red
|
50
|
-
exit 1
|
51
|
-
end
|
52
|
-
|
41
|
+
error!("foregraund expected only one config") if configs.size != 1
|
53
42
|
server_start_foregraund(configs.first)
|
54
43
|
|
55
44
|
elsif server_started?
|
@@ -90,9 +79,7 @@ class Cli < Thor
|
|
90
79
|
|
91
80
|
desc "history TARGET[,...]", "show process states history"
|
92
81
|
def history(*targets)
|
93
|
-
|
94
|
-
puts res if res && !res.empty?
|
95
|
-
puts
|
82
|
+
print cmd(:history, *targets)
|
96
83
|
end
|
97
84
|
|
98
85
|
desc "trace [TARGET]", "tracing log for app,group or process"
|
@@ -146,6 +133,16 @@ class Cli < Thor
|
|
146
133
|
|
147
134
|
private
|
148
135
|
|
136
|
+
def error!(msg)
|
137
|
+
say msg, :red
|
138
|
+
exit 1
|
139
|
+
end
|
140
|
+
|
141
|
+
def print(msg, new_line = true)
|
142
|
+
say msg if msg && !msg.empty?
|
143
|
+
say if new_line
|
144
|
+
end
|
145
|
+
|
149
146
|
def client
|
150
147
|
@client ||= Eye::Client.new(Eye::Settings.socket_path)
|
151
148
|
end
|
@@ -160,11 +157,9 @@ private
|
|
160
157
|
res = _cmd(cmd, *args)
|
161
158
|
|
162
159
|
if res == :not_started
|
163
|
-
|
164
|
-
exit 1
|
160
|
+
error! "eye monitoring not found, did you start it?"
|
165
161
|
elsif res == :timeouted
|
166
|
-
|
167
|
-
exit 1
|
162
|
+
error! "eye does not answer, timeouted..."
|
168
163
|
end
|
169
164
|
|
170
165
|
res
|
@@ -175,18 +170,12 @@ private
|
|
175
170
|
end
|
176
171
|
|
177
172
|
def say_load_result(res = {}, opts = {})
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
say_filename = (res.size > 1)
|
185
|
-
say "eye started!", :green if opts[:started]
|
186
|
-
res.each do |filename, _res|
|
187
|
-
say "#{filename}: ", nil, true if say_filename
|
188
|
-
show_load_message(_res, opts)
|
189
|
-
end
|
173
|
+
error!(res) unless res.is_a?(Hash)
|
174
|
+
say_filename = (res.size > 1)
|
175
|
+
say "eye started!", :green if opts[:started]
|
176
|
+
res.each do |filename, _res|
|
177
|
+
say "#{filename}: ", nil, true if say_filename
|
178
|
+
show_load_message(_res, opts)
|
190
179
|
end
|
191
180
|
end
|
192
181
|
|
@@ -212,11 +201,11 @@ private
|
|
212
201
|
def send_command(_cmd, *args)
|
213
202
|
res = cmd(_cmd, *args)
|
214
203
|
if res == :unknown_command
|
215
|
-
|
204
|
+
error! "unknown command :#{_cmd}"
|
216
205
|
elsif res == :corrupred_marshal
|
217
|
-
|
206
|
+
error! "something crazy wrong, check eye logs!"
|
218
207
|
elsif res == []
|
219
|
-
|
208
|
+
error! "command :#{_cmd}, targets not found!"
|
220
209
|
else
|
221
210
|
say "command :#{_cmd} sended to [#{res * ", "}]"
|
222
211
|
end
|
@@ -227,7 +216,7 @@ private
|
|
227
216
|
if log_file && File.exists?(log_file)
|
228
217
|
Process.exec "tail -n 100 -f #{log_file} | grep '#{tag}'"
|
229
218
|
else
|
230
|
-
|
219
|
+
error! "log file not found #{log_file.inspect}"
|
231
220
|
end
|
232
221
|
end
|
233
222
|
|
@@ -250,8 +239,7 @@ private
|
|
250
239
|
|
251
240
|
def ensure_loader_path
|
252
241
|
unless loader_path
|
253
|
-
|
254
|
-
exit 1
|
242
|
+
error! "start monitoring needs to run under ruby with installed gem 'eye'"
|
255
243
|
end
|
256
244
|
end
|
257
245
|
|
@@ -275,18 +263,15 @@ private
|
|
275
263
|
Eye::Settings.ensure_eye_dir
|
276
264
|
|
277
265
|
ensure_stop_previous_server
|
278
|
-
|
279
|
-
args = []
|
280
|
-
args += ['-l', options[:logger]] if options[:logger]
|
281
266
|
|
267
|
+
args = []
|
282
268
|
pid = Process.spawn(ruby_path, loader_path, *args, :out => '/dev/null', :err => '/dev/null', :in => '/dev/null',
|
283
269
|
:chdir => '/', :pgroup => true)
|
284
270
|
Process.detach(pid)
|
285
271
|
File.open(Eye::Settings.pid_path, 'w'){|f| f.write(pid) }
|
286
272
|
|
287
273
|
unless wait_server
|
288
|
-
|
289
|
-
exit 1
|
274
|
+
error! "server not runned in 15 seconds, something crazy wrong"
|
290
275
|
end
|
291
276
|
|
292
277
|
configs.unshift(Eye::Settings.eyeconfig) if File.exists?(Eye::Settings.eyeconfig)
|
data/examples/notify.eye
CHANGED
data/examples/puma.eye
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
RUBY = '/usr/local/ruby/1.9.3-p392/bin/ruby'
|
2
2
|
RAILS_ENV = 'production'
|
3
|
-
ROOT =
|
3
|
+
ROOT = File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
4
4
|
CURRENT = File.expand_path(File.join(ROOT, %w{current}))
|
5
5
|
LOGS = File.expand_path(File.join(ROOT, %w{shared log}))
|
6
6
|
PIDS = File.expand_path(File.join(ROOT, %w{shared pids}))
|
@@ -12,7 +12,7 @@ end
|
|
12
12
|
|
13
13
|
Eye.application :super_app do
|
14
14
|
env 'RAILS_ENV' => RAILS_ENV
|
15
|
-
working_dir
|
15
|
+
working_dir ROOT
|
16
16
|
triggers :flapping, :times => 10, :within => 1.minute
|
17
17
|
|
18
18
|
process :puma do
|
data/examples/rbenv.eye
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Eye.application "rbenv_example" do
|
2
2
|
env 'RBENV_ROOT' => '/usr/local/rbenv', 'PATH' => "/usr/local/rbenv/shims:/usr/local/rbenv/bin:#{ENV['PATH']}"
|
3
|
-
working_dir
|
3
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
4
4
|
|
5
5
|
process "some_process" do
|
6
6
|
pid_file "some.pid"
|
@@ -8,4 +8,4 @@ Eye.application "rbenv_example" do
|
|
8
8
|
daemonize true
|
9
9
|
stdall "some.log"
|
10
10
|
end
|
11
|
-
end
|
11
|
+
end
|
data/examples/sidekiq.eye
CHANGED
@@ -16,8 +16,8 @@ def sidekiq_process(proxy, name)
|
|
16
16
|
end
|
17
17
|
|
18
18
|
Eye.application :sidekiq_test do
|
19
|
-
working_dir
|
19
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
20
20
|
env "RAILS_ENV" => 'production'
|
21
21
|
|
22
22
|
sidekiq_process self, :sidekiq
|
23
|
-
end
|
23
|
+
end
|
data/examples/thin-farm.eye
CHANGED
data/examples/unicorn.eye
CHANGED
@@ -5,7 +5,7 @@ RAILS_ENV = 'production'
|
|
5
5
|
|
6
6
|
Eye.application "rails_unicorn" do
|
7
7
|
env "RAILS_ENV" => RAILS_ENV, "PATH" => "#{File.dirname(RUBY)}:#{ENV['PATH']}"
|
8
|
-
working_dir
|
8
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
9
9
|
|
10
10
|
process("unicorn") do
|
11
11
|
pid_file "tmp/pids/unicorn.pid"
|
data/eye.gemspec
CHANGED
@@ -27,7 +27,6 @@ Gem::Specification.new do |gem|
|
|
27
27
|
|
28
28
|
gem.add_development_dependency 'rake'
|
29
29
|
gem.add_development_dependency 'rspec'
|
30
|
-
gem.add_development_dependency 'simplecov'
|
31
30
|
gem.add_development_dependency 'rr'
|
32
31
|
gem.add_development_dependency 'ruby-graphviz'
|
33
32
|
gem.add_development_dependency 'forking'
|
@@ -36,4 +35,5 @@ Gem::Specification.new do |gem|
|
|
36
35
|
gem.add_development_dependency 'sinatra'
|
37
36
|
gem.add_development_dependency 'thin'
|
38
37
|
gem.add_development_dependency 'xmpp4r'
|
38
|
+
gem.add_development_dependency 'coveralls'
|
39
39
|
end
|
data/lib/eye.rb
CHANGED
data/lib/eye/application.rb
CHANGED
data/lib/eye/checker.rb
CHANGED
@@ -13,6 +13,16 @@ class Eye::Checker
|
|
13
13
|
|
14
14
|
attr_accessor :value, :values, :options, :pid, :type, :check_count
|
15
15
|
|
16
|
+
def self.name_and_class(type)
|
17
|
+
type = type.to_sym
|
18
|
+
return {:name => type, :type => type} if TYPES[type]
|
19
|
+
|
20
|
+
if type =~ /\A(.*?)_?[0-9]+\z/
|
21
|
+
ctype = $1.to_sym
|
22
|
+
return {:name => type, :type => ctype} if TYPES[ctype]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
16
26
|
def self.get_class(type)
|
17
27
|
klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
|
18
28
|
raise "Unknown checker #{type}" unless klass
|
@@ -6,10 +6,24 @@ module Eye::Controller::Helpers
|
|
6
6
|
$0 = str
|
7
7
|
end
|
8
8
|
|
9
|
+
def save_cache
|
10
|
+
File.open(Eye::Settings.cache_path, 'w') { |f| f.write(cache_str) }
|
11
|
+
rescue => ex
|
12
|
+
warn "save cache crashed with #{ex.message}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def cache_str
|
16
|
+
all_processes.map{ |p| "#{p.full_name}=#{p.state}" } * "\n"
|
17
|
+
end
|
18
|
+
|
9
19
|
def process_by_name(name)
|
10
20
|
all_processes.detect{|c| c.name == name}
|
11
21
|
end
|
12
22
|
|
23
|
+
def process_by_full_name(name)
|
24
|
+
all_processes.detect{|c| c.full_name == name }
|
25
|
+
end
|
26
|
+
|
13
27
|
def group_by_name(name)
|
14
28
|
all_groups.detect{|c| c.name == name}
|
15
29
|
end
|
@@ -58,4 +72,4 @@ module Eye::Controller::Helpers
|
|
58
72
|
res
|
59
73
|
end
|
60
74
|
|
61
|
-
end
|
75
|
+
end
|
data/lib/eye/controller/load.rb
CHANGED
@@ -22,6 +22,7 @@ module Eye::Controller::Load
|
|
22
22
|
end
|
23
23
|
|
24
24
|
set_proc_line
|
25
|
+
save_cache
|
25
26
|
|
26
27
|
res
|
27
28
|
end
|
@@ -35,6 +36,8 @@ private
|
|
35
36
|
{ :error => false, :config => yield }
|
36
37
|
|
37
38
|
rescue Eye::Dsl::Error, Exception, NoMethodError => ex
|
39
|
+
raise if ex.class.to_s.include?('RR') # skip RR exceptions
|
40
|
+
|
38
41
|
error "load: config error <#{filename}>: #{ex.message}"
|
39
42
|
|
40
43
|
# filter backtrace for user output
|
@@ -4,7 +4,9 @@ module Eye::Controller::SendCommand
|
|
4
4
|
matched_objects(*obj_strs) do |obj|
|
5
5
|
if command.to_sym == :delete
|
6
6
|
remove_object_from_tree(obj)
|
7
|
-
|
7
|
+
|
8
|
+
set_proc_line
|
9
|
+
save_cache
|
8
10
|
end
|
9
11
|
|
10
12
|
obj.send_command(command)
|
@@ -61,32 +63,44 @@ private
|
|
61
63
|
return [] if obj_strs.blank?
|
62
64
|
return @applications.dup if obj_strs.size == 1 && (obj_strs[0].strip == 'all' || obj_strs[0].strip == '*')
|
63
65
|
|
64
|
-
res =
|
66
|
+
res = Eye::Utils::AliveArray.new
|
65
67
|
obj_strs.map{|c| c.split(",")}.flatten.each do |mask|
|
66
|
-
res += find_objects_by_mask(mask)
|
68
|
+
res += find_objects_by_mask(mask.to_s.strip)
|
67
69
|
end
|
70
|
+
res
|
71
|
+
end
|
72
|
+
|
73
|
+
def find_objects_by_mask(mask)
|
74
|
+
res = find_all_objects_by_mask(mask)
|
68
75
|
|
69
76
|
if res.size > 1
|
70
|
-
|
77
|
+
final = Eye::Utils::AliveArray.new
|
71
78
|
|
72
|
-
|
79
|
+
if mask[-1] != '*'
|
80
|
+
# try to find exactly matched
|
81
|
+
r = right_regexp(mask)
|
82
|
+
res.each do |obj|
|
83
|
+
final << obj if obj.full_name =~ r
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
return final if final.present?
|
88
|
+
|
89
|
+
# remove inherited targets
|
73
90
|
res.each do |obj|
|
74
91
|
sub_object = res.any?{|a| a.sub_object?(obj) }
|
75
92
|
final << obj unless sub_object
|
76
93
|
end
|
77
94
|
|
78
95
|
res = final
|
79
|
-
end
|
96
|
+
end
|
80
97
|
|
81
|
-
res
|
98
|
+
res
|
82
99
|
end
|
83
100
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
87
|
-
res = []
|
88
|
-
str = Regexp.escape(mask).gsub('\*', '.*?')
|
89
|
-
r = %r{\A#{str}}
|
101
|
+
def find_all_objects_by_mask(mask)
|
102
|
+
res = Eye::Utils::AliveArray
|
103
|
+
r = left_regexp(mask)
|
90
104
|
|
91
105
|
# find app
|
92
106
|
res = @applications.select{|a| a.name =~ r || a.full_name =~ r }
|
@@ -102,9 +116,16 @@ private
|
|
102
116
|
gr.processes.each do |p|
|
103
117
|
res << p if p.name =~ r || p.full_name =~ r
|
104
118
|
|
119
|
+
# child matching
|
105
120
|
if p.childs.present?
|
106
|
-
|
121
|
+
childs = p.childs.values
|
122
|
+
res += childs.select do |ch|
|
123
|
+
name = ch.name rescue ''
|
124
|
+
full_name = ch.full_name rescue ''
|
125
|
+
name =~ r || full_name =~ r
|
126
|
+
end
|
107
127
|
end
|
128
|
+
|
108
129
|
end
|
109
130
|
end
|
110
131
|
end
|
@@ -112,4 +133,13 @@ private
|
|
112
133
|
res
|
113
134
|
end
|
114
135
|
|
136
|
+
def left_regexp(mask)
|
137
|
+
str = Regexp.escape(mask).gsub('\*', '.*?')
|
138
|
+
%r|\A#{str}|
|
139
|
+
end
|
140
|
+
|
141
|
+
def right_regexp(mask)
|
142
|
+
str = Regexp.escape(mask).gsub('\*', '.*?')
|
143
|
+
%r|#{str}\z|
|
144
|
+
end
|
115
145
|
end
|
@@ -28,7 +28,7 @@ module Eye::Controller::Status
|
|
28
28
|
|
29
29
|
str = <<-S
|
30
30
|
About: #{Eye::ABOUT}
|
31
|
-
Info: #{resources_str(Eye::SystemResources.resources($$)
|
31
|
+
Info: #{resources_str(Eye::SystemResources.resources($$))}
|
32
32
|
Ruby: #{RUBY_DESCRIPTION}
|
33
33
|
Logger: #{Eye::Logger.dev}
|
34
34
|
Socket: #{Eye::Settings::socket_path}
|
@@ -98,16 +98,11 @@ private
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
def resources_str(r
|
101
|
+
def resources_str(r)
|
102
102
|
return '' if r.blank?
|
103
103
|
|
104
104
|
res = "#{r[:start_time]}, #{r[:cpu]}%"
|
105
|
-
|
106
|
-
if r[:memory]
|
107
|
-
mem = mb ? "#{r[:memory] / 1024}Mb" : "#{r[:memory]}Kb"
|
108
|
-
res += ", #{mem}"
|
109
|
-
end
|
110
|
-
|
105
|
+
res += ", #{r[:memory] / 1024}Mb" if r[:memory]
|
111
106
|
res += ", <#{r[:pid]}>"
|
112
107
|
|
113
108
|
res
|
@@ -6,6 +6,10 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
|
|
6
6
|
[:pid_file, :start_command]
|
7
7
|
end
|
8
8
|
|
9
|
+
def not_seed_options
|
10
|
+
[:groups]
|
11
|
+
end
|
12
|
+
|
9
13
|
def group(name, &block)
|
10
14
|
Eye::Dsl.debug "=> group #{name}"
|
11
15
|
|
@@ -28,6 +32,6 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
|
|
28
32
|
group("__default__"){ process(name.to_s, &block) }
|
29
33
|
end
|
30
34
|
|
31
|
-
|
32
|
-
|
35
|
+
alias xgroup nop
|
36
|
+
alias xprocess nop
|
33
37
|
end
|
data/lib/eye/dsl/group_opts.rb
CHANGED
@@ -6,6 +6,10 @@ class Eye::Dsl::GroupOpts < Eye::Dsl::Opts
|
|
6
6
|
[:pid_file, :start_command]
|
7
7
|
end
|
8
8
|
|
9
|
+
def not_seed_options
|
10
|
+
[:processes, :chain]
|
11
|
+
end
|
12
|
+
|
9
13
|
def process(name, &block)
|
10
14
|
Eye::Dsl.debug "=> process #{name}"
|
11
15
|
|
@@ -17,11 +21,8 @@ class Eye::Dsl::GroupOpts < Eye::Dsl::Opts
|
|
17
21
|
Eye::Dsl.debug "<= process #{name}"
|
18
22
|
end
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
parent
|
24
|
-
end
|
25
|
-
alias :app :application
|
24
|
+
alias xprocess nop
|
25
|
+
alias application parent
|
26
|
+
alias app application
|
26
27
|
|
27
28
|
end
|
data/lib/eye/dsl/main.rb
CHANGED
data/lib/eye/dsl/opts.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
2
2
|
|
3
3
|
STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :start_command,
|
4
|
-
:stop_command, :restart_command ]
|
4
|
+
:stop_command, :restart_command, :uid, :gid ]
|
5
5
|
create_options_methods(STR_OPTIONS, String)
|
6
6
|
|
7
7
|
BOOL_OPTIONS = [ :daemonize, :keep_alive, :control_pid, :auto_start, :stop_on_delete]
|
@@ -11,17 +11,14 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
11
11
|
:restart_grace, :stop_grace, :childs_update_period ]
|
12
12
|
create_options_methods(INTERVAL_OPTIONS, [Fixnum, Float])
|
13
13
|
|
14
|
-
|
15
|
-
create_options_methods(
|
14
|
+
create_options_methods([:environment], Hash)
|
15
|
+
create_options_methods([:stop_signals], Array)
|
16
|
+
create_options_methods([:umask], Fixnum)
|
16
17
|
|
17
18
|
|
18
19
|
def initialize(name = nil, parent = nil)
|
19
20
|
super(name, parent)
|
20
21
|
|
21
|
-
# ensure delete subobjects which can appears from parent config
|
22
|
-
@config.delete :groups
|
23
|
-
@config.delete :processes
|
24
|
-
|
25
22
|
@config[:application] = parent.name if parent.is_a?(Eye::Dsl::ApplicationOpts)
|
26
23
|
@config[:group] = parent.name if parent.is_a?(Eye::Dsl::GroupOpts)
|
27
24
|
|
@@ -30,14 +27,14 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
30
27
|
end
|
31
28
|
|
32
29
|
def checks(type, opts = {})
|
33
|
-
|
34
|
-
raise Eye::Dsl::Error, "unknown checker type #{type}" unless
|
30
|
+
nac = Eye::Checker.name_and_class(type.to_sym)
|
31
|
+
raise Eye::Dsl::Error, "unknown checker type #{type}" unless nac
|
35
32
|
|
36
|
-
opts.merge!(:type => type)
|
33
|
+
opts.merge!(:type => nac[:type])
|
37
34
|
Eye::Checker.validate!(opts)
|
38
35
|
|
39
36
|
@config[:checks] ||= {}
|
40
|
-
@config[:checks][
|
37
|
+
@config[:checks][nac[:name]] = opts
|
41
38
|
end
|
42
39
|
|
43
40
|
def triggers(type, opts = {})
|
@@ -53,9 +50,9 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
53
50
|
|
54
51
|
# clear checks from parent
|
55
52
|
def nochecks(type)
|
56
|
-
|
57
|
-
raise Eye::Dsl::Error, "unknown checker type #{type}" unless
|
58
|
-
@config[:checks].try :delete,
|
53
|
+
nac = Eye::Checker.name_and_class(type.to_sym)
|
54
|
+
raise Eye::Dsl::Error, "unknown checker type #{type}" unless nac
|
55
|
+
@config[:checks].try :delete, nac[:name]
|
59
56
|
end
|
60
57
|
|
61
58
|
# clear triggers from parent
|
@@ -85,7 +82,7 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
85
82
|
@config[:environment].merge!(value)
|
86
83
|
end
|
87
84
|
|
88
|
-
alias
|
85
|
+
alias env environment
|
89
86
|
|
90
87
|
def set_stdall(value)
|
91
88
|
super
|
@@ -94,6 +91,16 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
94
91
|
set_stderr value
|
95
92
|
end
|
96
93
|
|
94
|
+
def set_uid(value)
|
95
|
+
raise Eye::Dsl::Error, ":uid not supported by ruby (needed 2.0)" unless Eye::Settings.supported_setsid?
|
96
|
+
super
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_gid(value)
|
100
|
+
raise Eye::Dsl::Error, ":gid not supported by ruby (needed 2.0)" unless Eye::Settings.supported_setsid?
|
101
|
+
super
|
102
|
+
end
|
103
|
+
|
97
104
|
def scoped(&block)
|
98
105
|
h = self.class.new(self.name, self)
|
99
106
|
h.instance_eval(&block)
|
data/lib/eye/dsl/process_opts.rb
CHANGED
@@ -7,15 +7,12 @@ class Eye::Dsl::ProcessOpts < Eye::Dsl::Opts
|
|
7
7
|
@config[:monitor_children].merge!(opts.config)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
alias xmonitor_children nop
|
11
11
|
|
12
12
|
def application
|
13
13
|
parent.try(:parent)
|
14
14
|
end
|
15
|
-
alias
|
16
|
-
|
17
|
-
def group
|
18
|
-
parent
|
19
|
-
end
|
15
|
+
alias app application
|
16
|
+
alias group parent
|
20
17
|
|
21
18
|
end
|
data/lib/eye/dsl/pure_opts.rb
CHANGED
@@ -49,7 +49,12 @@ class Eye::Dsl::PureOpts
|
|
49
49
|
|
50
50
|
if parent
|
51
51
|
@parent = parent
|
52
|
-
|
52
|
+
if merge_parent_config
|
53
|
+
@config = Eye::Utils::deep_clone(parent.config)
|
54
|
+
parent.not_seed_options.each { |opt| @config.delete(opt) }
|
55
|
+
else
|
56
|
+
@config = {}
|
57
|
+
end
|
53
58
|
@full_name = "#{parent.full_name}:#{@full_name}"
|
54
59
|
else
|
55
60
|
@config = {}
|
@@ -66,6 +71,10 @@ class Eye::Dsl::PureOpts
|
|
66
71
|
[]
|
67
72
|
end
|
68
73
|
|
74
|
+
def not_seed_options
|
75
|
+
[]
|
76
|
+
end
|
77
|
+
|
69
78
|
def with_condition(cond = true, &block)
|
70
79
|
self.instance_eval(&block) if cond && block
|
71
80
|
end
|
@@ -90,6 +99,8 @@ class Eye::Dsl::PureOpts
|
|
90
99
|
end
|
91
100
|
end
|
92
101
|
|
102
|
+
def nop(*args, &block); end
|
103
|
+
|
93
104
|
private
|
94
105
|
|
95
106
|
def self.with_parsed_file(file_name)
|
data/lib/eye/group.rb
CHANGED
data/lib/eye/logger.rb
CHANGED
@@ -42,11 +42,11 @@ class Eye::Logger
|
|
42
42
|
attr_reader :dev, :log_level
|
43
43
|
|
44
44
|
def link_logger(dev)
|
45
|
-
@dev = dev ? dev.to_s
|
45
|
+
@dev = dev ? dev.to_s : nil
|
46
46
|
@dev_fd = @dev
|
47
47
|
|
48
|
-
@dev_fd = STDOUT if @dev == 'stdout'
|
49
|
-
@dev_fd = STDERR if @dev == 'stderr'
|
48
|
+
@dev_fd = STDOUT if @dev.to_s.downcase == 'stdout'
|
49
|
+
@dev_fd = STDERR if @dev.to_s.downcase == 'stderr'
|
50
50
|
|
51
51
|
@inner_logger = InnerLogger.new(@dev_fd)
|
52
52
|
@inner_logger.level = self.log_level || Logger::INFO
|
@@ -77,4 +77,4 @@ private
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
end
|
80
|
+
end
|
@@ -53,6 +53,10 @@ module Eye::Process::Scheduler
|
|
53
53
|
def scheduler_actions_list
|
54
54
|
scheduler.list.map{|c| c[:args].first rescue nil }.compact
|
55
55
|
end
|
56
|
+
|
57
|
+
def scheduler_clear_pending_list
|
58
|
+
scheduler.clear_pending_list
|
59
|
+
end
|
56
60
|
|
57
61
|
def self.included(base)
|
58
62
|
base.finalizer :remove_scheduler
|
data/lib/eye/process/validate.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'shellwords'
|
2
|
+
require 'etc'
|
2
3
|
|
3
4
|
module Eye::Process::Validate
|
4
5
|
|
@@ -18,6 +19,13 @@ module Eye::Process::Validate
|
|
18
19
|
|
19
20
|
Shellwords.shellwords(config[:stop_command]) if config[:stop_command]
|
20
21
|
Shellwords.shellwords(config[:restart_command]) if config[:restart_command]
|
22
|
+
|
23
|
+
Etc.getpwnam(config[:uid]) if config[:uid]
|
24
|
+
Etc.getpwnam(config[:gid]) if config[:gid]
|
25
|
+
|
26
|
+
if config[:working_dir]
|
27
|
+
raise Error, "working_dir '#{config[:working_dir]}' is invalid" unless File.directory?(config[:working_dir])
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
|
-
end
|
31
|
+
end
|
data/lib/eye/process/watchers.rb
CHANGED
@@ -46,14 +46,14 @@ private
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def start_checkers
|
49
|
-
self[:checks].each{|
|
49
|
+
self[:checks].each{|name, cfg| start_checker(name, cfg) }
|
50
50
|
end
|
51
51
|
|
52
|
-
def start_checker(cfg)
|
52
|
+
def start_checker(name, cfg)
|
53
53
|
subject = Eye::Checker.create(pid, cfg, logger.prefix)
|
54
54
|
|
55
55
|
# ex: {:type => :memory, :every => 5.seconds, :below => 100.megabytes, :times => [3,5]}
|
56
|
-
add_watcher("check_#{
|
56
|
+
add_watcher("check_#{name}".to_sym, subject.every, subject, &method(:watcher_tick).to_proc)
|
57
57
|
end
|
58
58
|
|
59
59
|
def watcher_tick(subject)
|
data/lib/eye/settings.rb
CHANGED
@@ -4,7 +4,7 @@ module Eye::Settings
|
|
4
4
|
module_function
|
5
5
|
|
6
6
|
def dir
|
7
|
-
if
|
7
|
+
if root?
|
8
8
|
'/var/run/eye'
|
9
9
|
else
|
10
10
|
File.expand_path(File.join(home, '.eye'))
|
@@ -12,13 +12,17 @@ module Eye::Settings
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def eyeconfig
|
15
|
-
if
|
15
|
+
if root?
|
16
16
|
'/etc/eye.conf'
|
17
17
|
else
|
18
18
|
File.expand_path(File.join(home, '.eyeconfig'))
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def root?
|
23
|
+
Process::UID.eid == 0
|
24
|
+
end
|
25
|
+
|
22
26
|
def home
|
23
27
|
ENV['EYE_HOME'] || ENV['HOME']
|
24
28
|
end
|
@@ -32,15 +36,23 @@ module Eye::Settings
|
|
32
36
|
end
|
33
37
|
|
34
38
|
def socket_path
|
35
|
-
path('sock')
|
39
|
+
path(ENV['EYE_SOCK'] || "sock#{ENV['EYE_V']}")
|
36
40
|
end
|
37
41
|
|
38
42
|
def pid_path
|
39
|
-
path('pid')
|
43
|
+
path(ENV['EYE_PID'] || "pid#{ENV['EYE_V']}")
|
40
44
|
end
|
41
45
|
|
46
|
+
def cache_path
|
47
|
+
path("processes#{ENV['EYE_V']}.cache")
|
48
|
+
end
|
49
|
+
|
42
50
|
def client_timeout
|
43
51
|
5
|
44
52
|
end
|
45
53
|
|
46
|
-
|
54
|
+
def supported_setsid?
|
55
|
+
RUBY_VERSION >= '2.0'
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/eye/system.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'shellwords'
|
2
2
|
require 'pathname'
|
3
|
+
require 'etc'
|
3
4
|
|
4
5
|
module Eye::System
|
5
6
|
class << self
|
@@ -134,6 +135,14 @@ module Eye::System
|
|
134
135
|
o.update(out: [config[:stdout], 'a']) if config[:stdout]
|
135
136
|
o.update(err: [config[:stderr], 'a']) if config[:stderr]
|
136
137
|
o.update(in: config[:stdin]) if config[:stdin]
|
138
|
+
|
139
|
+
if Eye::Settings.root?
|
140
|
+
o.update(uid: Etc.getpwnam(config[:uid]).uid) if config[:uid]
|
141
|
+
o.update(gid: Etc.getpwnam(config[:gid]).gid) if config[:gid]
|
142
|
+
end
|
143
|
+
|
144
|
+
o.update(umask: config[:umask]) if config[:umask]
|
145
|
+
|
137
146
|
o
|
138
147
|
end
|
139
148
|
|
@@ -2,7 +2,8 @@ class Eye::Utils::AliveArray
|
|
2
2
|
extend Forwardable
|
3
3
|
include Enumerable
|
4
4
|
|
5
|
-
def_delegators :@arr, :[], :<<, :clear, :delete, :size, :empty?, :push,
|
5
|
+
def_delegators :@arr, :[], :<<, :clear, :delete, :size, :empty?, :push,
|
6
|
+
:flatten, :present?, :uniq!
|
6
7
|
|
7
8
|
def initialize(arr = [])
|
8
9
|
@arr = arr
|
@@ -28,4 +29,25 @@ class Eye::Utils::AliveArray
|
|
28
29
|
self.class.new super
|
29
30
|
end
|
30
31
|
|
32
|
+
def +(other)
|
33
|
+
if other.is_a?(Eye::Utils::AliveArray)
|
34
|
+
@arr += other.pure
|
35
|
+
elsif other.is_a?(Array)
|
36
|
+
@arr += other
|
37
|
+
else
|
38
|
+
raise "Unexpected + #{other}"
|
39
|
+
end
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
if other.is_a?(Eye::Utils::AliveArray)
|
45
|
+
@arr == other.pure
|
46
|
+
elsif other.is_a?(Array)
|
47
|
+
@arr == other
|
48
|
+
else
|
49
|
+
raise "Unexpected == #{other}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
31
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eye
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Makarchev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rr
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - '>='
|
@@ -123,7 +123,7 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: ruby-graphviz
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - '>='
|
@@ -137,7 +137,7 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: forking
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - '>='
|
@@ -151,7 +151,7 @@ dependencies:
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: fakeweb
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - '>='
|
@@ -165,35 +165,35 @@ dependencies:
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
|
-
name:
|
168
|
+
name: eventmachine
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
171
|
- - '>='
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version:
|
173
|
+
version: 1.0.3
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - '>='
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
180
|
+
version: 1.0.3
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
182
|
+
name: sinatra
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
184
184
|
requirements:
|
185
185
|
- - '>='
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
187
|
+
version: '0'
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - '>='
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
194
|
+
version: '0'
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
|
-
name:
|
196
|
+
name: thin
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
198
198
|
requirements:
|
199
199
|
- - '>='
|
@@ -207,7 +207,7 @@ dependencies:
|
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '0'
|
209
209
|
- !ruby/object:Gem::Dependency
|
210
|
-
name:
|
210
|
+
name: xmpp4r
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
213
|
- - '>='
|
@@ -221,7 +221,7 @@ dependencies:
|
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
|
-
name:
|
224
|
+
name: coveralls
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|
226
226
|
requirements:
|
227
227
|
- - '>='
|
@@ -246,6 +246,7 @@ files:
|
|
246
246
|
- .gitignore
|
247
247
|
- .rspec
|
248
248
|
- .travis.yml
|
249
|
+
- CHANGES.md
|
249
250
|
- Gemfile
|
250
251
|
- LICENSE
|
251
252
|
- README.md
|