reel-eye 0.3.1

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.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +32 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +22 -0
  7. data/README.md +170 -0
  8. data/Rakefile +20 -0
  9. data/bin/eye +322 -0
  10. data/bin/loader_eye +58 -0
  11. data/examples/notify.eye +18 -0
  12. data/examples/process_thin.rb +29 -0
  13. data/examples/processes/em.rb +57 -0
  14. data/examples/processes/forking.rb +20 -0
  15. data/examples/processes/sample.rb +144 -0
  16. data/examples/processes/thin.ru +12 -0
  17. data/examples/puma.eye +34 -0
  18. data/examples/rbenv.eye +11 -0
  19. data/examples/sidekiq.eye +23 -0
  20. data/examples/test.eye +81 -0
  21. data/examples/thin-farm.eye +29 -0
  22. data/examples/unicorn.eye +31 -0
  23. data/eye.gemspec +42 -0
  24. data/lib/eye.rb +28 -0
  25. data/lib/eye/application.rb +74 -0
  26. data/lib/eye/checker.rb +138 -0
  27. data/lib/eye/checker/cpu.rb +27 -0
  28. data/lib/eye/checker/file_ctime.rb +25 -0
  29. data/lib/eye/checker/file_size.rb +34 -0
  30. data/lib/eye/checker/http.rb +98 -0
  31. data/lib/eye/checker/memory.rb +27 -0
  32. data/lib/eye/checker/socket.rb +152 -0
  33. data/lib/eye/child_process.rb +101 -0
  34. data/lib/eye/client.rb +32 -0
  35. data/lib/eye/config.rb +88 -0
  36. data/lib/eye/control.rb +2 -0
  37. data/lib/eye/controller.rb +53 -0
  38. data/lib/eye/controller/commands.rb +73 -0
  39. data/lib/eye/controller/helpers.rb +61 -0
  40. data/lib/eye/controller/load.rb +214 -0
  41. data/lib/eye/controller/options.rb +48 -0
  42. data/lib/eye/controller/send_command.rb +115 -0
  43. data/lib/eye/controller/show_history.rb +62 -0
  44. data/lib/eye/controller/status.rb +131 -0
  45. data/lib/eye/dsl.rb +48 -0
  46. data/lib/eye/dsl/application_opts.rb +33 -0
  47. data/lib/eye/dsl/chain.rb +12 -0
  48. data/lib/eye/dsl/child_process_opts.rb +8 -0
  49. data/lib/eye/dsl/config_opts.rb +48 -0
  50. data/lib/eye/dsl/group_opts.rb +27 -0
  51. data/lib/eye/dsl/helpers.rb +12 -0
  52. data/lib/eye/dsl/main.rb +40 -0
  53. data/lib/eye/dsl/opts.rb +140 -0
  54. data/lib/eye/dsl/process_opts.rb +21 -0
  55. data/lib/eye/dsl/pure_opts.rb +110 -0
  56. data/lib/eye/dsl/validation.rb +59 -0
  57. data/lib/eye/group.rb +134 -0
  58. data/lib/eye/group/chain.rb +81 -0
  59. data/lib/eye/http.rb +31 -0
  60. data/lib/eye/http/router.rb +25 -0
  61. data/lib/eye/loader.rb +23 -0
  62. data/lib/eye/logger.rb +80 -0
  63. data/lib/eye/notify.rb +86 -0
  64. data/lib/eye/notify/jabber.rb +30 -0
  65. data/lib/eye/notify/mail.rb +44 -0
  66. data/lib/eye/process.rb +86 -0
  67. data/lib/eye/process/child.rb +58 -0
  68. data/lib/eye/process/commands.rb +256 -0
  69. data/lib/eye/process/config.rb +70 -0
  70. data/lib/eye/process/controller.rb +76 -0
  71. data/lib/eye/process/data.rb +47 -0
  72. data/lib/eye/process/monitor.rb +95 -0
  73. data/lib/eye/process/notify.rb +32 -0
  74. data/lib/eye/process/scheduler.rb +78 -0
  75. data/lib/eye/process/states.rb +86 -0
  76. data/lib/eye/process/states_history.rb +66 -0
  77. data/lib/eye/process/system.rb +97 -0
  78. data/lib/eye/process/trigger.rb +54 -0
  79. data/lib/eye/process/validate.rb +23 -0
  80. data/lib/eye/process/watchers.rb +69 -0
  81. data/lib/eye/reason.rb +20 -0
  82. data/lib/eye/server.rb +52 -0
  83. data/lib/eye/settings.rb +46 -0
  84. data/lib/eye/system.rb +154 -0
  85. data/lib/eye/system_resources.rb +86 -0
  86. data/lib/eye/trigger.rb +53 -0
  87. data/lib/eye/trigger/flapping.rb +28 -0
  88. data/lib/eye/utils.rb +14 -0
  89. data/lib/eye/utils/alive_array.rb +31 -0
  90. data/lib/eye/utils/celluloid_chain.rb +70 -0
  91. data/lib/eye/utils/leak_19.rb +7 -0
  92. data/lib/eye/utils/tail.rb +20 -0
  93. metadata +390 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 464e9e9a66aef932d82c8452238c083bfc3561da
