eye 0.1.11
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.
- data/.gitignore +31 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +132 -0
- data/Rakefile +18 -0
- data/bin/eye +282 -0
- data/bin/loader_eye +56 -0
- data/examples/processes/em.rb +56 -0
- data/examples/processes/forking.rb +20 -0
- data/examples/processes/sample.rb +144 -0
- data/examples/rbenv.eye +11 -0
- data/examples/test.eye +65 -0
- data/examples/unicorn.eye +29 -0
- data/eye.gemspec +37 -0
- data/lib/eye.rb +25 -0
- data/lib/eye/application.rb +65 -0
- data/lib/eye/checker.rb +118 -0
- data/lib/eye/checker/cpu.rb +27 -0
- data/lib/eye/checker/file_ctime.rb +29 -0
- data/lib/eye/checker/file_size.rb +38 -0
- data/lib/eye/checker/http.rb +94 -0
- data/lib/eye/checker/memory.rb +27 -0
- data/lib/eye/checker/socket.rb +148 -0
- data/lib/eye/checker/validation.rb +49 -0
- data/lib/eye/child_process.rb +75 -0
- data/lib/eye/client.rb +32 -0
- data/lib/eye/control.rb +2 -0
- data/lib/eye/controller.rb +43 -0
- data/lib/eye/controller/commands.rb +64 -0
- data/lib/eye/controller/helpers.rb +61 -0
- data/lib/eye/controller/load.rb +224 -0
- data/lib/eye/controller/send_command.rb +88 -0
- data/lib/eye/controller/status.rb +136 -0
- data/lib/eye/dsl.rb +52 -0
- data/lib/eye/dsl/application_opts.rb +33 -0
- data/lib/eye/dsl/chain.rb +12 -0
- data/lib/eye/dsl/child_process_opts.rb +7 -0
- data/lib/eye/dsl/config_opts.rb +11 -0
- data/lib/eye/dsl/group_opts.rb +27 -0
- data/lib/eye/dsl/helpers.rb +12 -0
- data/lib/eye/dsl/main.rb +58 -0
- data/lib/eye/dsl/opts.rb +88 -0
- data/lib/eye/dsl/process_opts.rb +21 -0
- data/lib/eye/dsl/pure_opts.rb +132 -0
- data/lib/eye/dsl/validate.rb +41 -0
- data/lib/eye/group.rb +125 -0
- data/lib/eye/group/chain.rb +68 -0
- data/lib/eye/io/unix_server.rb +44 -0
- data/lib/eye/io/unix_socket.rb +39 -0
- data/lib/eye/loader.rb +13 -0
- data/lib/eye/logger.rb +80 -0
- data/lib/eye/process.rb +83 -0
- data/lib/eye/process/child.rb +61 -0
- data/lib/eye/process/commands.rb +256 -0
- data/lib/eye/process/config.rb +70 -0
- data/lib/eye/process/controller.rb +72 -0
- data/lib/eye/process/data.rb +46 -0
- data/lib/eye/process/monitor.rb +97 -0
- data/lib/eye/process/notify.rb +17 -0
- data/lib/eye/process/scheduler.rb +50 -0
- data/lib/eye/process/states.rb +92 -0
- data/lib/eye/process/states_history.rb +62 -0
- data/lib/eye/process/system.rb +60 -0
- data/lib/eye/process/trigger.rb +32 -0
- data/lib/eye/process/watchers.rb +67 -0
- data/lib/eye/server.rb +51 -0
- data/lib/eye/settings.rb +35 -0
- data/lib/eye/system.rb +145 -0
- data/lib/eye/system_resources.rb +83 -0
- data/lib/eye/trigger.rb +53 -0
- data/lib/eye/trigger/flapping.rb +24 -0
- data/lib/eye/utils.rb +5 -0
- data/lib/eye/utils/alive_array.rb +31 -0
- data/lib/eye/utils/celluloid_chain.rb +51 -0
- data/lib/eye/utils/leak_19.rb +7 -0
- data/lib/eye/utils/tail.rb +20 -0
- data/spec/checker/cpu_spec.rb +58 -0
- data/spec/checker/file_ctime_spec.rb +34 -0
- data/spec/checker/file_size_spec.rb +107 -0
- data/spec/checker/http_spec.rb +109 -0
- data/spec/checker/memory_spec.rb +64 -0
- data/spec/checker/socket_spec.rb +116 -0
- data/spec/checker_spec.rb +188 -0
- data/spec/child_process/child_process_spec.rb +46 -0
- data/spec/client_server_spec.rb +34 -0
- data/spec/controller/commands_spec.rb +92 -0
- data/spec/controller/controller_spec.rb +133 -0
- data/spec/controller/find_objects_spec.rb +150 -0
- data/spec/controller/group_spec.rb +110 -0
- data/spec/controller/intergration_spec.rb +327 -0
- data/spec/controller/load_spec.rb +326 -0
- data/spec/controller/races_spec.rb +70 -0
- data/spec/controller/stop_on_delete_spec.rb +157 -0
- data/spec/dsl/chain_spec.rb +140 -0
- data/spec/dsl/checks_spec.rb +202 -0
- data/spec/dsl/config_spec.rb +44 -0
- data/spec/dsl/dsl_spec.rb +73 -0
- data/spec/dsl/getter_spec.rb +223 -0
- data/spec/dsl/integration_spec.rb +311 -0
- data/spec/dsl/load_spec.rb +52 -0
- data/spec/dsl/process_spec.rb +330 -0
- data/spec/dsl/sub_procs_spec.rb +93 -0
- data/spec/dsl/with_server_spec.rb +104 -0
- data/spec/example/em.rb +57 -0
- data/spec/example/forking.rb +20 -0
- data/spec/example/sample.rb +154 -0
- data/spec/fixtures/dsl/0.rb +8 -0
- data/spec/fixtures/dsl/0a.rb +8 -0
- data/spec/fixtures/dsl/0c.rb +8 -0
- data/spec/fixtures/dsl/1.rb +5 -0
- data/spec/fixtures/dsl/bad.eye +6 -0
- data/spec/fixtures/dsl/configs/1.eye +3 -0
- data/spec/fixtures/dsl/configs/2.eye +1 -0
- data/spec/fixtures/dsl/configs/3.eye +1 -0
- data/spec/fixtures/dsl/configs/4.eye +3 -0
- data/spec/fixtures/dsl/empty.eye +20 -0
- data/spec/fixtures/dsl/include_test.eye +5 -0
- data/spec/fixtures/dsl/include_test/1.rb +6 -0
- data/spec/fixtures/dsl/include_test/ha.rb +4 -0
- data/spec/fixtures/dsl/include_test2.eye +5 -0
- data/spec/fixtures/dsl/integration.eye +30 -0
- data/spec/fixtures/dsl/integration2.eye +32 -0
- data/spec/fixtures/dsl/integration_locks.eye +30 -0
- data/spec/fixtures/dsl/integration_sor.eye +32 -0
- data/spec/fixtures/dsl/integration_sor2.eye +27 -0
- data/spec/fixtures/dsl/integration_sor3.eye +32 -0
- data/spec/fixtures/dsl/load.eye +25 -0
- data/spec/fixtures/dsl/load2.eye +7 -0
- data/spec/fixtures/dsl/load2_dup2.eye +13 -0
- data/spec/fixtures/dsl/load2_dup_pid.eye +7 -0
- data/spec/fixtures/dsl/load3.eye +10 -0
- data/spec/fixtures/dsl/load4.eye +7 -0
- data/spec/fixtures/dsl/load5.eye +8 -0
- data/spec/fixtures/dsl/load6.eye +17 -0
- data/spec/fixtures/dsl/load_dubls.eye +36 -0
- data/spec/fixtures/dsl/load_dup_ex_names.eye +15 -0
- data/spec/fixtures/dsl/load_error.eye +5 -0
- data/spec/fixtures/dsl/load_error_folder/load3.eye +10 -0
- data/spec/fixtures/dsl/load_error_folder/load4.eye +7 -0
- data/spec/fixtures/dsl/load_folder/load3.eye +10 -0
- data/spec/fixtures/dsl/load_folder/load4.eye +7 -0
- data/spec/fixtures/dsl/load_int.eye +8 -0
- data/spec/fixtures/dsl/load_int2.eye +13 -0
- data/spec/fixtures/dsl/load_logger.eye +26 -0
- data/spec/fixtures/dsl/load_logger2.eye +3 -0
- data/spec/fixtures/dsl/long_load.eye +5 -0
- data/spec/fixtures/dsl/subfolder1/proc1.rb +3 -0
- data/spec/fixtures/dsl/subfolder2.eye +9 -0
- data/spec/fixtures/dsl/subfolder2/common.rb +1 -0
- data/spec/fixtures/dsl/subfolder2/proc2.rb +3 -0
- data/spec/fixtures/dsl/subfolder2/sub/proc3.rb +6 -0
- data/spec/fixtures/dsl/subfolder3.eye +8 -0
- data/spec/fixtures/dsl/subfolder3/common.rb +1 -0
- data/spec/fixtures/dsl/subfolder3/proc4.rb +3 -0
- data/spec/fixtures/dsl/subfolder3/sub/proc5.rb +6 -0
- data/spec/fixtures/dsl/subfolder4.eye +6 -0
- data/spec/fixtures/dsl/subfolder4/a.rb +2 -0
- data/spec/fixtures/dsl/subfolder4/b.rb +1 -0
- data/spec/fixtures/dsl/subfolder4/c.rb +1 -0
- data/spec/mock_spec.rb +32 -0
- data/spec/process/checks/child_checks_spec.rb +79 -0
- data/spec/process/checks/cpu_spec.rb +114 -0
- data/spec/process/checks/ctime_spec.rb +43 -0
- data/spec/process/checks/fsize_spec.rb +22 -0
- data/spec/process/checks/http_spec.rb +52 -0
- data/spec/process/checks/intergration_spec.rb +32 -0
- data/spec/process/checks/memory_spec.rb +113 -0
- data/spec/process/child_process_spec.rb +125 -0
- data/spec/process/config_spec.rb +75 -0
- data/spec/process/controller_spec.rb +173 -0
- data/spec/process/monitoring_spec.rb +180 -0
- data/spec/process/restart_spec.rb +174 -0
- data/spec/process/scheduler_spec.rb +150 -0
- data/spec/process/start_spec.rb +261 -0
- data/spec/process/states_history_spec.rb +118 -0
- data/spec/process/stop_spec.rb +150 -0
- data/spec/process/system_spec.rb +100 -0
- data/spec/process/triggers/flapping_spec.rb +81 -0
- data/spec/process/update_config_spec.rb +63 -0
- data/spec/spec_helper.rb +120 -0
- data/spec/support/rr_celluloid.rb +36 -0
- data/spec/support/scheduler_hack.rb +16 -0
- data/spec/support/spec_support.rb +164 -0
- data/spec/system_resources_spec.rb +59 -0
- data/spec/system_spec.rb +170 -0
- data/spec/utils/alive_array_spec.rb +50 -0
- data/spec/utils/celluloid_chain_spec.rb +82 -0
- data/spec/utils/tail_spec.rb +21 -0
- metadata +558 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module IO
|
5
|
+
# UNIXServer with combined blocking and evented support
|
6
|
+
class UNIXServer
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@server, :listen, :sysaccept, :close, :closed?
|
9
|
+
|
10
|
+
def self.open(socket_path)
|
11
|
+
self.new(socket_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(socket_path)
|
15
|
+
@server = ::UNIXServer.new(socket_path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def accept
|
19
|
+
actor = Thread.current[:actor]
|
20
|
+
|
21
|
+
if evented?
|
22
|
+
Celluloid.current_actor.wait_readable @server
|
23
|
+
accept_nonblock
|
24
|
+
else
|
25
|
+
Celluloid::IO::UNIXSocket.from_ruby_socket @server.accept
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def accept_nonblock
|
30
|
+
Celluloid::IO::UNIXSocket.from_ruby_socket @server.accept_nonblock
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_io
|
34
|
+
@server
|
35
|
+
end
|
36
|
+
|
37
|
+
# Are we inside a Celluloid ::IO actor?
|
38
|
+
def evented?
|
39
|
+
actor = Thread.current[:actor]
|
40
|
+
actor && actor.mailbox.is_a?(Celluloid::IO::Mailbox)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module IO
|
5
|
+
# UNIXSocket with combined blocking and evented support
|
6
|
+
class UNIXSocket
|
7
|
+
include CommonMethods
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :closed?, :readline, :puts, :addr
|
11
|
+
|
12
|
+
# Convert a Ruby UNIXSocket into a Celluloid::IO::UNIXSocket
|
13
|
+
def self.from_ruby_socket(ruby_socket)
|
14
|
+
# Some hax here, but whatever ;)
|
15
|
+
socket = allocate
|
16
|
+
socket.instance_variable_set(:@socket, ruby_socket)
|
17
|
+
socket
|
18
|
+
end
|
19
|
+
|
20
|
+
# Open a UNIX connection.
|
21
|
+
def self.open(socket_path, &block)
|
22
|
+
self.new(socket_path, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Open a UNIX connection.
|
26
|
+
def initialize(socket_path, &block)
|
27
|
+
@socket = if block
|
28
|
+
::UNIXSocket.open(socket_path, &block)
|
29
|
+
else
|
30
|
+
::UNIXSocket.new(socket_path)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_io
|
35
|
+
@socket
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/eye/loader.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# mini bundler, for embedded server gem installation
|
2
|
+
|
3
|
+
gem 'celluloid', '~> 0.12.0'
|
4
|
+
gem 'celluloid-io', '~> 0.12.0'
|
5
|
+
gem 'nio4r'
|
6
|
+
gem 'facter'
|
7
|
+
gem 'timers'
|
8
|
+
|
9
|
+
gem 'state_machine'
|
10
|
+
gem 'activesupport', '~> 3.2.0'
|
11
|
+
|
12
|
+
gem 'i18n' # for as
|
13
|
+
gem 'multi_json' # for as
|
data/lib/eye/logger.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
class Eye::Logger
|
4
|
+
attr_accessor :prefix, :subprefix
|
5
|
+
|
6
|
+
class InnerLogger < Logger
|
7
|
+
FORMAT = '%d.%m.%Y %H:%M:%S'
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
|
12
|
+
self.formatter = Proc.new do |s, d, p, m|
|
13
|
+
"#{d.strftime(FORMAT)} #{s.ljust(5)} -- #{m}\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Helpers
|
19
|
+
attr_reader :logger
|
20
|
+
|
21
|
+
Logger::Severity.constants.each do |level|
|
22
|
+
method_name = level.to_s.downcase
|
23
|
+
define_method method_name do |msg|
|
24
|
+
@logger.send(method_name, msg)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Logger::Severity.constants.each do |level|
|
30
|
+
method_name = level.to_s.downcase
|
31
|
+
define_method method_name do |msg|
|
32
|
+
self.class.inner_logger.send(method_name, "#{prefix_str}#{msg}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(prefix = nil, subprefix = nil)
|
37
|
+
@prefix = prefix
|
38
|
+
@subprefix = subprefix
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_reader :dev, :log_level
|
43
|
+
|
44
|
+
def link_logger(dev)
|
45
|
+
@dev = dev ? dev.to_s.downcase : nil
|
46
|
+
@dev_fd = @dev
|
47
|
+
|
48
|
+
@dev_fd = STDOUT if @dev == 'stdout'
|
49
|
+
@dev_fd = STDERR if @dev == 'stderr'
|
50
|
+
|
51
|
+
@inner_logger = InnerLogger.new(@dev_fd)
|
52
|
+
@inner_logger.level = self.log_level || Logger::INFO
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_level=(level)
|
56
|
+
@log_level = level
|
57
|
+
@inner_logger.level = self.log_level if @inner_logger
|
58
|
+
end
|
59
|
+
|
60
|
+
def inner_logger
|
61
|
+
@inner_logger ||= InnerLogger.new(nil)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def prefix_str
|
68
|
+
@pref_string ||= begin
|
69
|
+
pref_string = ''
|
70
|
+
|
71
|
+
if @prefix
|
72
|
+
pref_string = "[#{@prefix}] "
|
73
|
+
pref_string += "#{@subprefix} " if @subprefix
|
74
|
+
end
|
75
|
+
|
76
|
+
pref_string
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/eye/process.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
|
3
|
+
class Eye::Process
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
autoload :Config, 'eye/process/config'
|
7
|
+
autoload :Commands, 'eye/process/commands'
|
8
|
+
autoload :Data, 'eye/process/data'
|
9
|
+
autoload :Watchers, 'eye/process/watchers'
|
10
|
+
autoload :Monitor, 'eye/process/monitor'
|
11
|
+
autoload :System, 'eye/process/system'
|
12
|
+
autoload :Controller, 'eye/process/controller'
|
13
|
+
autoload :StatesHistory, 'eye/process/states_history'
|
14
|
+
autoload :Child, 'eye/process/child'
|
15
|
+
autoload :Trigger, 'eye/process/trigger'
|
16
|
+
autoload :Notify, 'eye/process/notify'
|
17
|
+
autoload :Scheduler, 'eye/process/scheduler'
|
18
|
+
|
19
|
+
attr_accessor :pid, :watchers, :config, :states_history,
|
20
|
+
:childs, :triggers, :flapping, :name
|
21
|
+
|
22
|
+
def initialize(config)
|
23
|
+
raise 'pid file should be' unless config[:pid_file]
|
24
|
+
|
25
|
+
@config = prepare_config(config)
|
26
|
+
@logger = Eye::Logger.new(full_name)
|
27
|
+
|
28
|
+
@watchers = {}
|
29
|
+
@childs = {}
|
30
|
+
@triggers = []
|
31
|
+
@flapping = false
|
32
|
+
@name = @config[:name]
|
33
|
+
|
34
|
+
@states_history = Eye::Process::StatesHistory.new(100)
|
35
|
+
@states_history << :unmonitored
|
36
|
+
|
37
|
+
debug "create with config: #{@config.inspect}"
|
38
|
+
|
39
|
+
add_triggers
|
40
|
+
|
41
|
+
super() # for statemachine
|
42
|
+
end
|
43
|
+
|
44
|
+
# c(), self[]
|
45
|
+
include Eye::Process::Config
|
46
|
+
|
47
|
+
# full_name, status_data
|
48
|
+
include Eye::Process::Data
|
49
|
+
|
50
|
+
# commands:
|
51
|
+
# start_process, stop_process, restart_process
|
52
|
+
include Eye::Process::Commands
|
53
|
+
|
54
|
+
# start, stop, restart, monitor, unmonit, delete
|
55
|
+
include Eye::Process::Controller
|
56
|
+
|
57
|
+
# add_watchers, remove_watchers:
|
58
|
+
include Eye::Process::Watchers
|
59
|
+
|
60
|
+
# check alive, crush methods:
|
61
|
+
include Eye::Process::Monitor
|
62
|
+
|
63
|
+
# system methods:
|
64
|
+
include Eye::Process::System
|
65
|
+
|
66
|
+
# manage childs methods
|
67
|
+
include Eye::Process::Child
|
68
|
+
|
69
|
+
# manage triggers methods
|
70
|
+
include Eye::Process::Trigger
|
71
|
+
|
72
|
+
# manage notify methods
|
73
|
+
include Eye::Process::Notify
|
74
|
+
|
75
|
+
# logger methods
|
76
|
+
include Eye::Logger::Helpers
|
77
|
+
|
78
|
+
# scheduler
|
79
|
+
include Eye::Process::Scheduler
|
80
|
+
end
|
81
|
+
|
82
|
+
# include state_machine states
|
83
|
+
require_relative 'process/states'
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Eye::Process::Child
|
2
|
+
|
3
|
+
def add_childs
|
4
|
+
add_or_update_childs
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_or_update_childs
|
8
|
+
return unless self[:monitor_children]
|
9
|
+
|
10
|
+
return unless self.up?
|
11
|
+
|
12
|
+
unless self.pid
|
13
|
+
warn 'Cant add childs, because no pid'
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
now_childs = Eye::SystemResources.childs(self.pid)
|
18
|
+
new_childs = []
|
19
|
+
exist_childs = []
|
20
|
+
|
21
|
+
now_childs.each do |child_pid|
|
22
|
+
if self.childs[child_pid]
|
23
|
+
exist_childs << child_pid
|
24
|
+
else
|
25
|
+
new_childs << child_pid
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
removed_childs = self.childs.keys - now_childs
|
30
|
+
|
31
|
+
if new_childs.present?
|
32
|
+
new_childs.each do |child_pid|
|
33
|
+
self.childs[child_pid] = Eye::ChildProcess.new(child_pid, self[:monitor_children], logger.prefix)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if removed_childs.present?
|
38
|
+
removed_childs.each do |child_pid|
|
39
|
+
child = self.childs.delete(child_pid)
|
40
|
+
child.delete if child && child.alive?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
h = {:new => new_childs.size, :removed => removed_childs.size, :exists => exist_childs.size }
|
45
|
+
debug "childs info: #{ h.inspect }"
|
46
|
+
|
47
|
+
h
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_childs
|
51
|
+
if childs.present?
|
52
|
+
childs.keys.each do |child_pid|
|
53
|
+
child = childs.delete(child_pid)
|
54
|
+
child.delete if child && child.alive?
|
55
|
+
end
|
56
|
+
else
|
57
|
+
debug 'No childs to clear'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Eye::Process::Commands
|
2
|
+
|
3
|
+
def start_process
|
4
|
+
debug 'start_process command'
|
5
|
+
|
6
|
+
switch :starting
|
7
|
+
|
8
|
+
unless self[:start_command]
|
9
|
+
warn 'no start command, so unmonitoring'
|
10
|
+
switch :unmonitoring
|
11
|
+
return :no_start_command
|
12
|
+
end
|
13
|
+
|
14
|
+
result = self[:daemonize] ? daemonize_process : execute_process
|
15
|
+
|
16
|
+
if !result[:error]
|
17
|
+
debug "process (#{self.pid}) ok started"
|
18
|
+
switch :started
|
19
|
+
else
|
20
|
+
debug "process (#{self.pid}) failed to start (#{result[:error].inspect})"
|
21
|
+
if self.pid && Eye::System.pid_alive?(self.pid)
|
22
|
+
warn "kill, what remains from process (#{self.pid}), because its failed to start (without pid_file impossible to monitoring)"
|
23
|
+
send_signal(:KILL)
|
24
|
+
sleep 0.2 # little grace
|
25
|
+
end
|
26
|
+
|
27
|
+
self.pid = nil
|
28
|
+
switch :crushed
|
29
|
+
end
|
30
|
+
|
31
|
+
result
|
32
|
+
|
33
|
+
rescue StateMachine::InvalidTransition => e
|
34
|
+
warn "wrong switch '#{e.message}'"
|
35
|
+
|
36
|
+
:state_error
|
37
|
+
end
|
38
|
+
|
39
|
+
def stop_process
|
40
|
+
debug 'stop_process command'
|
41
|
+
|
42
|
+
switch :stopping
|
43
|
+
|
44
|
+
kill_process
|
45
|
+
|
46
|
+
if process_realy_running?
|
47
|
+
warn 'NOT STOPPED, check command/signals, or tune stop_timeout/stop_grace, seems it was really soft'
|
48
|
+
|
49
|
+
switch :unmonitoring
|
50
|
+
nil
|
51
|
+
|
52
|
+
else
|
53
|
+
switch :stopped
|
54
|
+
|
55
|
+
if control_pid?
|
56
|
+
info "delete pid_file: #{self[:pid_file]}"
|
57
|
+
clear_pid_file
|
58
|
+
end
|
59
|
+
|
60
|
+
true
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
rescue StateMachine::InvalidTransition => e
|
65
|
+
warn "wrong switch '#{e.message}'"
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def restart_process
|
70
|
+
debug 'restart_process command'
|
71
|
+
|
72
|
+
switch :restarting
|
73
|
+
|
74
|
+
if self[:restart_command]
|
75
|
+
cmd = prepare_command(self[:restart_command])
|
76
|
+
info "executing: `#{cmd}` with restart_timeout: #{self[:restart_timeout].to_f}s and restart_grace: #{self[:restart_grace].to_f}s"
|
77
|
+
|
78
|
+
res = execute(cmd, config.merge(:timeout => self[:restart_timeout]))
|
79
|
+
|
80
|
+
if res[:error]
|
81
|
+
error "restart raised with #{res[:error].inspect}"
|
82
|
+
|
83
|
+
if res[:error].class == Timeout::Error
|
84
|
+
error 'you should tune restart_timeout setting'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
sleep self[:restart_grace].to_f
|
89
|
+
|
90
|
+
result = check_alive_with_refresh_pid_if_needed
|
91
|
+
switch(result ? :restarted : :crushed)
|
92
|
+
else
|
93
|
+
stop_process
|
94
|
+
start_process
|
95
|
+
end
|
96
|
+
|
97
|
+
true
|
98
|
+
|
99
|
+
rescue StateMachine::InvalidTransition => e
|
100
|
+
warn "wrong switch '#{e.message}'"
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def kill_process
|
107
|
+
return unless self.pid
|
108
|
+
|
109
|
+
if self[:stop_command]
|
110
|
+
cmd = prepare_command(self[:stop_command])
|
111
|
+
res = execute(cmd, config.merge(:timeout => self[:stop_timeout]))
|
112
|
+
info "executing: `#{cmd}` with stop_timeout: #{self[:stop_timeout].to_f}s and stop_grace: #{self[:stop_grace].to_f}s"
|
113
|
+
|
114
|
+
if res[:error]
|
115
|
+
error "raised with #{res[:error].inspect}"
|
116
|
+
|
117
|
+
if res[:error].class == Timeout::Error
|
118
|
+
error 'you should tune stop_timeout setting'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
sleep self[:stop_grace].to_f
|
123
|
+
|
124
|
+
elsif self[:stop_signals]
|
125
|
+
info "executing signals `#{self[:stop_signals].inspect}`"
|
126
|
+
stop_signals = self[:stop_signals].clone
|
127
|
+
|
128
|
+
signal = stop_signals.shift
|
129
|
+
send_signal(signal)
|
130
|
+
|
131
|
+
while stop_signals.present?
|
132
|
+
delay = stop_signals.shift
|
133
|
+
signal = stop_signals.shift
|
134
|
+
|
135
|
+
sleep(delay.to_f)
|
136
|
+
unless process_realy_running?
|
137
|
+
info 'has terminated'
|
138
|
+
break
|
139
|
+
end
|
140
|
+
|
141
|
+
send_signal(signal)
|
142
|
+
end
|
143
|
+
|
144
|
+
sleep self[:stop_grace].to_f
|
145
|
+
|
146
|
+
else # default command
|
147
|
+
info "executing: `kill -TERM #{self.pid}` with stop_grace: #{self[:stop_grace].to_f}s"
|
148
|
+
send_signal(:TERM)
|
149
|
+
|
150
|
+
sleep self[:stop_grace].to_f
|
151
|
+
|
152
|
+
# if process not die here, by default we kill it force
|
153
|
+
if process_realy_running?
|
154
|
+
warn "process not die after TERM and stop_grace #{self[:stop_grace].to_f}s, so send KILL"
|
155
|
+
send_signal(:KILL)
|
156
|
+
sleep 0.1 # little grace
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def daemonize_process
|
162
|
+
time_before = Time.now
|
163
|
+
res = Eye::System.daemonize(self[:start_command], config)
|
164
|
+
start_time = Time.now - time_before
|
165
|
+
|
166
|
+
info "daemonizing: `#{self[:start_command]}` with start_grace: #{self[:start_grace].to_f}s, env: #{self[:environment].inspect}, working_dir: #{self[:working_dir]}"
|
167
|
+
|
168
|
+
|
169
|
+
if res[:error]
|
170
|
+
error "raised with #{res[:error].inspect}"
|
171
|
+
|
172
|
+
if res[:error].message == 'Permission denied - open'
|
173
|
+
error 'seems stdout/err/all files is not writable'
|
174
|
+
end
|
175
|
+
|
176
|
+
return {:error => res[:error].inspect}
|
177
|
+
end
|
178
|
+
|
179
|
+
self.pid = res[:pid]
|
180
|
+
|
181
|
+
unless self.pid
|
182
|
+
error 'returned empty pid, WTF O_o'
|
183
|
+
return {:error => :empty_pid}
|
184
|
+
end
|
185
|
+
|
186
|
+
sleep self[:start_grace].to_f
|
187
|
+
|
188
|
+
unless process_realy_running?
|
189
|
+
error "process with pid (#{self.pid}) not found, may be crushed (#{check_logs_str})"
|
190
|
+
return {:error => :not_realy_running}
|
191
|
+
end
|
192
|
+
|
193
|
+
begin
|
194
|
+
save_pid_to_file
|
195
|
+
rescue => ex
|
196
|
+
error "save pid to file raised with #{ex.inspect}"
|
197
|
+
return {:error => :cant_write_pid}
|
198
|
+
end
|
199
|
+
|
200
|
+
res
|
201
|
+
end
|
202
|
+
|
203
|
+
def execute_process
|
204
|
+
info "executing: `#{self[:start_command]}` with start_timeout: #{config[:start_timeout].to_f}s, start_grace: #{self[:start_grace].to_f}s, env: #{self[:environment].inspect}, working_dir: #{self[:working_dir]}"
|
205
|
+
time_before = Time.now
|
206
|
+
|
207
|
+
res = execute(self[:start_command], config.merge(:timeout => config[:start_timeout]))
|
208
|
+
start_time = Time.now - time_before
|
209
|
+
|
210
|
+
if res[:error]
|
211
|
+
error "raised with #{res[:error].inspect}"
|
212
|
+
|
213
|
+
if res[:error].message == 'Permission denied - open'
|
214
|
+
error 'seems stdout/err/all files is not writable'
|
215
|
+
end
|
216
|
+
|
217
|
+
if res[:error].class == Timeout::Error
|
218
|
+
error "try to increase start_timeout interval (current #{self[:start_timeout]} seems too small, for process self-daemonization)"
|
219
|
+
end
|
220
|
+
|
221
|
+
return {:error => res[:error].inspect}
|
222
|
+
end
|
223
|
+
|
224
|
+
sleep self[:start_grace].to_f
|
225
|
+
|
226
|
+
unless set_pid_from_file
|
227
|
+
error "pid_file(#{self[:pid_file]}) 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)"
|
228
|
+
return {:error => :pid_not_found}
|
229
|
+
end
|
230
|
+
|
231
|
+
unless process_realy_running?
|
232
|
+
error "process in pid_file(#{self[:pid_file]})(#{self.pid}) not found, maybe process do not write there actual pid, or just crushed (#{check_logs_str})"
|
233
|
+
return {:error => :not_realy_running}
|
234
|
+
end
|
235
|
+
|
236
|
+
res[:pid] = self.pid
|
237
|
+
res
|
238
|
+
end
|
239
|
+
|
240
|
+
def check_logs_str
|
241
|
+
if !self[:stdout] && !self[:stderr]
|
242
|
+
'maybe should add stdout/err/all logs'
|
243
|
+
else
|
244
|
+
"check also it stdout/err/all logs #{[self[:stdout], self[:stderr]].inspect}"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def prepare_command(command)
|
249
|
+
if self.pid
|
250
|
+
command.to_s.gsub('{{PID}}', self.pid.to_s).gsub('{PID}', self.pid.to_s)
|
251
|
+
else
|
252
|
+
command
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|