eye 0.7 → 0.8.celluloid15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +141 -0
- data/.travis.yml +5 -3
- data/CHANGES.md +9 -1
- data/README.md +5 -2
- data/Rakefile +6 -6
- data/bin/leye +9 -4
- data/bin/loader_eye +14 -15
- data/examples/custom_check.eye +24 -0
- data/examples/custom_trigger.eye +30 -0
- data/examples/delayed_job.eye +3 -3
- data/examples/dependency.eye +10 -11
- data/examples/leye_example/Eyefile +10 -0
- data/examples/notify.eye +3 -4
- data/examples/plugin/main.eye +5 -5
- data/examples/plugin/plugin.rb +10 -2
- data/examples/process_thin.rb +8 -8
- data/examples/processes/em.rb +18 -12
- data/examples/processes/forking.rb +5 -5
- data/examples/processes/sample.rb +46 -44
- data/examples/puma.eye +9 -8
- data/examples/rbenv.eye +5 -5
- data/examples/sidekiq.eye +3 -3
- data/examples/stress_test.eye +4 -4
- data/examples/syslog.eye +1 -1
- data/examples/test.eye +1 -2
- data/examples/thin-farm.eye +7 -8
- data/examples/triggers.eye +13 -15
- data/examples/unicorn.eye +12 -13
- data/eye.gemspec +16 -14
- data/lib/eye.rb +2 -3
- data/lib/eye/application.rb +5 -6
- data/lib/eye/checker.rb +44 -25
- data/lib/eye/checker/children_count.rb +1 -1
- data/lib/eye/checker/file_ctime.rb +1 -1
- data/lib/eye/checker/http.rb +13 -15
- data/lib/eye/checker/nop.rb +1 -0
- data/lib/eye/checker/socket.rb +60 -63
- data/lib/eye/checker/ssl_socket.rb +5 -5
- data/lib/eye/child_process.rb +6 -4
- data/lib/eye/cli.rb +74 -46
- data/lib/eye/cli/commands.rb +4 -5
- data/lib/eye/cli/render.rb +61 -41
- data/lib/eye/cli/server.rb +19 -16
- data/lib/eye/client.rb +1 -0
- data/lib/eye/config.rb +36 -33
- data/lib/eye/controller.rb +2 -3
- data/lib/eye/controller/commands.rb +1 -1
- data/lib/eye/controller/helpers.rb +2 -2
- data/lib/eye/controller/load.rb +19 -17
- data/lib/eye/controller/options.rb +1 -5
- data/lib/eye/controller/send_command.rb +21 -23
- data/lib/eye/controller/status.rb +17 -14
- data/lib/eye/dsl.rb +6 -1
- data/lib/eye/dsl/application_opts.rb +4 -3
- data/lib/eye/dsl/chain.rb +2 -2
- data/lib/eye/dsl/child_process_opts.rb +3 -3
- data/lib/eye/dsl/config_opts.rb +7 -7
- data/lib/eye/dsl/group_opts.rb +3 -3
- data/lib/eye/dsl/helpers.rb +1 -1
- data/lib/eye/dsl/main.rb +4 -3
- data/lib/eye/dsl/opts.rb +31 -28
- data/lib/eye/dsl/process_opts.rb +13 -7
- data/lib/eye/dsl/pure_opts.rb +13 -9
- data/lib/eye/dsl/validation.rb +48 -35
- data/lib/eye/group.rb +23 -8
- data/lib/eye/group/chain.rb +6 -6
- data/lib/eye/loader.rb +3 -3
- data/lib/eye/local.rb +9 -4
- data/lib/eye/logger.rb +11 -4
- data/lib/eye/notify.rb +10 -6
- data/lib/eye/notify/jabber.rb +1 -1
- data/lib/eye/notify/mail.rb +2 -2
- data/lib/eye/notify/slack.rb +4 -3
- data/lib/eye/process.rb +2 -0
- data/lib/eye/process/children.rb +4 -4
- data/lib/eye/process/commands.rb +38 -39
- data/lib/eye/process/config.rb +22 -16
- data/lib/eye/process/controller.rb +5 -19
- data/lib/eye/process/data.rb +11 -9
- data/lib/eye/process/monitor.rb +86 -76
- data/lib/eye/process/notify.rb +10 -10
- data/lib/eye/process/scheduler.rb +36 -31
- data/lib/eye/process/states.rb +7 -5
- data/lib/eye/process/states_history.rb +9 -3
- data/lib/eye/process/system.rb +35 -20
- data/lib/eye/process/trigger.rb +1 -5
- data/lib/eye/process/watchers.rb +12 -9
- data/lib/eye/reason.rb +4 -1
- data/lib/eye/server.rb +3 -2
- data/lib/eye/system.rb +22 -15
- data/lib/eye/system_resources.rb +17 -8
- data/lib/eye/trigger.rb +18 -16
- data/lib/eye/trigger/check_dependency.rb +7 -4
- data/lib/eye/trigger/flapping.rb +24 -7
- data/lib/eye/trigger/starting_guard.rb +7 -6
- data/lib/eye/trigger/stop_children.rb +2 -2
- data/lib/eye/trigger/transition.rb +1 -1
- data/lib/eye/trigger/wait_dependency.rb +3 -2
- data/lib/eye/utils.rb +4 -3
- data/lib/eye/utils/alive_array.rb +9 -4
- data/lib/eye/utils/celluloid_chain.rb +12 -10
- data/lib/eye/utils/mini_active_support.rb +16 -16
- data/lib/eye/utils/pmap.rb +2 -0
- data/lib/eye/utils/tail.rb +2 -2
- metadata +39 -8
- data/lib/eye/utils/leak_19.rb +0 -10
data/lib/eye/process/data.rb
CHANGED
@@ -20,30 +20,32 @@ module Eye::Process::Data
|
|
20
20
|
@full_name ||= [app_name, group_name, self[:name]].compact.join(':')
|
21
21
|
end
|
22
22
|
|
23
|
-
def status_data(
|
24
|
-
p_st = self_status_data(
|
23
|
+
def status_data(opts = {})
|
24
|
+
p_st = self_status_data(opts)
|
25
25
|
|
26
26
|
if children.present?
|
27
|
-
p_st.merge(:
|
27
|
+
p_st.merge(subtree: Eye::Utils::AliveArray.new(children.values).map { |c| c.status_data(opts) })
|
28
28
|
elsif self[:monitor_children] && self.up?
|
29
|
-
p_st.merge(:
|
29
|
+
p_st.merge(subtree: [{ name: '=loading children=' }])
|
30
30
|
else
|
31
31
|
# common state
|
32
32
|
p_st
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def self_status_data(
|
37
|
-
h = { name: name,
|
36
|
+
def self_status_data(opts)
|
37
|
+
h = { name: name,
|
38
|
+
state: state,
|
38
39
|
type: (self.class == Eye::ChildProcess ? :child_process : :process),
|
39
40
|
resources: Eye::SystemResources.resources(pid) }
|
40
41
|
|
41
42
|
if @states_history
|
42
|
-
h
|
43
|
-
|
43
|
+
h[:state_changed_at] = @states_history.last_state_changed_at.to_i
|
44
|
+
h[:state_reason] = @states_history.last_reason.to_s
|
44
45
|
end
|
45
46
|
|
46
|
-
h[:debug] = debug_data if debug
|
47
|
+
h[:debug] = debug_data if opts[:debug]
|
48
|
+
h[:procline] = Eye::SystemResources.args(self.pid) if opts[:procline]
|
47
49
|
h[:current_command] = current_scheduled_command if current_scheduled_command
|
48
50
|
|
49
51
|
h
|
data/lib/eye/process/monitor.rb
CHANGED
@@ -2,102 +2,112 @@ module Eye::Process::Monitor
|
|
2
2
|
|
3
3
|
private
|
4
4
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def load_external_pid_file
|
6
|
+
newpid = failsafe_load_pid
|
7
|
+
|
8
|
+
if !newpid
|
9
|
+
self.pid = nil
|
10
|
+
info 'load_external_pid_file: pid_file not found'
|
11
|
+
:no_pid_file
|
12
|
+
elsif process_pid_running?(newpid)
|
13
|
+
self.pid = newpid
|
14
|
+
res = compare_identity
|
15
|
+
if res == :fail
|
16
|
+
warn "load_external_pid_file: process <#{self.pid}> from pid_file failed check_identity"
|
17
|
+
:bad_identity
|
18
|
+
else
|
19
|
+
args = Eye::SystemResources.args(self.pid)
|
20
|
+
info "load_external_pid_file: process <#{self.pid}> from pid_file found and running (identity: #{res}) (#{args})"
|
21
|
+
:ok
|
22
|
+
end
|
9
23
|
else
|
10
|
-
|
11
|
-
|
24
|
+
@last_loaded_pid = newpid
|
25
|
+
self.pid = nil
|
26
|
+
info "load_external_pid_file: pid_file found, but process <#{newpid}> not found"
|
27
|
+
:not_running
|
12
28
|
end
|
13
29
|
end
|
14
30
|
|
15
|
-
def
|
16
|
-
|
17
|
-
newpid = load_pid_from_file
|
18
|
-
if newpid != self.pid
|
19
|
-
info "process <#{self.pid}> changed pid to <#{newpid}>, updating..." if self.pid
|
20
|
-
self.pid = newpid
|
31
|
+
def check_alive
|
32
|
+
return unless up?
|
21
33
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
warn "process <#{newpid}> was not found"
|
26
|
-
return false
|
27
|
-
end
|
34
|
+
# check that process runned
|
35
|
+
if process_really_running?
|
36
|
+
check_pid_file
|
28
37
|
else
|
29
|
-
|
30
|
-
|
38
|
+
warn "check_alive: process <#{self.pid}> not found"
|
39
|
+
notify :info, 'crashed!'
|
40
|
+
clear_pid_file(true) if control_pid?
|
41
|
+
|
42
|
+
switch :crashed, Eye::Reason.new(:crashed)
|
31
43
|
end
|
32
44
|
end
|
33
45
|
|
34
|
-
def
|
35
|
-
|
46
|
+
def check_pid_file
|
47
|
+
ppid = failsafe_load_pid
|
48
|
+
return if ppid == self.pid
|
36
49
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
50
|
+
msg = "check_alive: pid_file (#{self[:pid_file]}) changed by itself (<#{self.pid}> => <#{ppid}>)"
|
51
|
+
if control_pid?
|
52
|
+
msg += ", reverting to <#{self.pid}> (the pid_file is controlled by eye)"
|
53
|
+
unless failsafe_save_pid
|
54
|
+
msg += ', pid_file write failed! O_o'
|
55
|
+
end
|
56
|
+
else
|
57
|
+
changed_ago_s = Time.now - pid_file_ctime
|
42
58
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if ppid != self.pid
|
49
|
-
msg = "check_alive: pid_file (#{self[:pid_file]}) changed by itself (<#{self.pid}> => <#{ppid}>)"
|
50
|
-
if control_pid?
|
51
|
-
msg += ", reverting to <#{self.pid}> (the pid_file is controlled by eye)"
|
52
|
-
unless failsafe_save_pid
|
53
|
-
msg += ", pid_file write failed! O_o"
|
54
|
-
end
|
55
|
-
else
|
56
|
-
changed_ago_s = Time.now - pid_file_ctime
|
57
|
-
|
58
|
-
if ppid == nil
|
59
|
-
msg += ", reverting to <#{self.pid}> (the pid_file is empty)"
|
60
|
-
unless failsafe_save_pid
|
61
|
-
msg += ", pid_file write failed! O_o"
|
62
|
-
end
|
63
|
-
|
64
|
-
elsif (changed_ago_s > self[:auto_update_pidfile_grace]) && process_pid_running?(ppid)
|
65
|
-
msg += ", trusting this change, and now monitor <#{ppid}>"
|
66
|
-
self.pid = ppid
|
67
|
-
|
68
|
-
elsif (changed_ago_s > self[:revert_fuckup_pidfile_grace])
|
69
|
-
msg += " over #{self[:revert_fuckup_pidfile_grace]}s ago, reverting to <#{self.pid}>, because <#{ppid}> not alive"
|
70
|
-
unless failsafe_save_pid
|
71
|
-
msg += ", pid_file write failed! O_o"
|
72
|
-
end
|
73
|
-
|
74
|
-
else
|
75
|
-
msg += ', ignoring self-managed pid change'
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
warn msg
|
59
|
+
if !ppid
|
60
|
+
msg += ", reverting to <#{self.pid}> (the pid_file is empty)"
|
61
|
+
unless failsafe_save_pid
|
62
|
+
msg += ', pid_file write failed! O_o'
|
80
63
|
end
|
64
|
+
|
65
|
+
elsif (changed_ago_s > self[:auto_update_pidfile_grace]) && process_pid_running?(ppid) && (compare_identity(ppid) != :fail)
|
66
|
+
msg += ", trusting this change, and now monitor <#{ppid}>"
|
67
|
+
self.pid = ppid
|
68
|
+
|
69
|
+
elsif changed_ago_s > self[:revert_fuckup_pidfile_grace]
|
70
|
+
msg += " over #{self[:revert_fuckup_pidfile_grace]}s ago, reverting to <#{self.pid}>, because <#{ppid}> not alive"
|
71
|
+
unless failsafe_save_pid
|
72
|
+
msg += ', pid_file write failed! O_o'
|
73
|
+
end
|
74
|
+
|
75
|
+
else
|
76
|
+
msg += ', ignoring self-managed pid change'
|
81
77
|
end
|
82
78
|
end
|
79
|
+
|
80
|
+
warn msg
|
81
|
+
end
|
82
|
+
|
83
|
+
def check_identity
|
84
|
+
if compare_identity == :fail
|
85
|
+
notify :info, 'crashed by identity!'
|
86
|
+
switch :crashed, Eye::Reason.new(:crashed_by_identity)
|
87
|
+
clear_pid_file if self[:clear_pid]
|
88
|
+
false
|
89
|
+
else
|
90
|
+
true
|
91
|
+
end
|
83
92
|
end
|
84
93
|
|
85
94
|
def check_crash
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
+
unless down?
|
96
|
+
debug { 'check crashed: skipped, process is not in down' }
|
97
|
+
return
|
98
|
+
end
|
99
|
+
|
100
|
+
if self[:keep_alive]
|
101
|
+
warn 'check crashed: process is down'
|
102
|
+
|
103
|
+
if self[:restore_in]
|
104
|
+
schedule_in self[:restore_in].to_f, :restore, Eye::Reason.new(:crashed)
|
95
105
|
else
|
96
|
-
|
97
|
-
schedule :unmonitor, Eye::Reason.new(:crashed)
|
106
|
+
schedule :restore, Eye::Reason.new(:crashed)
|
98
107
|
end
|
99
108
|
else
|
100
|
-
|
109
|
+
warn 'check crashed: process without keep_alive'
|
110
|
+
schedule :unmonitor, Eye::Reason.new(:crashed)
|
101
111
|
end
|
102
112
|
end
|
103
113
|
|
data/lib/eye/process/notify.rb
CHANGED
@@ -5,21 +5,21 @@ module Eye::Process::Notify
|
|
5
5
|
# 2) checker bounded to restart process [:warn]
|
6
6
|
# 3) flapping + switch to unmonitored [:error]
|
7
7
|
|
8
|
-
LEVELS = {:
|
8
|
+
LEVELS = { debug: 0, info: 1, warn: 2, error: 3, fatal: 4 }
|
9
9
|
|
10
10
|
def notify(level, msg)
|
11
11
|
# logging it
|
12
12
|
error "NOTIFY: #{msg}" if ilevel(level) > ilevel(:info)
|
13
13
|
|
14
|
+
return if self[:notify].blank?
|
15
|
+
|
14
16
|
# send notifies
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
Eye::Notify.notify(contact, message) if ilevel(level) >= ilevel(not_level)
|
22
|
-
end
|
17
|
+
message = { message: msg, name: name,
|
18
|
+
full_name: full_name, pid: pid, host: Eye::Local.host, level: level,
|
19
|
+
at: Time.now }
|
20
|
+
|
21
|
+
self[:notify].each do |contact, not_level|
|
22
|
+
Eye::Notify.notify(contact, message) if ilevel(level) >= ilevel(not_level)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -29,4 +29,4 @@ private
|
|
29
29
|
LEVELS[level].to_i
|
30
30
|
end
|
31
31
|
|
32
|
-
end
|
32
|
+
end
|
@@ -2,32 +2,30 @@ module Eye::Process::Scheduler
|
|
2
2
|
|
3
3
|
# ex: schedule :update_config, config, "reason: update_config"
|
4
4
|
def schedule(command, *args, &block)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
scheduler.add_wo_dups(:scheduled_action, command, {:args => args, :reason => reason}, &block)
|
30
|
-
end
|
5
|
+
return unless scheduler.alive?
|
6
|
+
|
7
|
+
if scheduler_freeze?
|
8
|
+
warn ":#{command} ignoring to schedule, because scheduler is freeze"
|
9
|
+
return
|
10
|
+
end
|
11
|
+
|
12
|
+
unless self.respond_to?(command, true)
|
13
|
+
warn ":#{command} scheduling is unsupported"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
reason = args.pop if args.present? && args[-1].is_a?(Eye::Reason)
|
18
|
+
|
19
|
+
info "schedule :#{command} #{reason ? "(reason: #{reason})" : nil}"
|
20
|
+
|
21
|
+
if reason.class == Eye::Reason
|
22
|
+
# for auto reasons
|
23
|
+
# skip already running commands and all in chain
|
24
|
+
scheduler.add_wo_dups_current(:scheduled_action, command, args: args, reason: reason, block: block)
|
25
|
+
else
|
26
|
+
# for manual, or without reason
|
27
|
+
# skip only for last in chain
|
28
|
+
scheduler.add_wo_dups(:scheduled_action, command, args: args, reason: reason, block: block)
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
@@ -39,16 +37,16 @@ module Eye::Process::Scheduler
|
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
42
|
-
def scheduled_action(command, h = {}
|
43
|
-
reason = h
|
44
|
-
info "=> #{command} #{h[:args].present? ? "#{h[:args]*','
|
40
|
+
def scheduled_action(command, h = {})
|
41
|
+
reason = h[:reason]
|
42
|
+
info "=> #{command} #{h[:args].present? ? "#{h[:args] * ','}" : nil} #{reason ? "(reason: #{reason})" : nil}"
|
45
43
|
|
46
44
|
@current_scheduled_command = command
|
47
45
|
@last_scheduled_command = command
|
48
46
|
@last_scheduled_reason = reason
|
49
47
|
@last_scheduled_at = Time.now
|
50
48
|
|
51
|
-
send(command, *h[:args], &block)
|
49
|
+
send(command, *h[:args], &h[:block])
|
52
50
|
@current_scheduled_command = nil
|
53
51
|
info "<= #{command}"
|
54
52
|
|
@@ -59,8 +57,14 @@ module Eye::Process::Scheduler
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
60
|
+
def execute_proc(*_args, &block)
|
61
|
+
self.instance_exec(&block)
|
62
|
+
rescue Object => ex
|
63
|
+
log_ex(ex)
|
64
|
+
end
|
65
|
+
|
62
66
|
def scheduler_actions_list
|
63
|
-
scheduler.list.map{|c| c[:args].first rescue nil }.compact
|
67
|
+
scheduler.list.map { |c| c[:args].first rescue nil }.compact
|
64
68
|
end
|
65
69
|
|
66
70
|
def scheduler_clear_pending_list
|
@@ -69,6 +73,7 @@ module Eye::Process::Scheduler
|
|
69
73
|
|
70
74
|
def self.included(base)
|
71
75
|
base.finalizer :remove_scheduler
|
76
|
+
base.execute_block_on_receiver :schedule
|
72
77
|
end
|
73
78
|
|
74
79
|
attr_accessor :current_scheduled_command
|
data/lib/eye/process/states.rb
CHANGED
@@ -2,6 +2,7 @@ require 'state_machine'
|
|
2
2
|
require 'state_machine/version'
|
3
3
|
|
4
4
|
class Eye::Process
|
5
|
+
|
5
6
|
class StateError < Exception; end
|
6
7
|
|
7
8
|
# do transition
|
@@ -27,7 +28,7 @@ class Eye::Process
|
|
27
28
|
end
|
28
29
|
|
29
30
|
event :crashed do
|
30
|
-
transition [:starting, :restarting, :up] => :down
|
31
|
+
transition [:starting, :restarting, :stopping, :up] => :down
|
31
32
|
end
|
32
33
|
|
33
34
|
event :stopping do
|
@@ -59,16 +60,17 @@ class Eye::Process
|
|
59
60
|
|
60
61
|
after_transition any => :unmonitored, :do => :on_unmonitored
|
61
62
|
|
62
|
-
after_transition any
|
63
|
-
after_transition :up => any
|
63
|
+
after_transition any - :up => :up, :do => :add_watchers
|
64
|
+
after_transition :up => any - :up, :do => :remove_watchers
|
64
65
|
|
65
|
-
after_transition any
|
66
|
+
after_transition any - :up => :up, :do => :add_children
|
66
67
|
after_transition any => [:unmonitored, :down], :do => :remove_children
|
67
68
|
|
68
69
|
after_transition :on => :crashed, :do => :on_crashed
|
69
70
|
end
|
70
71
|
|
71
72
|
def on_crashed
|
73
|
+
self.pid = nil
|
72
74
|
schedule :check_crash, Eye::Reason.new(:crashed)
|
73
75
|
end
|
74
76
|
|
@@ -79,7 +81,7 @@ class Eye::Process
|
|
79
81
|
def log_transition(transition)
|
80
82
|
if transition.to_name != transition.from_name || @state_reason.is_a?(Eye::Reason::User)
|
81
83
|
@states_history.push transition.to_name, @state_reason
|
82
|
-
info "switch :#{transition.event} [:#{transition.from_name} => :#{transition.to_name}] #{
|
84
|
+
info "switch :#{transition.event} [:#{transition.from_name} => :#{transition.to_name}] #{"(reason: #{@state_reason})" if @state_reason}"
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
@@ -1,17 +1,22 @@
|
|
1
1
|
class Eye::Process::StatesHistory < Eye::Utils::Tail
|
2
|
+
|
2
3
|
def push(state, reason = nil, tm = Time.now)
|
3
4
|
super(state: state, at: tm.to_i, reason: reason)
|
4
5
|
end
|
5
6
|
|
6
7
|
def states
|
7
|
-
self.map{|c| c[:state] }
|
8
|
+
self.map { |c| c[:state] }
|
8
9
|
end
|
9
10
|
|
10
|
-
def states_for_period(period, from_time = nil)
|
11
|
+
def states_for_period(period, from_time = nil, &block)
|
11
12
|
tm = Time.now - period
|
12
13
|
tm = [tm, from_time].max if from_time
|
13
14
|
tm = tm.to_f
|
14
|
-
|
15
|
+
if block
|
16
|
+
self.each { |s| block.call(s) if s[:at] >= tm }
|
17
|
+
else
|
18
|
+
self.select { |s| s[:at] >= tm }.map { |c| c[:state] }
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def last_state
|
@@ -25,4 +30,5 @@ class Eye::Process::StatesHistory < Eye::Utils::Tail
|
|
25
30
|
def last_state_changed_at
|
26
31
|
Time.at(last[:at])
|
27
32
|
end
|
33
|
+
|
28
34
|
end
|
data/lib/eye/process/system.rb
CHANGED
@@ -3,16 +3,7 @@ require 'timeout'
|
|
3
3
|
module Eye::Process::System
|
4
4
|
|
5
5
|
def load_pid_from_file
|
6
|
-
|
7
|
-
_pid = File.read(self[:pid_file_ex]).to_i
|
8
|
-
_pid > 0 ? _pid : nil
|
9
|
-
end
|
10
|
-
|
11
|
-
res
|
12
|
-
end
|
13
|
-
|
14
|
-
def set_pid_from_file
|
15
|
-
self.pid = load_pid_from_file
|
6
|
+
File.read(self[:pid_file_ex]).to_i rescue nil
|
16
7
|
end
|
17
8
|
|
18
9
|
def save_pid_to_file
|
@@ -26,7 +17,8 @@ module Eye::Process::System
|
|
26
17
|
end
|
27
18
|
end
|
28
19
|
|
29
|
-
def clear_pid_file
|
20
|
+
def clear_pid_file(check_content = false)
|
21
|
+
return if check_content && self.pid && load_pid_from_file != self.pid
|
30
22
|
info "delete pid_file: #{self[:pid_file_ex]}"
|
31
23
|
File.unlink(self[:pid_file_ex])
|
32
24
|
true
|
@@ -38,14 +30,38 @@ module Eye::Process::System
|
|
38
30
|
File.ctime(self[:pid_file_ex]) rescue Time.now
|
39
31
|
end
|
40
32
|
|
33
|
+
def get_identity
|
34
|
+
File.mtime(self[:pid_file_ex])
|
35
|
+
rescue Errno::ENOENT
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def compare_identity(pid = self.pid)
|
40
|
+
return :ok unless self[:check_identity]
|
41
|
+
return :no_pid unless pid
|
42
|
+
id = get_identity
|
43
|
+
return :no_pid_file unless id
|
44
|
+
st = Eye::SystemResources.start_time(pid)
|
45
|
+
return :no_start_time unless st
|
46
|
+
st1 = st.to_i
|
47
|
+
id1 = id.to_i
|
48
|
+
if (id1 - st1).abs > self[:check_identity_grace]
|
49
|
+
args = Eye::SystemResources.args(pid)
|
50
|
+
msg = "pid_file: '#{Eye::Utils.human_time2(id)}', process: '#{Eye::Utils.human_time2(st)}' (#{args})"
|
51
|
+
res = (id1 < st1) ? :fail : :touched
|
52
|
+
warn "compare_identity: #{res}, #{msg}"
|
53
|
+
res
|
54
|
+
else
|
55
|
+
:ok
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
41
59
|
def process_really_running?
|
42
60
|
process_pid_running?(self.pid)
|
43
61
|
end
|
44
62
|
|
45
63
|
def process_pid_running?(pid)
|
46
|
-
|
47
|
-
debug { "process_really_running?: <#{pid}> #{res.inspect}" }
|
48
|
-
!!res[:result]
|
64
|
+
Eye::System.pid_alive?(pid)
|
49
65
|
end
|
50
66
|
|
51
67
|
def send_signal(code)
|
@@ -58,7 +74,7 @@ module Eye::Process::System
|
|
58
74
|
res[:result] == :ok
|
59
75
|
end
|
60
76
|
|
61
|
-
def wait_for_condition(timeout, step = 0.1, &
|
77
|
+
def wait_for_condition(timeout, step = 0.1, &_block)
|
62
78
|
res = nil
|
63
79
|
sumtime = 0
|
64
80
|
|
@@ -73,7 +89,7 @@ module Eye::Process::System
|
|
73
89
|
end
|
74
90
|
|
75
91
|
def execute(cmd, cfg = {})
|
76
|
-
defer { Eye::System
|
92
|
+
defer { Eye::System.execute cmd, cfg }.tap do |res|
|
77
93
|
notify(:debug, "Bad exit status of command #{cmd.inspect}(#{res[:exitstatus].inspect})") if res[:exitstatus] != 0
|
78
94
|
end
|
79
95
|
end
|
@@ -82,7 +98,7 @@ module Eye::Process::System
|
|
82
98
|
Eye::System.daemonize(cmd, cfg)
|
83
99
|
end
|
84
100
|
|
85
|
-
def execute_sync(cmd, opts = {:
|
101
|
+
def execute_sync(cmd, opts = { timeout: 1.second })
|
86
102
|
execute(cmd, self.config.merge(opts)).tap do |res|
|
87
103
|
info "execute_sync `#{cmd}` with res: #{res}"
|
88
104
|
end
|
@@ -97,13 +113,12 @@ module Eye::Process::System
|
|
97
113
|
def failsafe_load_pid
|
98
114
|
pid = load_pid_from_file
|
99
115
|
|
100
|
-
|
101
|
-
# this is can be symlink changed case
|
116
|
+
unless pid # this is can be symlink changed case
|
102
117
|
sleep 0.1
|
103
118
|
pid = load_pid_from_file
|
104
119
|
end
|
105
120
|
|
106
|
-
pid
|
121
|
+
pid if pid && pid > 0
|
107
122
|
end
|
108
123
|
|
109
124
|
def failsafe_save_pid
|