4
+ data.tar.gz: 795aaf16fec1578814570cdeff914cf5792144f6
5
+ SHA512:
6
+ metadata.gz: f68bc9205b02c7b3a1643c4f97a5a6f7e151391b93563019663d84b9bf335a8c5a180445ea4b1f97d888fc64d4ba3c3fa6fa1cefdaa404a9d8fe472a96f42f62
7
+ data.tar.gz: 9dcf75372e1a0a93f68a1f7ff04542b1ff391a9522597f7203322157b5860c8bf0243fb271b41c19567077dd70c657bc154061a2a35267149b68469acea7e011
data/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.pid
19
+ *.log
20
+ *.swp
21
+ *~
22
+ TODO
23
+ .todo
24
+ *.png
25
+ *.lock
26
+ experiments
27
+ .git2
28
+ *.stop
29
+ *sublime*
30
+ examples/work*.eye
31
+ script
32
+ [0-9].rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --profile
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eye.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012-2013 'Konstantin Makarchev'
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,170 @@
1
+ Eye [![Build Status](https://secure.travis-ci.org/kostya/eye.png?branch=master)](http://travis-ci.org/kostya/eye)
2
+ ===
3
+
4
+ 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
+
6
+ Little demo, shows general commands and how chain works:
7
+
8
+ [![Eye](https://raw.github.com/kostya/stuff/master/eye/eye.png)](https://raw.github.com/kostya/stuff/master/eye/eye.gif)
9
+
10
+ Recommended installation on the server (system wide):
11
+
12
+ $ sudo /usr/local/ruby/1.9.3/bin/gem install eye
13
+ $ sudo ln -sf /usr/local/ruby/1.9.3/bin/eye /usr/local/bin/eye
14
+
15
+
16
+ Config example, shows some typical processes and most of the options (see in exampes/ folder):
17
+
18
+ examples/test.eye
19
+ ```ruby
20
+ # load submodules, here just for example
21
+ Eye.load("./eye/*.rb")
22
+
23
+ # Eye self-configuration section
24
+ Eye.config do
25
+ logger "/tmp/eye.log"
26
+ end
27
+
28
+ # Adding application
29
+ Eye.application "test" do
30
+ # All options inherits down to the config leafs.
31
+ # except `env`, which merging down
32
+
33
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
34
+ stdall "trash.log" # stdout,err logs for processes by default
35
+ env "APP_ENV" => "production" # global env for each processes
36
+ triggers :flapping, :times => 10, :within => 1.minute, :retry_in => 10.minutes
37
+ checks :cpu, :below => 100, :times => 3 # global check for all processes
38
+
39
+ group "samples" do
40
+ chain :grace => 5.seconds # chained start-restart with 5s interval, one by one.
41
+
42
+ # eye daemonized process
43
+ process :sample1 do
44
+ pid_file "1.pid" # pid_path will be expanded with the working_dir
45
+ start_command "ruby ./sample.rb"
46
+ daemonize true
47
+ stdall "sample1.log"
48
+
49
+ checks :cpu, :below => 30, :times => [3, 5]
50
+ end
51
+
52
+ # self daemonized process
53
+ process :sample2 do
54
+ pid_file "2.pid"
55
+ start_command "ruby ./sample.rb -d --pid 2.pid --log sample2.log"
56
+ stop_command "kill -9 {PID}"
57
+
58
+ checks :memory, :below => 300.megabytes, :times => 3
59
+ end
60
+ end
61
+
62
+ # daemon with 3 childs
63
+ process :forking do
64
+ pid_file "forking.pid"
65
+ start_command "ruby ./forking.rb start"
66
+ stop_command "ruby forking.rb stop"
67
+ stdall "forking.log"
68
+
69
+ start_timeout 5.seconds
70
+ stop_grace 5.seconds
71
+
72
+ monitor_children do
73
+ restart_command "kill -2 {PID}" # for this child process
74
+ checks :memory, :below => 300.megabytes, :times => 3
75
+ end
76
+ end
77
+
78
+ # eventmachine process, daemonized with eye
79
+ process :event_machine do |p|
80
+ pid_file 'em.pid'
81
+ start_command 'ruby em.rb'
82
+ stdout 'em.log'
83
+ daemonize true
84
+ stop_signals [:QUIT, 2.seconds, :KILL]
85
+
86
+ checks :socket, :addr => "tcp://127.0.0.1:33221", :every => 10.seconds, :times => 2,
87
+ :timeout => 1.second, :send_data => "ping", :expect_data => /pong/
88
+ end
89
+
90
+ # thin process, self daemonized
91
+ process :thin do
92
+ pid_file "thin.pid"
93
+ start_command "bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid"
94
+ stop_signals [:QUIT, 2.seconds, :TERM, 1.seconds, :KILL]
95
+
96
+ checks :http, :url => "http://127.0.0.1:33233/hello", :pattern => /World/, :every => 5.seconds,
97
+ :times => [2, 3], :timeout => 1.second
98
+ end
99
+
100
+ end
101
+ ```
102
+
103
+ ### Start monitoring and load config:
104
+
105
+ $ eye l(oad) examples/test.eye
106
+
107
+ load folder with configs:
108
+
109
+ $ eye l examples/
110
+ $ eye l examples/*.rb
111
+
112
+ Load also uses for config synchronization and load new application into runned eye daemon. Light operation, so i recommend to use with every deploy (and than restart processes).
113
+ (for processes with option `stop_on_delete`, `load` becomes a tool for full config synchronization, which stopps deleted from config processes).
114
+
115
+
116
+ Process statuses:
117
+
118
+ $ eye i(nfo)
119
+
120
+ ```
121
+ test
122
+ samples
123
+ sample1 ....................... up (21:52, 0%, 13Mb, <4107>)
124
+ sample2 ....................... up (21:52, 0%, 12Mb, <4142>)
125
+ event_machine ................... up (21:52, 3%, 26Mb, <4112>)
126
+ forking ......................... up (21:52, 0%, 41Mb, <4203>)
127
+ child-4206 .................... up (21:52, 0%, 41Mb, <4206>)
128
+ child-4211 .................... up (21:52, 0%, 41Mb, <4211>)
129
+ child-4214 .................... up (21:52, 0%, 41Mb, <4214>)
130
+ thin ............................ up (21:53, 2%, 54Mb, <4228>)
131
+ ```
132
+
133
+ ### Commands:
134
+
135
+ start, stop, restart, delete, monitor, unmonitor
136
+
137
+ Command params (with restart for example):
138
+
139
+ $ eye r(estart) all
140
+ $ eye r test
141
+ $ eye r samples
142
+ $ eye r sample1
143
+ $ eye r sample*
144
+ $ eye r test:samples
145
+ $ eye r test:samples:sample1
146
+ $ eye r test:samples:sample*
147
+ $ eye r test:*sample*
148
+
149
+ Check config syntax:
150
+
151
+ $ eye c(heck) examples/test.eye
152
+
153
+ Log tracing:
154
+
155
+ $ eye trace
156
+ $ eye tr test
157
+ $ eye tr sample
158
+
159
+ Quit monitoring:
160
+
161
+ $ eye q(uit)
162
+
163
+ Config explain (for debug):
164
+
165
+ $ eye explain examples/test.eye
166
+
167
+
168
+ ### Config api:
169
+
170
+ Waiting for pull requests ..., until that you can read `examples` and `spec/dsl` folders.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ task :default => :spec
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.verbose = false
8
+ end
9
+
10
+ task :env do
11
+ require 'bundler/setup'
12
+ require 'eye'
13
+ Eye::Control
14
+ Eye::Process # preload
15
+ end
16
+
17
+ desc "graph"
18
+ task :graph => :env do
19
+ StateMachine::Machine.draw("Eye::Process")
20
+ end
data/bin/eye ADDED
@@ -0,0 +1,322 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib]))
3
+ require 'rubygems' if RUBY_VERSION < '1.9'
4
+ require 'eye'
5
+
6
+ gem 'thor'
7
+ require 'thor'
8
+
9
+ class Cli < Thor
10
+
11
+ desc "info [MASK]", "show process statuses"
12
+ def info(mask = nil)
13
+ res = cmd(:info, mask)
14
+ puts res if res && !res.empty?
15
+ puts
16
+ end
17
+
18
+ desc "status ", "show process statuses"
19
+ def status
20
+ say ":status is deprecated, use :info instead", :yellow
21
+ info
22
+ end
23
+
24
+ desc "xinfo", "extended eye info, debug data"
25
+ method_option :config, :type => :boolean, :aliases => "-c"
26
+ method_option :show_processes, :type => :boolean, :aliases => "-p"
27
+ def xinfo
28
+ res = cmd(:xinfo, options[:config], options[:show_processes])
29
+ puts res if res && !res.empty?
30
+ puts
31
+ end
32
+
33
+ desc "oinfo", "onelined info"
34
+ def oinfo
35
+ res = cmd(:oinfo)
36
+ puts res if res && !res.empty?
37
+ puts
38
+ end
39
+
40
+ desc "load [CONF, ...]", "load config (and start server if needed) (-f for foregraund start)"
41
+ method_option :foregraund, :type => :boolean, :aliases => "-f"
42
+ method_option :logger, :type => :string, :aliases => "-l"
43
+ def load(*configs)
44
+ configs.map!{ |c| File.expand_path(c) } if !configs.empty?
45
+
46
+ if options[:foregraund]
47
+ # 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
+
53
+ server_start_foregraund(configs.first)
54
+
55
+ elsif server_started?
56
+ say_load_result cmd(:load, *configs)
57
+
58
+ else
59
+ server_start(configs)
60
+
61
+ end
62
+ end
63
+
64
+ desc "quit", "stop eye monitoring"
65
+ def quit
66
+ res = _cmd(:quit)
67
+
68
+ # if eye server got crazy, stop by force
69
+ ensure_stop_previous_server if res != :corrupred_marshal
70
+
71
+ say "stopped...", :yellow
72
+ end
73
+
74
+ [:start, :stop, :restart, :unmonitor, :monitor, :delete, :match].each do |_cmd|
75
+ desc "#{_cmd} MASK[,...]", "#{_cmd} app,group or process"
76
+ define_method(_cmd) do |*targets|
77
+ send_command(_cmd, *targets)
78
+ end
79
+ end
80
+
81
+ desc "signal SIG, MASK[,...]", "send signal to matched app,group or process (ex: `eye sig USR2 some_app`)"
82
+ def signal(sig, *targets)
83
+ send_command(:signal, sig, *targets)
84
+ end
85
+
86
+ desc "break TARGET[,...]", "break group chain executing"
87
+ def break(*targets)
88
+ send_command(:break_chain, *targets)
89
+ end
90
+
91
+ desc "history TARGET[,...]", "show process states history"
92
+ def history(*targets)
93
+ res = cmd(:history, *targets)
94
+ puts res if res && !res.empty?
95
+ puts
96
+ end
97
+
98
+ desc "trace [TARGET]", "tracing log for app,group or process"
99
+ def trace(target = "")
100
+ log_trace(target)
101
+ end
102
+
103
+ desc "version", "show current version"
104
+ def version
105
+ say Eye::ABOUT
106
+ end
107
+
108
+ desc "check CONF", "check syntax of the config file"
109
+ method_option :host, :type => :string, :aliases => "-h"
110
+ method_option :verbose, :type => :boolean, :aliases => "-v"
111
+ def check(conf)
112
+ conf = File.expand_path(conf) if conf && !conf.empty?
113
+
114
+ Eye::System.host = options[:host] if options[:host]
115
+ Eye::Dsl.verbose = options[:verbose]
116
+
117
+ if RUBY_VERSION < '1.9'
118
+ say_load_result cmd(:check, conf), :syntax => true
119
+ else
120
+ say_load_result Eye::Control.check(conf), :syntax => true
121
+ end
122
+ end
123
+
124
+ desc "explain CONF", "explain config tree (for debug)"
125
+ method_option :host, :type => :string, :aliases => "-h"
126
+ method_option :verbose, :type => :boolean, :aliases => "-v"
127
+ def explain(conf)
128
+ conf = File.expand_path(conf) if conf && !conf.empty?
129
+
130
+ Eye::System.host = options[:host] if options[:host]
131
+ Eye::Dsl.verbose = options[:verbose]
132
+
133
+ if RUBY_VERSION < '1.9'
134
+ say_load_result cmd(:explain, conf), :print_config => true, :syntax => true
135
+ else
136
+ say_load_result Eye::Control.explain(conf), :print_config => true, :syntax => true
137
+ end
138
+ end
139
+
140
+ desc "watch [MASK]", "interactive process info"
141
+ def watch(*args)
142
+ pid = Process.spawn("watch -n 1 --color #{$0} i #{args * ' '}")
143
+ Process.waitpid(pid)
144
+ rescue Interrupt
145
+ end
146
+
147
+ private
148
+
149
+ def client
150
+ @client ||= Eye::Client.new(Eye::Settings.socket_path)
151
+ end
152
+
153
+ def _cmd(cmd, *args)
154
+ client.command(cmd, *args)
155
+ rescue Errno::ECONNREFUSED, Errno::ENOENT
156
+ :not_started
157
+ end
158
+
159
+ def cmd(cmd, *args)
160
+ res = _cmd(cmd, *args)
161
+
162
+ if res == :not_started
163
+ say "eye monitoring not found, did you start it?", :red
164
+ exit 1
165
+ elsif res == :timeouted
166
+ say "eye does not answer, timeouted...", :red
167
+ exit 1
168
+ end
169
+
170
+ res
171
+ end
172
+
173
+ def server_started?
174
+ _cmd(:ping) == :pong
175
+ end
176
+
177
+ def say_load_result(res = {}, opts = {})
178
+ say(res) unless res.is_a?(Hash)
179
+
180
+ if res.has_key?(:error) # TODO: remove that case, outdated
181
+ show_load_message(res, opts)
182
+ exit 1 if res[:error]
183
+ else
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
190
+ end
191
+ end
192
+
193
+ def show_load_message(res, opts = {})
194
+ if res[:error]
195
+ say res[:message], :red
196
+ res[:backtrace].to_a.each{|line| say line, :red }
197
+ else
198
+ all_error = false
199
+ if opts[:syntax]
200
+ say "config ok!", :green if !res[:empty]
201
+ else
202
+ say "config loaded!", :green if !res[:empty]
203
+ end
204
+
205
+ if opts[:print_config]
206
+ require 'pp'
207
+ PP.pp res[:config]
208
+ end
209
+ end
210
+ end
211
+
212
+ def send_command(_cmd, *args)
213
+ res = cmd(_cmd, *args)
214
+ if res == :unknown_command
215
+ say "unknown command :#{_cmd}", :red
216
+ elsif res == :corrupred_marshal
217
+ say "something crazy wrong, check eye logs!", :red
218
+ elsif res == []
219
+ say "command :#{_cmd}, targets not found!", :red
220
+ else
221
+ say "command :#{_cmd} sended to [#{res * ", "}]"
222
+ end
223
+ end
224
+
225
+ def log_trace(tag = '')
226
+ log_file = cmd(:logger_dev)
227
+ if log_file && File.exists?(log_file)
228
+ Process.exec "tail -n 100 -f #{log_file} | grep '#{tag}'"
229
+ else
230
+ say "log file not found #{log_file.inspect}", :red
231
+ end
232
+ end
233
+
234
+ def loader_path
235
+ if RUBY_VERSION < '1.9'
236
+ begin
237
+ return Gem.bin_path('eye', 'loader_eye')
238
+ rescue Gem::GemNotFoundException, Gem::Exception
239
+ end
240
+ end
241
+
242
+ filename = File.expand_path(File.join(File.dirname(__FILE__), %w[loader_eye]))
243
+ File.exists?(filename) ? filename : nil
244
+ end
245
+
246
+ def ruby_path
247
+ require 'rbconfig'
248
+ RbConfig::CONFIG['bindir'] + "/ruby"
249
+ end
250
+
251
+ def ensure_loader_path
252
+ unless loader_path
253
+ say "start monitoring needs to run under ruby with installed gem 'eye'", :red
254
+ exit 1
255
+ end
256
+ end
257
+
258
+ def server_start_foregraund(conf = nil)
259
+ ensure_loader_path
260
+ Eye::Settings.ensure_eye_dir
261
+
262
+ if server_started?
263
+ _cmd(:quit) && sleep(1) # stop previous server
264
+ end
265
+
266
+ args = []
267
+ args += ['-c', conf] if conf
268
+ args += ['-l', 'stdout']
269
+
270
+ Process.exec(ruby_path, loader_path, *args)
271
+ end
272
+
273
+ def server_start(configs)
274
+ ensure_loader_path
275
+ Eye::Settings.ensure_eye_dir
276
+
277
+ ensure_stop_previous_server
278
+
279
+ args = []
280
+ args += ['-l', options[:logger]] if options[:logger]
281
+
282
+ pid = Process.spawn(ruby_path, loader_path, *args, :out => '/dev/null', :err => '/dev/null', :in => '/dev/null',
283
+ :chdir => '/', :pgroup => true)
284
+ Process.detach(pid)
285
+ File.open(Eye::Settings.pid_path, 'w'){|f| f.write(pid) }
286
+
287
+ unless wait_server
288
+ say "server not runned in 15 seconds, something crazy wrong", :red
289
+ exit 1
290
+ end
291
+
292
+ configs.unshift(Eye::Settings.eyeconfig) if File.exists?(Eye::Settings.eyeconfig)
293
+
294
+ if !configs.empty?
295
+ say_load_result cmd(:load, *configs), :started => true
296
+ else
297
+ say "started!", :green
298
+ end
299
+ end
300
+
301
+ def ensure_stop_previous_server
302
+ Eye::Settings.ensure_eye_dir
303
+ pid = File.read(Eye::Settings.pid_path).to_i rescue nil
304
+ if pid
305
+ Process.kill(9, pid) rescue nil
306
+ end
307
+ File.delete(Eye::Settings.pid_path) rescue nil
308
+ true
309
+ end
310
+
311
+ def wait_server(timeout = 15)
312
+ Timeout.timeout(timeout) do
313
+ sleep 0.3 while !server_started?
314
+ end
315
+ true
316
+ rescue Timeout::Error
317
+ false
318
+ end
319
+
320
+ end
321
+
322
+ Cli.start