eye 0.7 → 0.8.celluloid15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +141 -0
  3. data/.travis.yml +5 -3
  4. data/CHANGES.md +9 -1
  5. data/README.md +5 -2
  6. data/Rakefile +6 -6
  7. data/bin/leye +9 -4
  8. data/bin/loader_eye +14 -15
  9. data/examples/custom_check.eye +24 -0
  10. data/examples/custom_trigger.eye +30 -0
  11. data/examples/delayed_job.eye +3 -3
  12. data/examples/dependency.eye +10 -11
  13. data/examples/leye_example/Eyefile +10 -0
  14. data/examples/notify.eye +3 -4
  15. data/examples/plugin/main.eye +5 -5
  16. data/examples/plugin/plugin.rb +10 -2
  17. data/examples/process_thin.rb +8 -8
  18. data/examples/processes/em.rb +18 -12
  19. data/examples/processes/forking.rb +5 -5
  20. data/examples/processes/sample.rb +46 -44
  21. data/examples/puma.eye +9 -8
  22. data/examples/rbenv.eye +5 -5
  23. data/examples/sidekiq.eye +3 -3
  24. data/examples/stress_test.eye +4 -4
  25. data/examples/syslog.eye +1 -1
  26. data/examples/test.eye +1 -2
  27. data/examples/thin-farm.eye +7 -8
  28. data/examples/triggers.eye +13 -15
  29. data/examples/unicorn.eye +12 -13
  30. data/eye.gemspec +16 -14
  31. data/lib/eye.rb +2 -3
  32. data/lib/eye/application.rb +5 -6
  33. data/lib/eye/checker.rb +44 -25
  34. data/lib/eye/checker/children_count.rb +1 -1
  35. data/lib/eye/checker/file_ctime.rb +1 -1
  36. data/lib/eye/checker/http.rb +13 -15
  37. data/lib/eye/checker/nop.rb +1 -0
  38. data/lib/eye/checker/socket.rb +60 -63
  39. data/lib/eye/checker/ssl_socket.rb +5 -5
  40. data/lib/eye/child_process.rb +6 -4
  41. data/lib/eye/cli.rb +74 -46
  42. data/lib/eye/cli/commands.rb +4 -5
  43. data/lib/eye/cli/render.rb +61 -41
  44. data/lib/eye/cli/server.rb +19 -16
  45. data/lib/eye/client.rb +1 -0
  46. data/lib/eye/config.rb +36 -33
  47. data/lib/eye/controller.rb +2 -3
  48. data/lib/eye/controller/commands.rb +1 -1
  49. data/lib/eye/controller/helpers.rb +2 -2
  50. data/lib/eye/controller/load.rb +19 -17
  51. data/lib/eye/controller/options.rb +1 -5
  52. data/lib/eye/controller/send_command.rb +21 -23
  53. data/lib/eye/controller/status.rb +17 -14
  54. data/lib/eye/dsl.rb +6 -1
  55. data/lib/eye/dsl/application_opts.rb +4 -3
  56. data/lib/eye/dsl/chain.rb +2 -2
  57. data/lib/eye/dsl/child_process_opts.rb +3 -3
  58. data/lib/eye/dsl/config_opts.rb +7 -7
  59. data/lib/eye/dsl/group_opts.rb +3 -3
  60. data/lib/eye/dsl/helpers.rb +1 -1
  61. data/lib/eye/dsl/main.rb +4 -3
  62. data/lib/eye/dsl/opts.rb +31 -28
  63. data/lib/eye/dsl/process_opts.rb +13 -7
  64. data/lib/eye/dsl/pure_opts.rb +13 -9
  65. data/lib/eye/dsl/validation.rb +48 -35
  66. data/lib/eye/group.rb +23 -8
  67. data/lib/eye/group/chain.rb +6 -6
  68. data/lib/eye/loader.rb +3 -3
  69. data/lib/eye/local.rb +9 -4
  70. data/lib/eye/logger.rb +11 -4
  71. data/lib/eye/notify.rb +10 -6
  72. data/lib/eye/notify/jabber.rb +1 -1
  73. data/lib/eye/notify/mail.rb +2 -2
  74. data/lib/eye/notify/slack.rb +4 -3
  75. data/lib/eye/process.rb +2 -0
  76. data/lib/eye/process/children.rb +4 -4
  77. data/lib/eye/process/commands.rb +38 -39
  78. data/lib/eye/process/config.rb +22 -16
  79. data/lib/eye/process/controller.rb +5 -19
  80. data/lib/eye/process/data.rb +11 -9
  81. data/lib/eye/process/monitor.rb +86 -76
  82. data/lib/eye/process/notify.rb +10 -10
  83. data/lib/eye/process/scheduler.rb +36 -31
  84. data/lib/eye/process/states.rb +7 -5
  85. data/lib/eye/process/states_history.rb +9 -3
  86. data/lib/eye/process/system.rb +35 -20
  87. data/lib/eye/process/trigger.rb +1 -5
  88. data/lib/eye/process/watchers.rb +12 -9
  89. data/lib/eye/reason.rb +4 -1
  90. data/lib/eye/server.rb +3 -2
  91. data/lib/eye/system.rb +22 -15
  92. data/lib/eye/system_resources.rb +17 -8
  93. data/lib/eye/trigger.rb +18 -16
  94. data/lib/eye/trigger/check_dependency.rb +7 -4
  95. data/lib/eye/trigger/flapping.rb +24 -7
  96. data/lib/eye/trigger/starting_guard.rb +7 -6
  97. data/lib/eye/trigger/stop_children.rb +2 -2
  98. data/lib/eye/trigger/transition.rb +1 -1
  99. data/lib/eye/trigger/wait_dependency.rb +3 -2
  100. data/lib/eye/utils.rb +4 -3
  101. data/lib/eye/utils/alive_array.rb +9 -4
  102. data/lib/eye/utils/celluloid_chain.rb +12 -10
  103. data/lib/eye/utils/mini_active_support.rb +16 -16
  104. data/lib/eye/utils/pmap.rb +2 -0
  105. data/lib/eye/utils/tail.rb +2 -2
  106. metadata +39 -8
  107. data/lib/eye/utils/leak_19.rb +0 -10
