epi 0.0.1 → 0.1.0
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/bin/epi +1 -1
- data/lib/epi/cli/command.rb +7 -0
- data/lib/epi/cli/commands/concerns/daemon.rb +33 -0
- data/lib/epi/cli/commands/config.rb +11 -3
- data/lib/epi/cli/commands/daemon.rb +14 -0
- data/lib/epi/cli/commands/help.rb +0 -0
- data/lib/epi/cli/commands/job.rb +1 -1
- data/lib/epi/cli/commands/restart.rb +16 -0
- data/lib/epi/cli/commands/start.rb +15 -0
- data/lib/epi/cli/commands/status.rb +6 -2
- data/lib/epi/cli/commands/stop.rb +16 -0
- data/lib/epi/cli.rb +1 -1
- data/lib/epi/connection.rb +7 -0
- data/lib/epi/core_ext/inflector.rb +1 -1
- data/lib/epi/daemon/receiver.rb +37 -0
- data/lib/epi/{server → daemon}/responder.rb +14 -5
- data/lib/epi/{server → daemon}/responders/config.rb +14 -2
- data/lib/epi/{server → daemon}/responders/job.rb +5 -6
- data/lib/epi/{server → daemon}/responders/shutdown.rb +1 -1
- data/lib/epi/daemon/responders/start.rb +19 -0
- data/lib/epi/{server → daemon}/responders/status.rb +4 -2
- data/lib/epi/daemon/responders/stop_all.rb +20 -0
- data/lib/epi/daemon/sender.rb +74 -0
- data/lib/epi/{server.rb → daemon.rb} +26 -27
- data/lib/epi/data.rb +4 -5
- data/lib/epi/job.rb +60 -2
- data/lib/epi/job_description.rb +6 -8
- data/lib/epi/jobs.rb +30 -2
- data/lib/epi/launch.rb +1 -1
- data/lib/epi/logging.rb +33 -0
- data/lib/epi/process_status.rb +1 -1
- data/lib/epi/running_process.rb +21 -3
- data/lib/epi/trigger.rb +53 -0
- data/lib/epi/triggers/concerns/comparison.rb +43 -0
- data/lib/epi/triggers/memory.rb +16 -0
- data/lib/epi/triggers/touch.rb +37 -0
- data/lib/epi/triggers/uptime.rb +12 -0
- data/lib/epi/version.rb +1 -1
- data/lib/epi.rb +4 -22
- metadata +26 -26
- data/lib/epi/cli/commands/server.rb +0 -38
- data/lib/epi/server/receiver.rb +0 -46
- data/lib/epi/server/responders/command.rb +0 -15
- data/lib/epi/server/sender.rb +0 -64
data/lib/epi/job.rb
CHANGED
@@ -15,6 +15,7 @@ module Epi
|
|
15
15
|
|
16
16
|
def initialize(job_description, state)
|
17
17
|
@job_description = job_description
|
18
|
+
@triggers = job_description.triggers.map { |t| Trigger.make self, *t }
|
18
19
|
@expected_count = state['expected_count'] || job_description.initial_processes
|
19
20
|
@pids = state['pids']
|
20
21
|
@dying_pids = state['dying_pids']
|
@@ -76,25 +77,80 @@ module Epi
|
|
76
77
|
stop_one while running_count > expected_count
|
77
78
|
end
|
78
79
|
|
80
|
+
def run_triggers!
|
81
|
+
@triggers.each &:try
|
82
|
+
end
|
83
|
+
|
84
|
+
def shutdown!(&callback)
|
85
|
+
count = running_count
|
86
|
+
if count > 0
|
87
|
+
count.times do
|
88
|
+
stop_one do
|
89
|
+
count -= 1
|
90
|
+
callback.call if callback && count == 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
else
|
94
|
+
callback.call if callback
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
79
98
|
def terminate!
|
80
99
|
self.expected_count = 0
|
81
100
|
sync!
|
82
101
|
end
|
83
102
|
|
103
|
+
def restart!
|
104
|
+
count = expected_count
|
105
|
+
if count > 0
|
106
|
+
self.expected_count = 0
|
107
|
+
sync!
|
108
|
+
self.expected_count = count
|
109
|
+
sync!
|
110
|
+
end
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
def running_processes
|
115
|
+
pids.map do |proc_id, pid|
|
116
|
+
[proc_id, ProcessStatus[pid] || RunningProcess.new(pid)]
|
117
|
+
end.to_h
|
118
|
+
end
|
119
|
+
|
84
120
|
def running_count
|
85
121
|
pids.count
|
86
122
|
end
|
87
123
|
|
124
|
+
def dying_count
|
125
|
+
dying_pids.count
|
126
|
+
end
|
127
|
+
|
128
|
+
# Replace a running process with a new one
|
129
|
+
# @param pid [Fixnum] PID of the process to replace
|
130
|
+
def replace(pid, &callback)
|
131
|
+
stop_one pid do
|
132
|
+
start_one while running_count < expected_count
|
133
|
+
callback.call if callback
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
88
137
|
private
|
89
138
|
|
90
139
|
def start_one
|
91
140
|
proc_id, pid = job_description.launch
|
92
141
|
pids[proc_id] = pid
|
93
142
|
Data.write pid_key(proc_id), pid
|
143
|
+
Jobs.by_pid[pid] = self
|
94
144
|
end
|
95
145
|
|
96
|
-
def stop_one
|
97
|
-
|
146
|
+
def stop_one(pid = nil, &callback)
|
147
|
+
if pid
|
148
|
+
proc_id = pids.key pid
|
149
|
+
raise Exceptions::Fatal, "Process #{pid} isn't managed by job #{id}" unless proc_id
|
150
|
+
pids.delete proc_id
|
151
|
+
else
|
152
|
+
proc_id, pid = pids.shift
|
153
|
+
end
|
98
154
|
dying_pids[proc_id] = pid
|
99
155
|
work = proc do
|
100
156
|
ProcessStatus[pid].kill job_description.kill_timeout
|
@@ -102,6 +158,8 @@ module Epi
|
|
102
158
|
done = proc do
|
103
159
|
dying_pids.delete proc_id
|
104
160
|
Data.write pid_key(proc_id), nil
|
161
|
+
Jobs.by_pid.delete pid
|
162
|
+
callback.call if callback
|
105
163
|
end
|
106
164
|
EventMachine.defer work, done
|
107
165
|
end
|
data/lib/epi/job_description.rb
CHANGED
@@ -56,11 +56,11 @@ module Epi
|
|
56
56
|
'Must be a non-negative number' unless value.is_a?(Numeric) && value >= 0
|
57
57
|
end
|
58
58
|
|
59
|
-
attr_reader :id
|
59
|
+
attr_reader :id, :triggers
|
60
60
|
|
61
61
|
def initialize(id)
|
62
62
|
@id = id
|
63
|
-
@
|
63
|
+
@triggers = []
|
64
64
|
@props = {}
|
65
65
|
end
|
66
66
|
|
@@ -78,15 +78,13 @@ module Epi
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def reconfigure
|
81
|
-
@
|
81
|
+
@triggers = []
|
82
82
|
yield self
|
83
|
+
# TODO: trigger an update of existing/running jobs
|
83
84
|
end
|
84
85
|
|
85
|
-
def on(
|
86
|
-
|
87
|
-
args: args,
|
88
|
-
handler: handler
|
89
|
-
}
|
86
|
+
def on(trigger_name, *args, &handler)
|
87
|
+
@triggers << [trigger_name, args, handler]
|
90
88
|
end
|
91
89
|
|
92
90
|
def pid_key(proc_id)
|
data/lib/epi/jobs.rb
CHANGED
@@ -8,13 +8,14 @@ module Epi
|
|
8
8
|
class << self
|
9
9
|
extend Forwardable
|
10
10
|
|
11
|
-
delegate [:[], :[]=, :delete, :each_value, :map] => :@jobs
|
11
|
+
delegate [:[], :[]=, :delete, :each_value, :map, :find, :count] => :@jobs
|
12
12
|
|
13
|
-
attr_reader :configuration_files
|
13
|
+
attr_reader :configuration_files, :by_pid
|
14
14
|
|
15
15
|
def reset!
|
16
16
|
@configuration_files = {}
|
17
17
|
@jobs = {}
|
18
|
+
@by_pid = {}
|
18
19
|
end
|
19
20
|
|
20
21
|
def beat!
|
@@ -37,6 +38,13 @@ module Epi
|
|
37
38
|
# Sync each job with its expectations
|
38
39
|
each_value &:sync!
|
39
40
|
|
41
|
+
# Snapshot processes again, so that triggers have access to
|
42
|
+
# newly-spawned processes
|
43
|
+
ProcessStatus.take!
|
44
|
+
|
45
|
+
# Run job triggers
|
46
|
+
each_value &:run_triggers!
|
47
|
+
|
40
48
|
# Write state of each job to data file
|
41
49
|
Data.jobs = map { |id, job| [id.to_s, job.state] }.to_h
|
42
50
|
Data.save
|
@@ -45,6 +53,26 @@ module Epi
|
|
45
53
|
@next_beat = EventMachine.add_timer(5) { beat! } # TODO: make interval configurable
|
46
54
|
end
|
47
55
|
|
56
|
+
def shutdown!(&callback)
|
57
|
+
EventMachine.cancel_timer @next_beat if @next_beat
|
58
|
+
ProcessStatus.take!
|
59
|
+
remaining = count
|
60
|
+
if remaining > 0
|
61
|
+
each_value do |job|
|
62
|
+
job.shutdown! do
|
63
|
+
remaining -= 1
|
64
|
+
callback.call if callback && remaining == 0
|
65
|
+
end
|
66
|
+
end
|
67
|
+
else
|
68
|
+
callback.call if callback
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def running_process_count
|
73
|
+
each_value.map(&:running_count).reduce(:+) || 0
|
74
|
+
end
|
75
|
+
|
48
76
|
def job_descriptions
|
49
77
|
configuration_files.values.inject({}) { |all, conf_file| all.merge! conf_file.job_descriptions }
|
50
78
|
end
|
data/lib/epi/launch.rb
CHANGED
@@ -53,7 +53,7 @@ module Epi
|
|
53
53
|
|
54
54
|
# Run the command and read the resulting PID from its STDOUT
|
55
55
|
IO.popen(env, cmd) { |p| p.read }.to_i.tap do |pid|
|
56
|
-
logger.
|
56
|
+
logger.info "Process #{pid} started: #{`ps -p #{pid} -o command=`.chomp}"
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
data/lib/epi/logging.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Epi
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
DEFAULT_LEVEL = 'info'
|
6
|
+
|
7
|
+
def logger
|
8
|
+
@logger ||= make_logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def logger=(value)
|
12
|
+
@logger = Logger === value ? value : make_logger(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def make_logger(target = nil)
|
18
|
+
Logger.new(target || ENV['EPI_LOG'] || default_log_path).tap do |logger|
|
19
|
+
logger.level = log_level
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def default_log_path
|
24
|
+
Data.home.join('epi.log').to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def log_level
|
28
|
+
Logger::Severity.const_get (ENV['EPI_LOG_LEVEL'] || DEFAULT_LEVEL).upcase
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/epi/process_status.rb
CHANGED
data/lib/epi/running_process.rb
CHANGED
@@ -42,10 +42,11 @@ module Epi
|
|
42
42
|
Epi.logger
|
43
43
|
end
|
44
44
|
|
45
|
-
def initialize(pid, ps_line
|
46
|
-
@pid = pid
|
45
|
+
def initialize(pid, ps_line: nil, job: nil)
|
46
|
+
@pid = pid.to_i
|
47
47
|
@ps_line = ps_line
|
48
48
|
@props = {}
|
49
|
+
@job = job
|
49
50
|
reload! unless ps_line
|
50
51
|
end
|
51
52
|
|
@@ -96,6 +97,12 @@ module Epi
|
|
96
97
|
@started_at ||= Time.parse parts[5..9].join ' '
|
97
98
|
end
|
98
99
|
|
100
|
+
# Duration the process has been running (in seconds)
|
101
|
+
# @return [Float]
|
102
|
+
def uptime
|
103
|
+
Time.now - started_at
|
104
|
+
end
|
105
|
+
|
99
106
|
# Name of the user that owns the process
|
100
107
|
# @return [String]
|
101
108
|
def user
|
@@ -136,17 +143,28 @@ module Epi
|
|
136
143
|
else
|
137
144
|
signal = timeout ? 'KILL' : 'TERM'
|
138
145
|
logger.info "Sending #{signal} to process #{pid}"
|
139
|
-
Process.kill signal, pid
|
146
|
+
Process.kill signal, pid rescue Errno::ESRCH false
|
140
147
|
sleep 0.2 while `ps -p #{pid} > /dev/null 2>&1; echo $?`.chomp.to_i == 0
|
141
148
|
logger.info "Process #{pid} terminated by signal #{signal}"
|
142
149
|
end
|
143
150
|
self
|
144
151
|
end
|
145
152
|
|
153
|
+
# Kill a running process immediately and synchronously with kill -9
|
154
|
+
# @return [RunningProcess]
|
146
155
|
def kill!
|
147
156
|
kill true
|
148
157
|
end
|
149
158
|
|
159
|
+
def job
|
160
|
+
@job ||= Jobs.by_pid[pid]
|
161
|
+
end
|
162
|
+
|
163
|
+
def restart!
|
164
|
+
raise Exceptions::Fatal, 'Cannot restart this process because it is not managed by a job' unless job
|
165
|
+
job.replace pid
|
166
|
+
end
|
167
|
+
|
150
168
|
private
|
151
169
|
|
152
170
|
def parts
|
data/lib/epi/trigger.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Epi
|
2
|
+
class Trigger
|
3
|
+
|
4
|
+
def self.make(job, name, args, handler)
|
5
|
+
klass_name = name.camelize
|
6
|
+
klass = Triggers.const_defined?(klass_name) && Triggers.const_get(klass_name)
|
7
|
+
raise Exceptions::Fatal, "No trigger exists named #{name}" unless Class === klass && klass < self
|
8
|
+
klass.new job, handler, *args
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :job, :args
|
12
|
+
|
13
|
+
def initialize(job, handler, *args)
|
14
|
+
@job = job
|
15
|
+
@handler = handler
|
16
|
+
@args = args
|
17
|
+
end
|
18
|
+
|
19
|
+
def logger
|
20
|
+
Epi.logger
|
21
|
+
end
|
22
|
+
|
23
|
+
def message
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def try
|
28
|
+
case self
|
29
|
+
when ProcessTrigger then job.running_processes.each_value { |process| try_with process }
|
30
|
+
when JobTrigger then try_with nil
|
31
|
+
else nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def try_with(process)
|
36
|
+
args = [process].reject(&:nil?)
|
37
|
+
if test *args
|
38
|
+
text = "Trigger on job #{job.id}"
|
39
|
+
text << " (PID #{process.pid})" if process
|
40
|
+
text << ": " << message if message
|
41
|
+
logger.info text
|
42
|
+
@handler.call process || job
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class JobTrigger < self; end
|
47
|
+
class ProcessTrigger < self; end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
Dir[File.expand_path '../triggers/concerns/*.rb', __FILE__].each { |f| require f }
|
53
|
+
Dir[File.expand_path '../triggers/*.rb', __FILE__].each { |f| require f }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Epi
|
2
|
+
module Triggers
|
3
|
+
module Concerns
|
4
|
+
module Comparison
|
5
|
+
|
6
|
+
def compare(subject)
|
7
|
+
tester.call subject, object
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def tester
|
13
|
+
@tester ||= choose_tester
|
14
|
+
end
|
15
|
+
|
16
|
+
def op
|
17
|
+
@op ||= args[0]
|
18
|
+
end
|
19
|
+
|
20
|
+
def object
|
21
|
+
@object ||= args[1]
|
22
|
+
end
|
23
|
+
|
24
|
+
def choose_tester
|
25
|
+
case op
|
26
|
+
when :gt then -> a, b { a > b }
|
27
|
+
when :lt then -> a, b { a < b }
|
28
|
+
when :gte then -> a, b { a >= b }
|
29
|
+
when :lte then -> a, b { a <= b }
|
30
|
+
when :eq then -> a, b { a == b }
|
31
|
+
when :not_eq then -> a, b { a != b}
|
32
|
+
when :match then -> a, b { a =~ b }
|
33
|
+
when :not_match then -> a, b { a !~ b }
|
34
|
+
when :like then -> a, b { a === b }
|
35
|
+
when :not_like then -> a, b { !(a === b) }
|
36
|
+
else raise Exceptions::Fatal, "Unknown operation #{op}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Epi
|
2
|
+
module Triggers
|
3
|
+
class Memory < Trigger::ProcessTrigger
|
4
|
+
include Concerns::Comparison
|
5
|
+
|
6
|
+
def test(process)
|
7
|
+
compare process.physical_memory
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
"Physical memory exceeded #{object} bytes"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Epi
|
2
|
+
module Triggers
|
3
|
+
class Touch < Trigger::JobTrigger
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
super *args
|
7
|
+
update
|
8
|
+
end
|
9
|
+
|
10
|
+
def test
|
11
|
+
ino = @ino; mtime = @mtime
|
12
|
+
update
|
13
|
+
ino != @ino || mtime != @mtime
|
14
|
+
end
|
15
|
+
|
16
|
+
def message
|
17
|
+
"Path '#{path}' was touched"
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def path
|
23
|
+
@path ||= Pathname args.first
|
24
|
+
end
|
25
|
+
|
26
|
+
def update
|
27
|
+
@ino, @mtime = begin
|
28
|
+
stat = path.stat
|
29
|
+
[stat.ino, stat.mtime]
|
30
|
+
rescue Errno::ENOENT
|
31
|
+
[nil, nil]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/epi/version.rb
CHANGED
data/lib/epi.rb
CHANGED
@@ -3,10 +3,12 @@ require 'logger'
|
|
3
3
|
require 'shellwords'
|
4
4
|
|
5
5
|
require 'epi/core_ext'
|
6
|
+
require 'epi/logging'
|
6
7
|
require 'epi/exceptions'
|
7
8
|
require 'epi/version'
|
8
9
|
require 'epi/cli'
|
9
|
-
require 'epi/
|
10
|
+
require 'epi/connection'
|
11
|
+
require 'epi/daemon'
|
10
12
|
require 'epi/data'
|
11
13
|
require 'epi/process_status'
|
12
14
|
require 'epi/running_process'
|
@@ -15,38 +17,18 @@ require 'epi/jobs'
|
|
15
17
|
require 'epi/configuration_file'
|
16
18
|
require 'epi/job_description'
|
17
19
|
require 'epi/launch'
|
20
|
+
require 'epi/trigger'
|
18
21
|
|
19
22
|
module Epi
|
20
23
|
ROOT = Pathname File.expand_path('../..', __FILE__)
|
21
24
|
|
22
25
|
class << self
|
23
26
|
|
24
|
-
def logger
|
25
|
-
@logger ||= make_logger
|
26
|
-
end
|
27
|
-
|
28
|
-
def logger=(value)
|
29
|
-
@logger = Logger === value ? value : make_logger(value)
|
30
|
-
end
|
31
|
-
|
32
27
|
def root?
|
33
28
|
@is_root = `whoami`.chomp == 'root' if @is_root.nil?
|
34
29
|
@is_root
|
35
30
|
end
|
36
31
|
|
37
|
-
private
|
38
|
-
|
39
|
-
def make_logger(target = nil)
|
40
|
-
Logger.new(target || ENV['EPI_LOG'] || STDOUT).tap do |logger|
|
41
|
-
logger.level = Logger::Severity::WARN
|
42
|
-
level = ENV['EPI_LOG_LEVEL']
|
43
|
-
if level
|
44
|
-
level = level.upcase
|
45
|
-
logger.level = Logger::Severity.const_get(level) if Logger::Severity.const_defined? level
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
32
|
end
|
51
33
|
|
52
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil E. Pearson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bson
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.3'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.3'
|
41
27
|
description: Manage your background processes
|
42
28
|
email:
|
43
29
|
- neil@helium.net.au
|
@@ -50,13 +36,29 @@ files:
|
|
50
36
|
- lib/epi.rb
|
51
37
|
- lib/epi/cli.rb
|
52
38
|
- lib/epi/cli/command.rb
|
39
|
+
- lib/epi/cli/commands/concerns/daemon.rb
|
53
40
|
- lib/epi/cli/commands/config.rb
|
41
|
+
- lib/epi/cli/commands/daemon.rb
|
42
|
+
- lib/epi/cli/commands/help.rb
|
54
43
|
- lib/epi/cli/commands/job.rb
|
55
|
-
- lib/epi/cli/commands/
|
44
|
+
- lib/epi/cli/commands/restart.rb
|
45
|
+
- lib/epi/cli/commands/start.rb
|
56
46
|
- lib/epi/cli/commands/status.rb
|
47
|
+
- lib/epi/cli/commands/stop.rb
|
57
48
|
- lib/epi/configuration_file.rb
|
49
|
+
- lib/epi/connection.rb
|
58
50
|
- lib/epi/core_ext.rb
|
59
51
|
- lib/epi/core_ext/inflector.rb
|
52
|
+
- lib/epi/daemon.rb
|
53
|
+
- lib/epi/daemon/receiver.rb
|
54
|
+
- lib/epi/daemon/responder.rb
|
55
|
+
- lib/epi/daemon/responders/config.rb
|
56
|
+
- lib/epi/daemon/responders/job.rb
|
57
|
+
- lib/epi/daemon/responders/shutdown.rb
|
58
|
+
- lib/epi/daemon/responders/start.rb
|
59
|
+
- lib/epi/daemon/responders/status.rb
|
60
|
+
- lib/epi/daemon/responders/stop_all.rb
|
61
|
+
- lib/epi/daemon/sender.rb
|
60
62
|
- lib/epi/data.rb
|
61
63
|
- lib/epi/exceptions.rb
|
62
64
|
- lib/epi/exceptions/base.rb
|
@@ -67,17 +69,14 @@ files:
|
|
67
69
|
- lib/epi/job_description.rb
|
68
70
|
- lib/epi/jobs.rb
|
69
71
|
- lib/epi/launch.rb
|
72
|
+
- lib/epi/logging.rb
|
70
73
|
- lib/epi/process_status.rb
|
71
74
|
- lib/epi/running_process.rb
|
72
|
-
- lib/epi/
|
73
|
-
- lib/epi/
|
74
|
-
- lib/epi/
|
75
|
-
- lib/epi/
|
76
|
-
- lib/epi/
|
77
|
-
- lib/epi/server/responders/job.rb
|
78
|
-
- lib/epi/server/responders/shutdown.rb
|
79
|
-
- lib/epi/server/responders/status.rb
|
80
|
-
- lib/epi/server/sender.rb
|
75
|
+
- lib/epi/trigger.rb
|
76
|
+
- lib/epi/triggers/concerns/comparison.rb
|
77
|
+
- lib/epi/triggers/memory.rb
|
78
|
+
- lib/epi/triggers/touch.rb
|
79
|
+
- lib/epi/triggers/uptime.rb
|
81
80
|
- lib/epi/version.rb
|
82
81
|
homepage: https://github.com/hx/epi
|
83
82
|
licenses:
|
@@ -104,3 +103,4 @@ signing_key:
|
|
104
103
|
specification_version: 4
|
105
104
|
summary: Epinephrine
|
106
105
|
test_files: []
|
106
|
+
has_rdoc:
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module Epi
|
2
|
-
module Cli
|
3
|
-
module Commands
|
4
|
-
class Server < Command
|
5
|
-
|
6
|
-
def run
|
7
|
-
process = Epi::Server.process
|
8
|
-
raise Exceptions::Fatal, 'You need root privileges to manage this server' if
|
9
|
-
process && process.was_alive? && process.root? && !Epi.root?
|
10
|
-
case args.first
|
11
|
-
when nil, 'start' then startup
|
12
|
-
when 'run' then run_server
|
13
|
-
when 'stop' then shutdown
|
14
|
-
else raise Exceptions::Fatal, 'Unknown server command, use [ start | stop | restart ]'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def startup
|
21
|
-
Epi::Server.ensure_running
|
22
|
-
puts 'Server is running'
|
23
|
-
end
|
24
|
-
|
25
|
-
def shutdown
|
26
|
-
Epi::Server.shutdown
|
27
|
-
puts 'Server has shut down'
|
28
|
-
end
|
29
|
-
|
30
|
-
def run_server
|
31
|
-
Epi::Server.run
|
32
|
-
puts 'Server is running'
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|