eye 0.3.2 → 0.4
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 +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -1
- data/.travis.yml +3 -1
- data/CHANGES.md +11 -2
- data/Gemfile +1 -0
- data/README.md +18 -14
- data/Rakefile +10 -3
- data/bin/eye +41 -27
- data/examples/process_thin.rb +1 -1
- data/examples/processes/em.rb +2 -2
- data/examples/processes/forking.rb +2 -2
- data/examples/processes/sample.rb +5 -5
- data/examples/rbenv.eye +1 -1
- data/examples/sidekiq.eye +2 -2
- data/examples/test.eye +10 -6
- data/examples/thin-farm.eye +1 -1
- data/examples/unicorn.eye +1 -1
- data/eye.gemspec +13 -7
- data/lib/eye.rb +6 -6
- data/lib/eye/application.rb +9 -6
- data/lib/eye/checker.rb +51 -21
- data/lib/eye/checker/file_size.rb +1 -1
- data/lib/eye/checker/http.rb +3 -3
- data/lib/eye/checker/memory.rb +1 -1
- data/lib/eye/checker/socket.rb +6 -6
- data/lib/eye/child_process.rb +7 -11
- data/lib/eye/client.rb +6 -6
- data/lib/eye/config.rb +2 -2
- data/lib/eye/controller.rb +11 -8
- data/lib/eye/controller/commands.rb +8 -9
- data/lib/eye/controller/helpers.rb +1 -0
- data/lib/eye/controller/load.rb +11 -7
- data/lib/eye/controller/send_command.rb +44 -19
- data/lib/eye/controller/show_history.rb +8 -7
- data/lib/eye/controller/status.rb +39 -26
- data/lib/eye/dsl.rb +3 -3
- data/lib/eye/dsl/application_opts.rb +4 -4
- data/lib/eye/dsl/config_opts.rb +4 -4
- data/lib/eye/dsl/helpers.rb +2 -2
- data/lib/eye/dsl/main.rb +2 -2
- data/lib/eye/dsl/opts.rb +19 -14
- data/lib/eye/dsl/process_opts.rb +1 -1
- data/lib/eye/dsl/pure_opts.rb +2 -2
- data/lib/eye/dsl/validation.rb +7 -5
- data/lib/eye/group.rb +17 -11
- data/lib/eye/group/chain.rb +3 -3
- data/lib/eye/loader.rb +8 -6
- data/lib/eye/logger.rb +14 -5
- data/lib/eye/notify.rb +13 -7
- data/lib/eye/notify/jabber.rb +2 -2
- data/lib/eye/notify/mail.rb +2 -2
- data/lib/eye/process.rb +10 -13
- data/lib/eye/process/child.rb +1 -1
- data/lib/eye/process/commands.rb +34 -32
- data/lib/eye/process/config.rb +17 -12
- data/lib/eye/process/controller.rb +3 -6
- data/lib/eye/process/data.rb +16 -5
- data/lib/eye/process/monitor.rb +12 -5
- data/lib/eye/process/notify.rb +1 -1
- data/lib/eye/process/scheduler.rb +3 -3
- data/lib/eye/process/states.rb +10 -13
- data/lib/eye/process/states_history.rb +3 -3
- data/lib/eye/process/system.rb +17 -21
- data/lib/eye/process/trigger.rb +11 -30
- data/lib/eye/process/watchers.rb +9 -9
- data/lib/eye/server.rb +14 -6
- data/lib/eye/settings.rb +4 -4
- data/lib/eye/system.rb +10 -7
- data/lib/eye/system_resources.rb +4 -4
- data/lib/eye/trigger.rb +58 -21
- data/lib/eye/trigger/flapping.rb +24 -4
- data/lib/eye/trigger/state.rb +28 -0
- data/lib/eye/utils/alive_array.rb +1 -1
- data/lib/eye/utils/celluloid_klass.rb +5 -0
- data/lib/eye/utils/pmap.rb +7 -0
- data/lib/eye/utils/tail.rb +1 -1
- metadata +39 -23
- data/lib/eye/utils/leak_19.rb +0 -7
data/lib/eye/notify/jabber.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
class Eye::Notify::Jabber < Eye::Notify
|
2
|
-
|
2
|
+
|
3
3
|
# Eye.config do
|
4
4
|
# jabber :host => "some.host", :port => 12345, :user => "eye@some.host", :password => "123456"
|
5
5
|
# contact :vasya, :jabber, "vasya@some.host"
|
6
6
|
# end
|
7
|
-
|
7
|
+
|
8
8
|
param :host, String, true
|
9
9
|
param :port, [String, Fixnum], true
|
10
10
|
param :user, String, true
|
data/lib/eye/notify/mail.rb
CHANGED
@@ -14,10 +14,10 @@ class Eye::Notify::Mail < Eye::Notify
|
|
14
14
|
param :user, String
|
15
15
|
param :password, String
|
16
16
|
param :auth, Symbol, nil, nil, [:plain, :login, :cram_md5]
|
17
|
-
|
17
|
+
|
18
18
|
param :from_mail, String
|
19
19
|
param :from_name, String, nil, 'eye'
|
20
|
-
|
20
|
+
|
21
21
|
def execute
|
22
22
|
smtp
|
23
23
|
end
|
data/lib/eye/process.rb
CHANGED
@@ -2,7 +2,7 @@ require 'celluloid'
|
|
2
2
|
|
3
3
|
class Eye::Process
|
4
4
|
include Celluloid
|
5
|
-
|
5
|
+
|
6
6
|
autoload :Config, 'eye/process/config'
|
7
7
|
autoload :Commands, 'eye/process/commands'
|
8
8
|
autoload :Data, 'eye/process/data'
|
@@ -17,19 +17,19 @@ class Eye::Process
|
|
17
17
|
autoload :Scheduler, 'eye/process/scheduler'
|
18
18
|
autoload :Validate, 'eye/process/validate'
|
19
19
|
|
20
|
-
attr_accessor :pid, :watchers, :config, :states_history,
|
21
|
-
:childs, :triggers, :name, :state_reason
|
22
|
-
|
20
|
+
attr_accessor :pid, :watchers, :config, :states_history,
|
21
|
+
:childs, :triggers, :name, :state_reason, :flapping_times
|
22
|
+
|
23
23
|
def initialize(config)
|
24
24
|
raise 'pid file should be' unless config[:pid_file]
|
25
25
|
|
26
26
|
@config = prepare_config(config)
|
27
|
-
@logger = Eye::Logger.new(full_name)
|
28
27
|
|
29
28
|
@watchers = {}
|
30
29
|
@childs = {}
|
31
30
|
@triggers = []
|
32
31
|
@name = @config[:name]
|
32
|
+
@flapping_times = 0
|
33
33
|
|
34
34
|
@states_history = Eye::Process::StatesHistory.new(100)
|
35
35
|
@states_history << :unmonitored
|
@@ -41,22 +41,22 @@ class Eye::Process
|
|
41
41
|
super() # for statemachine
|
42
42
|
end
|
43
43
|
|
44
|
-
# c(), self[]
|
44
|
+
# c(), self[]
|
45
45
|
include Eye::Process::Config
|
46
|
-
|
46
|
+
|
47
47
|
# full_name, status_data
|
48
48
|
include Eye::Process::Data
|
49
|
-
|
49
|
+
|
50
50
|
# commands:
|
51
51
|
# start_process, stop_process, restart_process
|
52
52
|
include Eye::Process::Commands
|
53
53
|
|
54
54
|
# start, stop, restart, monitor, unmonit, delete
|
55
55
|
include Eye::Process::Controller
|
56
|
-
|
56
|
+
|
57
57
|
# add_watchers, remove_watchers:
|
58
58
|
include Eye::Process::Watchers
|
59
|
-
|
59
|
+
|
60
60
|
# check alive, crash methods:
|
61
61
|
include Eye::Process::Monitor
|
62
62
|
|
@@ -72,9 +72,6 @@ class Eye::Process
|
|
72
72
|
# manage notify methods
|
73
73
|
include Eye::Process::Notify
|
74
74
|
|
75
|
-
# logger methods
|
76
|
-
include Eye::Logger::Helpers
|
77
|
-
|
78
75
|
# scheduler
|
79
76
|
include Eye::Process::Scheduler
|
80
77
|
|
data/lib/eye/process/child.rb
CHANGED
data/lib/eye/process/commands.rb
CHANGED
@@ -7,7 +7,7 @@ module Eye::Process::Commands
|
|
7
7
|
|
8
8
|
unless self[:start_command]
|
9
9
|
warn 'no start command, so unmonitoring'
|
10
|
-
switch :unmonitoring
|
10
|
+
switch :unmonitoring, Eye::Reason.new(:no_start_command)
|
11
11
|
return :no_start_command
|
12
12
|
end
|
13
13
|
|
@@ -35,7 +35,7 @@ module Eye::Process::Commands
|
|
35
35
|
|
36
36
|
:state_error
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def stop_process
|
40
40
|
debug 'stop_process command'
|
41
41
|
|
@@ -46,19 +46,15 @@ module Eye::Process::Commands
|
|
46
46
|
if process_realy_running?
|
47
47
|
warn 'NOT STOPPED, check command/signals, or tune stop_timeout/stop_grace, seems it was really soft'
|
48
48
|
|
49
|
-
switch :unmonitoring
|
49
|
+
switch :unmonitoring, Eye::Reason.new(:'not stopped (soft command)')
|
50
50
|
nil
|
51
51
|
|
52
52
|
else
|
53
53
|
switch :stopped
|
54
54
|
|
55
|
-
if
|
56
|
-
info "delete pid_file: #{self[:pid_file_ex]}"
|
57
|
-
clear_pid_file
|
58
|
-
end
|
59
|
-
|
60
|
-
true
|
55
|
+
clear_pid_file if self[:clear_pid] # by default for all
|
61
56
|
|
57
|
+
true
|
62
58
|
end
|
63
59
|
|
64
60
|
rescue StateMachine::InvalidTransition => e
|
@@ -73,7 +69,7 @@ module Eye::Process::Commands
|
|
73
69
|
|
74
70
|
if self[:restart_command]
|
75
71
|
execute_restart_command
|
76
|
-
|
72
|
+
sleep_grace(:restart_grace)
|
77
73
|
result = check_alive_with_refresh_pid_if_needed
|
78
74
|
switch(result ? :restarted : :crashed)
|
79
75
|
else
|
@@ -106,7 +102,7 @@ private
|
|
106
102
|
end
|
107
103
|
end
|
108
104
|
|
109
|
-
|
105
|
+
sleep_grace(:stop_grace)
|
110
106
|
|
111
107
|
elsif self[:stop_signals]
|
112
108
|
info "executing stop_signals #{self[:stop_signals].inspect}"
|
@@ -119,7 +115,7 @@ private
|
|
119
115
|
delay = stop_signals.shift
|
120
116
|
signal = stop_signals.shift
|
121
117
|
|
122
|
-
if wait_for_condition(delay.to_f, 0.
|
118
|
+
if wait_for_condition(delay.to_f, 0.3){ !process_realy_running? }
|
123
119
|
info 'has terminated'
|
124
120
|
break
|
125
121
|
end
|
@@ -127,17 +123,17 @@ private
|
|
127
123
|
send_signal(signal)
|
128
124
|
end
|
129
125
|
|
130
|
-
|
126
|
+
sleep_grace(:stop_grace)
|
131
127
|
|
132
128
|
else # default command
|
133
|
-
|
129
|
+
debug "executing: `kill -TERM #{self.pid}` with stop_grace: #{self[:stop_grace].to_f}s"
|
134
130
|
send_signal(:TERM)
|
135
|
-
|
136
|
-
|
131
|
+
|
132
|
+
sleep_grace(:stop_grace)
|
137
133
|
|
138
134
|
# if process not die here, by default we force kill it
|
139
135
|
if process_realy_running?
|
140
|
-
warn "process not die after TERM and stop_grace #{self[:stop_grace].to_f}s, so send KILL"
|
136
|
+
warn "process not die after TERM and stop_grace #{self[:stop_grace].to_f}s, so send KILL(#{self.pid})"
|
141
137
|
send_signal(:KILL)
|
142
138
|
sleep 0.1 # little grace
|
143
139
|
end
|
@@ -160,7 +156,7 @@ private
|
|
160
156
|
|
161
157
|
res
|
162
158
|
end
|
163
|
-
|
159
|
+
|
164
160
|
def daemonize_process
|
165
161
|
time_before = Time.now
|
166
162
|
res = Eye::System.daemonize(self[:start_command], config)
|
@@ -169,15 +165,15 @@ private
|
|
169
165
|
info "daemonizing: `#{self[:start_command]}` with start_grace: #{self[:start_grace].to_f}s, env: #{self[:environment].inspect}, working_dir: #{self[:working_dir]} (pid:#{res[:pid]})"
|
170
166
|
|
171
167
|
if res[:error]
|
172
|
-
error "raised with #{res[:error].inspect}"
|
173
|
-
|
174
168
|
if res[:error].message == 'Permission denied - open'
|
175
|
-
error
|
169
|
+
error "raised with #{res[:error].inspect}, seems #{[self[:stdout], self[:stderr]]} files are not writable"
|
170
|
+
else
|
171
|
+
error "raised with #{res[:error].inspect}"
|
176
172
|
end
|
177
173
|
|
178
174
|
return {:error => res[:error].inspect}
|
179
175
|
end
|
180
|
-
|
176
|
+
|
181
177
|
self.pid = res[:pid]
|
182
178
|
|
183
179
|
unless self.pid
|
@@ -185,7 +181,7 @@ private
|
|
185
181
|
return {:error => :empty_pid}
|
186
182
|
end
|
187
183
|
|
188
|
-
|
184
|
+
sleep_grace(:start_grace)
|
189
185
|
|
190
186
|
unless process_realy_running?
|
191
187
|
error "process with pid(#{self.pid}) not found, may be crashed (#{check_logs_str})"
|
@@ -193,9 +189,9 @@ private
|
|
193
189
|
end
|
194
190
|
|
195
191
|
unless failsafe_save_pid
|
196
|
-
return {:error => :cant_write_pid}
|
192
|
+
return {:error => :cant_write_pid}
|
197
193
|
end
|
198
|
-
|
194
|
+
|
199
195
|
res
|
200
196
|
end
|
201
197
|
|
@@ -204,13 +200,13 @@ private
|
|
204
200
|
time_before = Time.now
|
205
201
|
|
206
202
|
res = execute(self[:start_command], config.merge(:timeout => config[:start_timeout]))
|
207
|
-
start_time = Time.now - time_before
|
203
|
+
start_time = Time.now - time_before
|
208
204
|
|
209
205
|
if res[:error]
|
210
|
-
error "raised with #{res[:error].inspect}"
|
211
|
-
|
212
206
|
if res[:error].message == 'Permission denied - open'
|
213
|
-
error
|
207
|
+
error "raised with #{res[:error].inspect}, seems #{[self[:stdout], self[:stderr]]} files are not writable"
|
208
|
+
else
|
209
|
+
error "raised with #{res[:error].inspect}"
|
214
210
|
end
|
215
211
|
|
216
212
|
if res[:error].class == Timeout::Error
|
@@ -220,7 +216,7 @@ private
|
|
220
216
|
return {:error => res[:error].inspect}
|
221
217
|
end
|
222
218
|
|
223
|
-
|
219
|
+
sleep_grace(:start_grace)
|
224
220
|
|
225
221
|
unless set_pid_from_file
|
226
222
|
error "pid_file(#{self[:pid_file_ex]}) does not appears after start_grace #{self[:start_grace].to_f}, check start_command, or tune start_grace (eye dont know what to monitor without pid)"
|
@@ -241,8 +237,8 @@ private
|
|
241
237
|
if !self[:stdout] && !self[:stderr]
|
242
238
|
'maybe should add stdout/err/all logs'
|
243
239
|
else
|
244
|
-
"check also it stdout/err/all logs #{[self[:stdout], self[:stderr]]
|
245
|
-
end
|
240
|
+
"check also it stdout/err/all logs #{[self[:stdout], self[:stderr]]}"
|
241
|
+
end
|
246
242
|
end
|
247
243
|
|
248
244
|
def prepare_command(command)
|
@@ -253,4 +249,10 @@ private
|
|
253
249
|
end
|
254
250
|
end
|
255
251
|
|
252
|
+
def sleep_grace(grace_name)
|
253
|
+
grace = self[grace_name].to_f
|
254
|
+
info "sleeping for :#{grace_name} #{grace}"
|
255
|
+
sleep grace
|
256
|
+
end
|
257
|
+
|
256
258
|
end
|
data/lib/eye/process/config.rb
CHANGED
@@ -8,14 +8,15 @@ module Eye::Process::Config
|
|
8
8
|
:stop_timeout => 10.seconds,
|
9
9
|
:restart_timeout => 10.seconds,
|
10
10
|
|
11
|
-
:start_grace => 2.5.seconds,
|
12
|
-
:stop_grace => 0.5.seconds,
|
13
|
-
:restart_grace =>
|
11
|
+
:start_grace => 2.5.seconds,
|
12
|
+
:stop_grace => 0.5.seconds,
|
13
|
+
:restart_grace => 1.second,
|
14
14
|
|
15
15
|
:daemonize => false,
|
16
16
|
:auto_start => true, # auto start on monitor action
|
17
17
|
|
18
|
-
:childs_update_period => 30.seconds
|
18
|
+
:childs_update_period => 30.seconds,
|
19
|
+
:clear_pid => true # by default clear pid on stop
|
19
20
|
}
|
20
21
|
|
21
22
|
def prepare_config(new_config)
|
@@ -30,25 +31,26 @@ module Eye::Process::Config
|
|
30
31
|
h[:triggers] ||= {}
|
31
32
|
h[:triggers][:flapping] = {:type => :flapping, :times => 10, :within => 10.seconds}
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
h[:stdout] = Eye::System.normalized_file(h[:stdout], h[:working_dir]) if h[:stdout]
|
35
36
|
h[:stderr] = Eye::System.normalized_file(h[:stderr], h[:working_dir]) if h[:stderr]
|
36
37
|
|
37
|
-
h
|
38
|
+
h
|
38
39
|
end
|
39
40
|
|
40
41
|
def c(name)
|
41
42
|
@config[name]
|
42
43
|
end
|
43
|
-
|
44
|
+
|
44
45
|
def [](name)
|
45
46
|
@config[name]
|
46
47
|
end
|
47
|
-
|
48
|
+
|
48
49
|
def update_config(new_config = {})
|
49
50
|
new_config = prepare_config(new_config)
|
50
51
|
@config = new_config
|
51
52
|
@full_name = nil
|
53
|
+
@logger = nil
|
52
54
|
|
53
55
|
debug "update config to: #{@config.inspect}"
|
54
56
|
|
@@ -57,14 +59,17 @@ module Eye::Process::Config
|
|
57
59
|
|
58
60
|
if up?
|
59
61
|
# rebuild checks for this process
|
60
|
-
|
61
|
-
|
62
|
+
remove_watchers
|
63
|
+
remove_childs
|
64
|
+
|
65
|
+
add_watchers
|
66
|
+
add_childs
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
70
|
# is pid_file under Eye::Process control, or not
|
65
71
|
def control_pid?
|
66
|
-
return self[:control_pid] unless self[:control_pid].nil?
|
67
72
|
!!self[:daemonize]
|
68
73
|
end
|
69
|
-
|
74
|
+
|
70
75
|
end
|
@@ -52,7 +52,7 @@ module Eye::Process::Controller
|
|
52
52
|
def unmonitor
|
53
53
|
switch :unmonitoring
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def delete
|
57
57
|
if self[:stop_on_delete]
|
58
58
|
info 'process has stop_on_delete option, so sync-stop it first'
|
@@ -67,10 +67,7 @@ module Eye::Process::Controller
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def signal(sig = 0)
|
70
|
-
if self.pid
|
71
|
-
res = send_signal(sig)
|
72
|
-
info "send signal #{sig} to #{self.pid} = #{res}"
|
73
|
-
end
|
70
|
+
send_signal(sig) if self.pid
|
74
71
|
end
|
75
|
-
|
72
|
+
|
76
73
|
end
|
data/lib/eye/process/data.rb
CHANGED
@@ -1,8 +1,19 @@
|
|
1
1
|
module Eye::Process::Data
|
2
2
|
|
3
|
-
|
3
|
+
def logger_tag
|
4
|
+
full_name
|
5
|
+
end
|
6
|
+
|
7
|
+
def app_name
|
8
|
+
self[:application]
|
9
|
+
end
|
10
|
+
|
11
|
+
def group_name
|
12
|
+
(self[:group] == '__default__') ? nil : self[:group]
|
13
|
+
end
|
14
|
+
|
4
15
|
def full_name
|
5
|
-
@full_name ||= [
|
16
|
+
@full_name ||= [app_name, group_name, self[:name]].compact.join(':')
|
6
17
|
end
|
7
18
|
|
8
19
|
def status_data(debug = false)
|
@@ -19,8 +30,8 @@ module Eye::Process::Data
|
|
19
30
|
end
|
20
31
|
|
21
32
|
def self_status_data(debug = false)
|
22
|
-
h = { name: name, state: state,
|
23
|
-
type: (self.class == Eye::ChildProcess ? :child_process : :process),
|
33
|
+
h = { name: name, state: state,
|
34
|
+
type: (self.class == Eye::ChildProcess ? :child_process : :process),
|
24
35
|
resources: Eye::SystemResources.resources(pid) }
|
25
36
|
|
26
37
|
if @states_history
|
@@ -31,7 +42,7 @@ module Eye::Process::Data
|
|
31
42
|
h.merge!(debug: debug_data) if debug
|
32
43
|
h.merge!(current_command: current_scheduled_command) if current_scheduled_command
|
33
44
|
|
34
|
-
h
|
45
|
+
h
|
35
46
|
end
|
36
47
|
|
37
48
|
def debug_data
|
data/lib/eye/process/monitor.rb
CHANGED
@@ -15,7 +15,7 @@ private
|
|
15
15
|
def try_update_pid_from_file
|
16
16
|
# if pid file was rewrited
|
17
17
|
newpid = load_pid_from_file
|
18
|
-
if newpid != self.pid
|
18
|
+
if newpid != self.pid
|
19
19
|
info "process changed pid to #{newpid}, updating..." if self.pid
|
20
20
|
self.pid = newpid
|
21
21
|
|
@@ -23,7 +23,7 @@ private
|
|
23
23
|
return true
|
24
24
|
else
|
25
25
|
warn "process with new_pid #{newpid} not found"
|
26
|
-
return false
|
26
|
+
return false
|
27
27
|
end
|
28
28
|
else
|
29
29
|
debug 'process not found'
|
@@ -32,7 +32,7 @@ private
|
|
32
32
|
end
|
33
33
|
|
34
34
|
REWRITE_FACKUP_PIDFILE_PERIOD = 2.minutes
|
35
|
-
|
35
|
+
|
36
36
|
def check_alive
|
37
37
|
if up?
|
38
38
|
|
@@ -40,11 +40,13 @@ private
|
|
40
40
|
unless process_realy_running?
|
41
41
|
warn "check_alive: process(#{self.pid}) not found!"
|
42
42
|
notify :info, 'crashed!'
|
43
|
+
clear_pid_file if control_pid? && self.pid && load_pid_from_file == self.pid
|
44
|
+
|
43
45
|
switch :crashed, Eye::Reason.new(:crashed)
|
44
46
|
else
|
45
47
|
# check that pid_file still here
|
46
48
|
ppid = failsafe_load_pid
|
47
|
-
|
49
|
+
|
48
50
|
if ppid != self.pid
|
49
51
|
msg = "check_alive: pid_file(#{self[:pid_file]}) changes by itself (pid:#{self.pid}) => (pid:#{ppid})"
|
50
52
|
if control_pid?
|
@@ -78,7 +80,12 @@ private
|
|
78
80
|
if down?
|
79
81
|
if self[:keep_alive]
|
80
82
|
warn 'check crashed: process is down'
|
81
|
-
|
83
|
+
|
84
|
+
if self[:restore_in]
|
85
|
+
schedule_in self[:restore_in].to_f, :restore, Eye::Reason.new(:crashed)
|
86
|
+
else
|
87
|
+
schedule :restore, Eye::Reason.new(:crashed)
|
88
|
+
end
|
82
89
|
else
|
83
90
|
warn 'check crashed: process without keep_alive'
|
84
91
|
schedule :unmonitor, Eye::Reason.new(:crashed)
|