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.
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