zeusd 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.
- data/.gitignore +2 -0
- data/Gemfile +2 -0
- data/Guardfile +1 -2
- data/README.md +27 -23
- data/Rakefile +1 -2
- data/bin/zeusd +13 -15
- data/lib/zeusd.rb +1 -1
- data/lib/zeusd/daemon.rb +80 -52
- data/lib/zeusd/{state_interpreter.rb → interpreter.rb} +18 -12
- data/lib/zeusd/process.rb +36 -25
- data/lib/zeusd/version.rb +1 -1
- data/spec/spec_helper.rb +3 -1
- data/spec/support/dummy_process.rb +10 -0
- data/spec/zeusd/daemon_spec.rb +37 -9
- data/spec/zeusd/process_spec.rb +76 -9
- data/zeusd.gemspec +1 -0
- metadata +23 -5
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
guard :rspec, :failed_mode => :none do
|
2
2
|
watch(%r{^spec/.+_spec\.rb$})
|
3
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/
|
4
|
-
watch(%r{^lib/zeusd/(.+)\.rb$}) { |m| "spec/lib/zeusd/#{m[1]}_spec.rb" }
|
3
|
+
watch(%r{^lib/zeusd/(.+)\.rb$}) { |m| "spec/zeusd/#{m[1]}_spec.rb" }
|
5
4
|
watch('spec/spec_helper.rb') { "spec" }
|
6
5
|
end
|
7
6
|
|
data/README.md
CHANGED
@@ -1,48 +1,52 @@
|
|
1
|
-
# Zeusd
|
1
|
+
# Zeusd [](http://badge.fury.io/rb/zeusd) [](https://travis-ci.org/veloper/zeusd) [](https://codeclimate.com/github/veloper/zeusd)
|
2
2
|
|
3
|
-
Run
|
3
|
+
*Run Zeus as a daemon.*
|
4
4
|
|
5
|
-
|
5
|
+
## Introduction
|
6
6
|
|
7
|
+
Zeus**d** lets you work with the [Zeus Gem](https://github.com/burke/zeus) like it's a daemon -- allowing greater control and easier scripting
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
Add this line to your application's Gemfile:
|
11
|
-
|
12
|
-
gem 'zeusd'
|
9
|
+
### Primary Commands
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Or install it yourself as:
|
11
|
+
```
|
12
|
+
$ zeusd start [--cwd=/path/to/rails/root]
|
13
|
+
[--block | -b]
|
14
|
+
[--verbose | -v]
|
19
15
|
|
20
|
-
|
16
|
+
$ zeusd restart [--cwd=/path/to/rails/root]
|
17
|
+
[--block | -b]
|
18
|
+
[--verbose | -v]
|
21
19
|
|
22
|
-
|
20
|
+
$ zeusd stop [--cwd=/path/to/rails/root]
|
21
|
+
[--verbose | -v]
|
22
|
+
```
|
23
23
|
|
24
|
-
### Commands
|
24
|
+
### Utility Commands
|
25
25
|
|
26
26
|
```
|
27
|
-
zeusd
|
28
|
-
|
29
|
-
zeusd restart
|
27
|
+
$ zeusd tail [--cwd=/path/to/rails/root]
|
28
|
+
[--follow | -f]
|
30
29
|
```
|
31
30
|
|
32
|
-
|
33
|
-
* `--cwd=current/work/directory/of/rails/app` or alias `-d`
|
34
|
-
* `--verbose` or `-v`
|
31
|
+
## Installation
|
35
32
|
|
33
|
+
```
|
34
|
+
$ gem install zeusd
|
35
|
+
```
|
36
36
|
|
37
37
|
## Contributing
|
38
38
|
|
39
39
|
1. Fork it
|
40
40
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
41
|
-
3. Write
|
41
|
+
3. Write passing specs that test your changes
|
42
42
|
3. Commit your changes and specs (`git commit -am 'Add some feature'`)
|
43
43
|
4. Push to the branch (`git push origin my-new-feature`)
|
44
44
|
5. Create new Pull Request
|
45
45
|
|
46
|
+
## Author
|
47
|
+
|
48
|
+
[Daniel Doezema](http://dan.doezema.com)
|
49
|
+
|
46
50
|
## License
|
47
51
|
|
48
52
|
* Zeusd is released under the New BSD license. http://dan.doezema.com/licenses/new-bsd/
|
data/Rakefile
CHANGED
data/bin/zeusd
CHANGED
@@ -4,37 +4,35 @@ require "zeusd"
|
|
4
4
|
class ZeusdCLI < Thor
|
5
5
|
class_option :verbose, :type => :boolean, :aliases => :v
|
6
6
|
class_option :block, :type => :boolean, :aliases => :b
|
7
|
-
class_option :cwd, :type => :string
|
8
|
-
class_option :log, :type => :string, :aliases => :l
|
7
|
+
class_option :cwd, :type => :string
|
9
8
|
|
10
|
-
desc "start", "."
|
9
|
+
desc "start", "Start the daemon."
|
11
10
|
def start
|
12
|
-
daemon.start!
|
11
|
+
daemon.start!(:block => options[:block])
|
13
12
|
end
|
14
13
|
|
15
|
-
desc "restart", "."
|
14
|
+
desc "restart", "Restart the daemon."
|
16
15
|
def restart
|
17
|
-
|
18
|
-
start
|
16
|
+
daemon.restart!(:block => options[:block])
|
19
17
|
end
|
20
18
|
|
21
|
-
desc "stop", "."
|
19
|
+
desc "stop", "Stop the daemon."
|
22
20
|
def stop
|
23
21
|
daemon.stop!
|
24
22
|
end
|
25
23
|
|
26
|
-
desc "
|
27
|
-
|
28
|
-
|
24
|
+
desc "tail", "Tail the daemon's log."
|
25
|
+
method_option :follow, :type => :boolean, :aliases => :f
|
26
|
+
def tail
|
27
|
+
cmd = "tail#{options[:follow] ? ' -f' : ''} -n 25 #{daemon.log_file.to_path}"
|
28
|
+
puts "\n\n[Zeusd] exec(#{cmd})\n\n"
|
29
|
+
exec(cmd)
|
29
30
|
end
|
30
31
|
|
31
32
|
protected
|
32
33
|
|
33
34
|
def daemon
|
34
|
-
Zeusd::Daemon.new(
|
35
|
-
:verbose => options[:verbose],
|
36
|
-
:cwd => options[:cwd]
|
37
|
-
)
|
35
|
+
Zeusd::Daemon.new(:verbose => options[:verbose], :cwd => options[:cwd])
|
38
36
|
end
|
39
37
|
|
40
38
|
end
|
data/lib/zeusd.rb
CHANGED
data/lib/zeusd/daemon.rb
CHANGED
@@ -1,78 +1,113 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'childprocess'
|
3
3
|
require 'pathname'
|
4
|
+
require 'hooks'
|
4
5
|
|
5
6
|
module Zeusd
|
6
7
|
class DaemonException < StandardError; end
|
7
8
|
|
8
9
|
class Daemon
|
9
|
-
|
10
|
-
|
11
|
-
attr_reader :state
|
12
|
-
attr_reader :child_process, :reader, :writer
|
10
|
+
include Hooks
|
11
|
+
define_hooks :after_output, :after_start!, :after_stop!, :after_start_process!
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@queue = Queue.new
|
18
|
-
@state = StateInterpreter.new
|
19
|
-
on_update(&method(:puts)) if verbose
|
20
|
-
end
|
13
|
+
after_start! { log(:start) }
|
14
|
+
after_stop! { log(:stop) }
|
15
|
+
after_output {|x| log(x, :zeus) }
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
Zeusd::Process.kill!(processes.map(&:pid))
|
26
|
-
end
|
17
|
+
after_start_process! :ensure_log_worker
|
18
|
+
|
19
|
+
after_stop! do
|
27
20
|
(socket_file.delete rescue nil) if socket_file.exist?
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
@process = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
after_output do |output|
|
25
|
+
interpreter.translate(output)
|
26
|
+
puts(output) if verbose?
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :cwd, :verbose, :log_file, :log_queue, :interpreter, :child_process
|
30
|
+
|
31
|
+
def initialize(options = {})
|
32
|
+
@cwd = Pathname.new(options.fetch(:cwd, Dir.pwd)).realpath
|
33
|
+
@verbose = options.fetch(:verbose, false)
|
34
|
+
@interpreter = Interpreter.new
|
34
35
|
end
|
35
36
|
|
36
37
|
def start!(options = {})
|
37
|
-
@process = Zeusd::Process.find(
|
38
|
+
@process = Zeusd::Process.find(start_process!.pid)
|
38
39
|
|
39
40
|
if options.fetch(:block, false)
|
40
|
-
|
41
|
-
if loaded?
|
42
|
-
puts state.last_status
|
43
|
-
break
|
44
|
-
end
|
45
|
-
sleep(0.1)
|
46
|
-
end
|
41
|
+
sleep(0.1) until loaded?
|
47
42
|
end
|
48
43
|
|
49
|
-
|
44
|
+
self
|
45
|
+
ensure
|
46
|
+
run_hook :after_start!
|
50
47
|
end
|
51
48
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
49
|
+
def restart!(options = {})
|
50
|
+
stop!.start!(options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop!
|
54
|
+
return self unless process
|
55
|
+
|
56
|
+
# Kill Pids and Wait
|
57
|
+
process.kill!(:recursive => true, :wait => true)
|
58
|
+
|
59
|
+
# Check for remaining processes
|
60
|
+
if[process, process.descendants].flatten.select(&:alive?).any?
|
61
|
+
raise DaemonException, "Unable to KILL processes: " + alive_processes.join(', ')
|
55
62
|
end
|
63
|
+
|
64
|
+
self
|
65
|
+
ensure
|
66
|
+
run_hook :after_stop!
|
67
|
+
end
|
68
|
+
|
69
|
+
def process
|
70
|
+
@process ||= Process.all.find {|p| !!p.command[/zeus.*start$/] && p.cwd == cwd }
|
56
71
|
end
|
57
72
|
|
58
73
|
def loaded?
|
59
|
-
|
74
|
+
interpreter.complete?
|
60
75
|
end
|
61
76
|
|
62
|
-
|
63
|
-
|
64
|
-
|
77
|
+
|
78
|
+
def log_file
|
79
|
+
cwd.join('log/zeusd.log')
|
65
80
|
end
|
66
81
|
|
67
82
|
def socket_file
|
68
83
|
cwd.join('.zeus.sock')
|
69
84
|
end
|
70
85
|
|
86
|
+
def verbose?
|
87
|
+
!!verbose
|
88
|
+
end
|
89
|
+
|
71
90
|
protected
|
72
91
|
|
73
|
-
def
|
92
|
+
def log(entry, type = :zeusd)
|
93
|
+
log_queue << "<#{type.to_s} utc='#{Time.now.utc}'>#{entry}</#{type.to_s}>\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
def log_queue
|
97
|
+
@log_queue ||= Queue.new
|
98
|
+
end
|
99
|
+
|
100
|
+
def ensure_log_worker
|
101
|
+
@log_worker ||= Thread.new do
|
102
|
+
while value = log_queue.shift
|
103
|
+
log_file.open("a+") {|f| f.write(value) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def start_process!
|
74
109
|
@reader, @writer = IO.pipe
|
75
|
-
@child_process
|
110
|
+
@child_process = ChildProcess.build("zeus", "start")
|
76
111
|
@child_process.environment["BUNDLE_GEMFILE"] = cwd.join("Gemfile").to_path
|
77
112
|
@child_process.io.stdout = @child_process.io.stderr = @writer
|
78
113
|
@child_process.cwd = cwd.to_path
|
@@ -80,22 +115,15 @@ module Zeusd
|
|
80
115
|
@child_process.start
|
81
116
|
@writer.close
|
82
117
|
|
83
|
-
|
84
|
-
while (buffer = (reader.readpartial(10000) rescue nil)) do
|
85
|
-
state << buffer
|
86
|
-
queue << buffer
|
87
|
-
end
|
88
|
-
end
|
118
|
+
run_hook :after_start_process!
|
89
119
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
on_update.call(output)
|
94
|
-
end
|
120
|
+
Thread.new do
|
121
|
+
while (buffer = (@reader.readpartial(10000) rescue nil)) do
|
122
|
+
run_hook :after_output, buffer
|
95
123
|
end
|
96
124
|
end
|
97
125
|
|
98
|
-
sleep
|
126
|
+
sleep 0.1 until interpreter.commands.any?
|
99
127
|
|
100
128
|
@child_process
|
101
129
|
end
|
@@ -1,23 +1,22 @@
|
|
1
|
-
require 'stringio'
|
2
1
|
module Zeusd
|
3
|
-
class
|
2
|
+
class Interpreter
|
4
3
|
STATES = %w[ready crashed running connecting waiting]
|
5
4
|
|
6
5
|
attr_reader :lines
|
7
6
|
attr_reader :state_colors, :commands, :errors
|
7
|
+
attr_reader :last_status
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
@state_colors = Hash[STATES.zip([nil]*STATES.length)]
|
11
11
|
@commands = {}
|
12
12
|
@errors = []
|
13
13
|
@lines = []
|
14
|
-
super(*args)
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
16
|
+
def translate(zeus_output)
|
17
|
+
zeus_output.split("\n").map{|x| Line.new(x) }.each do |line|
|
19
18
|
# State Colors
|
20
|
-
if @state_colors.values.any?(&:nil?) && line.
|
19
|
+
if @state_colors.values.any?(&:nil?) && line.state_legend?
|
21
20
|
STATES.each do |state|
|
22
21
|
state_colors[state] = line.color_of(state)
|
23
22
|
end
|
@@ -32,15 +31,22 @@ module Zeusd
|
|
32
31
|
# Add Line
|
33
32
|
@lines << line
|
34
33
|
end
|
34
|
+
|
35
|
+
# Garbage Collection
|
36
|
+
if @lines.length > 100
|
37
|
+
@lines = @lines.last(100)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
|
37
|
-
def
|
41
|
+
def complete?
|
38
42
|
return false if errors.any?
|
39
|
-
return true if commands.all? {|command, status| %[crashed
|
43
|
+
return true if commands.all? {|command, status| %[crashed ready].include?(status)}
|
40
44
|
false
|
41
45
|
end
|
42
46
|
|
43
|
-
|
47
|
+
|
48
|
+
|
49
|
+
def last_update
|
44
50
|
@lines[@lines.rindex(&:update?)..-1].join("\n").to_s
|
45
51
|
end
|
46
52
|
|
@@ -55,12 +61,12 @@ module Zeusd
|
|
55
61
|
end
|
56
62
|
|
57
63
|
def command
|
58
|
-
if match
|
59
|
-
{ :name => match[2], :color => match[1] }
|
64
|
+
if @match ||= self.match(/^(\e.*?)zeus\s(.*?)(\s|\e)/)
|
65
|
+
{ :name => @match[2], :color => @match[1] }
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
63
|
-
def
|
69
|
+
def state_legend?
|
64
70
|
STATES.all?{|state| !!self[state]}
|
65
71
|
end
|
66
72
|
|
data/lib/zeusd/process.rb
CHANGED
@@ -7,11 +7,15 @@ module Zeusd
|
|
7
7
|
"stat" => ->(x){x.to_s},
|
8
8
|
"command" => ->(x){x.to_s}
|
9
9
|
}
|
10
|
-
attr_accessor :attributes
|
11
|
-
attr_accessor :children
|
10
|
+
attr_accessor :attributes, :children
|
12
11
|
|
13
|
-
def initialize(
|
14
|
-
|
12
|
+
def initialize(attributes_or_pid)
|
13
|
+
if attributes_or_pid.is_a? Hash
|
14
|
+
self.attributes = attributes_or_pid
|
15
|
+
else
|
16
|
+
self.attributes = {"pid" => attributes_or_pid.to_i}
|
17
|
+
reload!
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
def self.ps(options = {})
|
@@ -35,17 +39,10 @@ module Zeusd
|
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
38
|
-
# Note: Non-chinable, AND joined, Proc allowed for value
|
39
|
-
# {"attr" => value}
|
40
42
|
def self.where(criteria, options = {})
|
41
43
|
all(options).select do |process|
|
42
44
|
criteria.all? do |key, value|
|
43
|
-
|
44
|
-
when Array then value.include?(process.send(key))
|
45
|
-
when Proc then !!value.call(process)
|
46
|
-
else
|
47
|
-
process.send(key) == value
|
48
|
-
end
|
45
|
+
process.send(key) == value
|
49
46
|
end
|
50
47
|
end
|
51
48
|
end
|
@@ -56,12 +53,24 @@ module Zeusd
|
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
56
|
+
def self.wait(pids = [])
|
57
|
+
pids = Array(pids).map(&:to_s)
|
58
|
+
loop do
|
59
|
+
break if (self.ps.map{|x| x["pid"]} & pids).length.zero?
|
60
|
+
sleep(0.1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
59
64
|
def self.kill!(pids, options = {})
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
+
pids = Array(pids).map(&:to_i).select{|x| x > 0}
|
66
|
+
processes = pids.map{|pid| self.new(pid)}
|
67
|
+
signal = options.fetch(:signal, "TERM")
|
68
|
+
wait = options.fetch(:wait, false)
|
69
|
+
return false if processes.any?(&:dead?)
|
70
|
+
|
71
|
+
if system("kill -#{signal} #{processes.map(&:pid).join(' ')}")
|
72
|
+
self.wait(pids) if wait
|
73
|
+
true
|
65
74
|
else
|
66
75
|
false
|
67
76
|
end
|
@@ -69,7 +78,7 @@ module Zeusd
|
|
69
78
|
|
70
79
|
def reload!
|
71
80
|
self.attributes = self.class.ps(:pid => pid).first || {}
|
72
|
-
@children
|
81
|
+
@children = nil
|
73
82
|
!attributes.empty?
|
74
83
|
end
|
75
84
|
|
@@ -112,8 +121,14 @@ module Zeusd
|
|
112
121
|
end
|
113
122
|
|
114
123
|
def kill!(options = {})
|
115
|
-
|
116
|
-
|
124
|
+
return false if dead?
|
125
|
+
opts = options.dup
|
126
|
+
|
127
|
+
pids = [pid].tap do |x|
|
128
|
+
x.concat(descendants.map(&:pid)) if !!opts.delete(:recursive)
|
129
|
+
end
|
130
|
+
|
131
|
+
self.class.kill!(pids, opts)
|
117
132
|
end
|
118
133
|
|
119
134
|
def descendants(options = {})
|
@@ -123,11 +138,7 @@ module Zeusd
|
|
123
138
|
end
|
124
139
|
|
125
140
|
def children(options = {})
|
126
|
-
@children = self.class.where("ppid" => pid)
|
127
|
-
if options.fetch(:recursive, false)
|
128
|
-
processes.each{|p| p.children(options)}
|
129
|
-
end
|
130
|
-
end
|
141
|
+
@children = self.class.where("ppid" => pid)
|
131
142
|
end
|
132
143
|
|
133
144
|
def attributes=(hash)
|
data/lib/zeusd/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/zeusd/daemon_spec.rb
CHANGED
@@ -3,23 +3,51 @@ require 'spec_helper'
|
|
3
3
|
describe Zeusd::Daemon do
|
4
4
|
let(:daemon) { Zeusd::Daemon.new(:cwd => DUMMY_APP_PATH) }
|
5
5
|
after(:each) { daemon.stop! }
|
6
|
+
|
6
7
|
describe ".start!" do
|
8
|
+
subject { daemon.start!(:verbose => true) }
|
9
|
+
it { should be daemon }
|
10
|
+
it { should_not be_loaded }
|
7
11
|
|
8
|
-
|
12
|
+
describe ":block option" do
|
9
13
|
subject { daemon.start!(:block => true) }
|
10
|
-
it { should
|
14
|
+
it { should be_loaded }
|
15
|
+
end
|
16
|
+
end
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
describe ".stop!" do
|
19
|
+
subject { daemon.start!.stop! }
|
20
|
+
it { should be daemon }
|
21
|
+
it { should_not be_loaded }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".restart!" do
|
25
|
+
subject { daemon }
|
26
|
+
context "when daemon is already running" do
|
27
|
+
before { subject.start!.restart!(:block => true) }
|
28
|
+
it { should be_loaded }
|
16
29
|
end
|
30
|
+
end
|
17
31
|
|
18
|
-
|
19
|
-
|
20
|
-
|
32
|
+
describe ".process" do
|
33
|
+
context "before start" do
|
34
|
+
subject { daemon.process }
|
35
|
+
it { should be_nil }
|
21
36
|
end
|
22
37
|
|
38
|
+
context "after start" do
|
39
|
+
subject { daemon.start!.process }
|
40
|
+
it { should be_a Zeusd::Process}
|
41
|
+
it { should be_alive }
|
42
|
+
its "a zeus start process" do
|
43
|
+
subject.command.should match(/zeus.*?start$/)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "after start and stop" do
|
48
|
+
subject { daemon.start!.stop!.process }
|
49
|
+
it { should be_nil }
|
50
|
+
end
|
23
51
|
end
|
24
52
|
|
25
53
|
end
|
data/spec/zeusd/process_spec.rb
CHANGED
@@ -1,16 +1,83 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'benchmark'
|
2
3
|
require 'zeusd'
|
3
4
|
|
4
5
|
describe Zeusd::Process do
|
5
6
|
|
6
|
-
def spawn_dummy_process(
|
7
|
-
|
7
|
+
def spawn_dummy_process(ttl = 1, usr1delay = 0.5, options = {})
|
8
|
+
ttl = ttl.to_f.to_s
|
9
|
+
usr1delay = usr1delay.to_f.to_s
|
10
|
+
script = File.expand_path("../../support/dummy_process.rb", __FILE__)
|
11
|
+
p = ChildProcess.build(script, ttl, usr1delay)
|
12
|
+
p.cwd = options[:cwd] if options[:cwd]
|
13
|
+
p.detach = true
|
14
|
+
p.start
|
15
|
+
p
|
8
16
|
end
|
9
17
|
|
18
|
+
before(:each) do
|
19
|
+
@dummy_ttl = 1
|
20
|
+
@dummy_usr1delay = 0.5
|
21
|
+
@dummy_process = spawn_dummy_process(@dummy_ttl, @dummy_usr1delay)
|
22
|
+
end
|
10
23
|
subject(:model) { Zeusd::Process }
|
11
24
|
|
12
|
-
|
13
|
-
|
25
|
+
|
26
|
+
describe "process instance" do
|
27
|
+
subject { model.find(@dummy_process.pid) }
|
28
|
+
it { should be_a Zeusd::Process }
|
29
|
+
it { should be_alive }
|
30
|
+
it { should_not be_dead }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "instance methods" do
|
34
|
+
subject { model.find(@dummy_process.pid) }
|
35
|
+
|
36
|
+
describe ".cwd" do
|
37
|
+
it "return the current working directory" do
|
38
|
+
subject.cwd.to_path == Dir.pwd
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe ".kill!" do
|
43
|
+
context "when process exists" do
|
44
|
+
it "kills the process and returns true" do
|
45
|
+
subject.kill!(:wait => true).should be_true
|
46
|
+
subject.should be_dead
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when processes does not exists" do
|
51
|
+
it "returns false" do
|
52
|
+
subject.kill!(:wait => true).should be_true
|
53
|
+
subject.kill!.should be_false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
describe "class methods" do
|
61
|
+
|
62
|
+
describe "::kill!" do
|
63
|
+
it "kills a process in under 0.1 seconds" do
|
64
|
+
model.kill!(@dummy_process.pid)
|
65
|
+
sleep 0.1
|
66
|
+
model.find(@dummy_process.pid).should be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
it "blocks until the process exits" do
|
70
|
+
Benchmark.realtime do
|
71
|
+
model.kill!(@dummy_process.pid, :signal => "USR1", :wait => true).should be_true
|
72
|
+
end.should be < 1.0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "::wait" do
|
77
|
+
it "blocks until the process exits" do
|
78
|
+
Benchmark.realtime { model.wait(@dummy_process.pid) }.should be > 1
|
79
|
+
end
|
80
|
+
end
|
14
81
|
|
15
82
|
describe "::ps" do
|
16
83
|
subject { model.ps }
|
@@ -19,7 +86,7 @@ describe Zeusd::Process do
|
|
19
86
|
subject.all?{|x| x.is_a?(Hash)}.should be_true
|
20
87
|
end
|
21
88
|
it "includes the dummy process" do
|
22
|
-
subject.map{|x|x["pid"]}.should include(@
|
89
|
+
subject.map{|x|x["pid"]}.should include(@dummy_process.pid.to_s)
|
23
90
|
end
|
24
91
|
it "allows additional -o keywords" do
|
25
92
|
model.ps(:keywords => "user").first.should include("user")
|
@@ -60,7 +127,7 @@ describe Zeusd::Process do
|
|
60
127
|
it { should have_at_least(2).items }
|
61
128
|
end
|
62
129
|
context "criteria not met" do
|
63
|
-
subject {model.where(:pid => @
|
130
|
+
subject {model.where(:pid => @dummy_process.pid, :pgid => 9999999999999)}
|
64
131
|
it { should be_an Array }
|
65
132
|
it { should be_empty }
|
66
133
|
end
|
@@ -68,14 +135,14 @@ describe Zeusd::Process do
|
|
68
135
|
end
|
69
136
|
|
70
137
|
describe "::find" do
|
71
|
-
subject { model.find(@
|
138
|
+
subject { model.find(@dummy_process.pid) }
|
72
139
|
context "existing process" do
|
73
140
|
it { should be_a Zeusd::Process }
|
74
141
|
it { should be_alive }
|
75
|
-
it { subject.pid.should eq(@
|
142
|
+
it { subject.pid.should eq(@dummy_process.pid) }
|
76
143
|
end
|
77
144
|
context "non-existant process" do
|
78
|
-
before(:each) {
|
145
|
+
before(:each) { @dummy_process.stop }
|
79
146
|
it { should be_nil }
|
80
147
|
end
|
81
148
|
end
|
data/zeusd.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zeusd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-02-
|
12
|
+
date: 2014-02-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: hooks
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: zeus
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,8 +142,8 @@ files:
|
|
126
142
|
- bin/zeusd
|
127
143
|
- lib/zeusd.rb
|
128
144
|
- lib/zeusd/daemon.rb
|
145
|
+
- lib/zeusd/interpreter.rb
|
129
146
|
- lib/zeusd/process.rb
|
130
|
-
- lib/zeusd/state_interpreter.rb
|
131
147
|
- lib/zeusd/version.rb
|
132
148
|
- spec/dummy/.gitignore
|
133
149
|
- spec/dummy/Gemfile
|
@@ -180,6 +196,7 @@ files:
|
|
180
196
|
- spec/dummy/vendor/plugins/.gitkeep
|
181
197
|
- spec/dummy/zeus.json
|
182
198
|
- spec/spec_helper.rb
|
199
|
+
- spec/support/dummy_process.rb
|
183
200
|
- spec/zeusd/daemon_spec.rb
|
184
201
|
- spec/zeusd/process_spec.rb
|
185
202
|
- zeusd.gemspec
|
@@ -198,7 +215,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
198
215
|
version: '0'
|
199
216
|
segments:
|
200
217
|
- 0
|
201
|
-
hash: -
|
218
|
+
hash: -3204481942119935445
|
202
219
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
203
220
|
none: false
|
204
221
|
requirements:
|
@@ -207,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
224
|
version: '0'
|
208
225
|
segments:
|
209
226
|
- 0
|
210
|
-
hash: -
|
227
|
+
hash: -3204481942119935445
|
211
228
|
requirements: []
|
212
229
|
rubyforge_project:
|
213
230
|
rubygems_version: 1.8.25
|
@@ -266,5 +283,6 @@ test_files:
|
|
266
283
|
- spec/dummy/vendor/plugins/.gitkeep
|
267
284
|
- spec/dummy/zeus.json
|
268
285
|
- spec/spec_helper.rb
|
286
|
+
- spec/support/dummy_process.rb
|
269
287
|
- spec/zeusd/daemon_spec.rb
|
270
288
|
- spec/zeusd/process_spec.rb
|