@@ -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(debug = false)
24
- p_st = self_status_data(debug)
23
+ def status_data(opts = {})
24
+ p_st = self_status_data(opts)
25
25
 
26
26
  if children.present?
27
- p_st.merge(:subtree => Eye::Utils::AliveArray.new(children.values).map{|c| c.status_data(debug) } )
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(:subtree => [{name: '=loading children='}])
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(debug = false)
37
- h = { name: name, state: state,
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.merge!( state_changed_at: @states_history.last_state_changed_at.to_i,
43
- state_reason: @states_history.last_reason.to_s )
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
@@ -2,102 +2,112 @@ module Eye::Process::Monitor
2
2
 
3
3
  private
4
4
 
5
- def check_alive_with_refresh_pid_if_needed
6
- if process_really_running?
7
- return true
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
- warn 'process not really running'
11
- try_update_pid_from_file
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 try_update_pid_from_file
16
- # if pid file was rewritten
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
- if process_really_running?
23
- return true
24
- else
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
- debug { 'process was not found' }
30
- return false
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 check_alive
35
- if up?
46
+ def check_pid_file
47
+ ppid = failsafe_load_pid
48
+ return if ppid == self.pid
36
49
 
37
- # check that process runned
38
- unless process_really_running?
39
- warn "check_alive: process <#{self.pid}> not found"
40
- notify :info, 'crashed!'
41
- clear_pid_file if control_pid? && self.pid && load_pid_from_file == self.pid
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
- switch :crashed, Eye::Reason.new(:crashed)
44
- else
45
- # check that pid_file still here
46
- ppid = failsafe_load_pid
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
- if down?
87
- if self[:keep_alive]
88
- warn 'check crashed: process is down'
89
-
90
- if self[:restore_in]
91
- schedule_in self[:restore_in].to_f, :restore, Eye::Reason.new(:crashed)
92
- else
93
- schedule :restore, Eye::Reason.new(:crashed)
94
- end
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
- warn 'check crashed: process without keep_alive'
97
- schedule :unmonitor, Eye::Reason.new(:crashed)
106
+ schedule :restore, Eye::Reason.new(:crashed)
98
107
  end
99
108
  else
100
- debug { 'check crashed: skipped, process is not in down' }
109
+ warn 'check crashed: process without keep_alive'
110
+ schedule :unmonitor, Eye::Reason.new(:crashed)
101
111
  end
102
112
  end
103
113
 
@@ -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 = {:debug => 0, :info => 1, :warn => 2, :error => 3, :fatal => 4}
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
- if self[:notify].present?
16
- message = {:message => msg, :name => name,
17
- :full_name => full_name, :pid => pid, :host => Eye::Local.host, :level => level,
18
- :at => Time.now }
19
-
20
- self[:notify].each do |contact, not_level|
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
- if scheduler.alive?
6
- if scheduler_freeze?
7
- warn ":#{command} ignoring to schedule, because scheduler is freeze"
8
- return
9
- end
10
-
11
- unless self.respond_to?(command, true)
12
- warn ":#{command} scheduling is unsupported"
13
- return
14
- end
15
-
16
- reason = if args.present? && args[-1].kind_of?(Eye::Reason)
17
- args.pop
18
- end
19
-
20
- info "schedule :#{command} #{reason ? "(reason: #{reason})" : nil}"
21
-
22
- if reason.class == Eye::Reason
23
- # for auto reasons
24
- # skip already running commands and all in chain
25
- scheduler.add_wo_dups_current(:scheduled_action, command, {:args => args, :reason => reason}, &block)
26
- else
27
- # for manual, or without reason
28
- # skip only for last in chain
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 = {}, &block)
43
- reason = h.delete(:reason)
44
- info "=> #{command} #{h[:args].present? ? "#{h[:args]*',' }" : nil} #{reason ? "(reason: #{reason})" : nil}"
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
@@ -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-:up => :up, :do => :add_watchers
63
- after_transition :up => any-:up, :do => :remove_watchers
63
+ after_transition any - :up => :up, :do => :add_watchers
64
+ after_transition :up => any - :up, :do => :remove_watchers
64
65
 
65
- after_transition any-:up => :up, :do => :add_children
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}] #{@state_reason ? "(reason: #{@state_reason})" : nil}"
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
- self.select{|s| s[:at] >= tm }.map{|c| c[:state] }
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
@@ -3,16 +3,7 @@ require 'timeout'
3
3
  module Eye::Process::System
4
4
 
5
5
  def load_pid_from_file
6
- res = if File.exist?(self[:pid_file_ex])
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
- res = Eye::System.check_pid_alive(pid)
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, &block)
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::execute cmd, cfg }.tap do |res|
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 = {:timeout => 1.second})
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
- if !pid
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