eye 0.7 → 0.8.celluloid15
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/.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
|