phantom-manager 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.DS_Store +0 -0
- data/.gitignore +3 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/bin/phantom_monitor +55 -0
- data/config/config.yml +27 -0
- data/lib/.DS_Store +0 -0
- data/lib/monitors/base.rb +39 -0
- data/lib/monitors/memory.rb +27 -0
- data/lib/monitors/processes.rb +33 -0
- data/lib/monitors/restart_listener.rb +39 -0
- data/lib/monitors/violations_recorders/base.rb +56 -0
- data/lib/monitors/violations_recorders/memory.rb +23 -0
- data/lib/monitors/violations_recorders/processes.rb +21 -0
- data/lib/nginx/manager.rb +59 -0
- data/lib/phantom/.DS_Store +0 -0
- data/lib/phantom/collector.rb +36 -0
- data/lib/phantom/manager/version.rb +5 -0
- data/lib/phantom/manager.rb +34 -0
- data/lib/phantom/process.rb +54 -0
- data/lib/utils/cfg.rb +18 -0
- data/lib/utils/limited_array.rb +31 -0
- data/lib/utils/lock.rb +29 -0
- data/lib/utils/logger.rb +3 -0
- data/lib/utils/shell.rb +12 -0
- data/phantom-manager.gemspec +24 -0
- data/spec/files/config.yml +12 -0
- data/spec/files/nginx.conf +26 -0
- data/spec/lib/monitors/base_spec.rb +14 -0
- data/spec/lib/monitors/memory_spec.rb +33 -0
- data/spec/lib/monitors/processes_spec.rb +45 -0
- data/spec/lib/monitors/restart_listener_spec.rb +27 -0
- data/spec/lib/monitors/violations_recorders/base_spec.rb +126 -0
- data/spec/lib/monitors/violations_recorders/memory_spec.rb +73 -0
- data/spec/lib/monitors/violations_recorders/processes_spec.rb +51 -0
- data/spec/lib/nginx/manager_spec.rb +80 -0
- data/spec/lib/phantom/collector_spec.rb +59 -0
- data/spec/lib/phantom/manager_spec.rb +25 -0
- data/spec/lib/phantom/process_spec.rb +47 -0
- data/spec/lib/utils/limited_array_spec.rb +73 -0
- data/spec/lib/utils/lock_spec.rb +69 -0
- data/spec/lib/utils/shell_spec.rb +18 -0
- data/spec/shared_spec.rb +45 -0
- data/spec/spec_helper.rb +29 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmU1OGFhZGQzODQ2NGJkNjkwN2FkNmM3ZWI0NTE3ZWI4NWY5NzEzNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGJjMTI5Yzk1NjVkOTczM2E4MWEyMWM2NGMxMmQ2NmUzMTdmYjM4MQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjI3NTQwNDNjMWVmZGRkYzk3NTYzZmE5MDE4YmFiNjkwNGFjMmJmMTkxOWE0
|
10
|
+
ODQ1MTRlYzY3NjFmMzg0MjZiZGM5ODIyOWY2NWY0NjgyNWQ0M2UyZTI1NDcx
|
11
|
+
MDMxZmUzZTM0OTVlMzFmYWVkNGI5MGNiZDVjNzEyYTU2Yjk3MmE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzdkODY4MjYyNDc4MzFmYjlhNTc2NGE2MDg5MmMwOWI2ZTA4ZjI4ZTkwYTA2
|
14
|
+
YTU2OTdlMjI4MmJlNmUyZmEyYzAxOWE5ZWQyMzQzZDdiNWRmYWFmNWM5ODRj
|
15
|
+
ZDJiYjUzNTU4YzcyYmYyZTlhZTdiZmEzZDhmOGUzYTQwZjcyMGQ=
|
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
phantom-manager (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
columnize (0.3.6)
|
10
|
+
debugger (1.4.0)
|
11
|
+
columnize (>= 0.3.1)
|
12
|
+
debugger-linecache (~> 1.1.1)
|
13
|
+
debugger-ruby_core_source (~> 1.2.0)
|
14
|
+
debugger-linecache (1.1.2)
|
15
|
+
debugger-ruby_core_source (>= 1.1.1)
|
16
|
+
debugger-ruby_core_source (1.2.0)
|
17
|
+
diff-lcs (1.2.4)
|
18
|
+
rake (10.1.0)
|
19
|
+
rspec (2.14.1)
|
20
|
+
rspec-core (~> 2.14.0)
|
21
|
+
rspec-expectations (~> 2.14.0)
|
22
|
+
rspec-mocks (~> 2.14.0)
|
23
|
+
rspec-core (2.14.3)
|
24
|
+
rspec-expectations (2.14.0)
|
25
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
26
|
+
rspec-mocks (2.14.1)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bundler (~> 1.3)
|
33
|
+
debugger
|
34
|
+
phantom-manager!
|
35
|
+
rake
|
36
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Erez Rabih
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Phantom::Manager
|
2
|
+
|
3
|
+
phantom-manager allows you to use multiple phantom-js processes behind an Nginx
|
4
|
+
server. It will manage both presence and memory consumption of those processes
|
5
|
+
and kill them when appropriate, all this in sync with the Nginx configuration
|
6
|
+
so that all requests will get answered.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'phantom-manager'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install phantom-manager
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
TODO: Write usage instructions here
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Fork it
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
32
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/phantom_monitor
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
$options = {}
|
6
|
+
|
7
|
+
optparse = OptionParser.new do |opts|
|
8
|
+
|
9
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
10
|
+
puts opts
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
opts.on( '-c', '--config FILE', "Configuration file path" ) do |f|
|
15
|
+
$options[:config] = f
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on( '-e', '--env ENVIRONMENT', "Environment to run on" ) do |env|
|
19
|
+
$options[:env] = env
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
optparse.parse!
|
25
|
+
|
26
|
+
mandatory = [:env, :config]
|
27
|
+
missing = mandatory.select{ |param| $options[param].nil? }
|
28
|
+
|
29
|
+
if not missing.empty?
|
30
|
+
puts "Missing options: #{missing.join(', ')}"
|
31
|
+
puts optparse
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
lib = File.expand_path('../../lib', __FILE__)
|
36
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
37
|
+
|
38
|
+
require 'phantom/manager/version'
|
39
|
+
require 'monitors/memory.rb'
|
40
|
+
require 'monitors/processes.rb'
|
41
|
+
require 'monitors/restart_listener.rb'
|
42
|
+
|
43
|
+
|
44
|
+
$logger.info "Starting for environment #{$options[:env]} with config file #{$options[:config]}... "
|
45
|
+
|
46
|
+
Monitors::RestartListener.run
|
47
|
+
|
48
|
+
$logger.info "Running memory monitor for phantom processes"
|
49
|
+
|
50
|
+
Thread.new {Monitors::Memory.run}
|
51
|
+
|
52
|
+
$logger.info "Running processes monitor for phantom processes"
|
53
|
+
|
54
|
+
Thread.new {Monitors::Processes.run}.join
|
55
|
+
|
data/config/config.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
development:
|
2
|
+
#The time to wait between removing a phantomjs from the nginx configuration
|
3
|
+
#and actually killing the process.
|
4
|
+
phantom_termination_grace: 10
|
5
|
+
|
6
|
+
#This will be the inital port of the phantomjs processes. For example if
|
7
|
+
#phantom_processes_number is set to 4 and phantom_base_port to 8000 then 4
|
8
|
+
#phantoms, on ports 8000 8001 8002 8003 will be managed.
|
9
|
+
phantom_base_port: 8002
|
10
|
+
#Rails root path
|
11
|
+
rails_root: "path"
|
12
|
+
#Path to your nginx configuration
|
13
|
+
nginx_conf: "path"
|
14
|
+
#Path to where you want to keep your phantomjs logs
|
15
|
+
phantom_log_path: "path"
|
16
|
+
#If a phantom process memory consumption is over memory_limit for
|
17
|
+
#memory_retries times with memory_check_interval between each check it will
|
18
|
+
#be killed
|
19
|
+
memory_limit: 150000
|
20
|
+
memory_retries: 5
|
21
|
+
memory_check_interval: 5
|
22
|
+
#Number of phantom processes to keep up. If a process is missing for
|
23
|
+
#processes_check_retries times in a row with processes_check_interval between
|
24
|
+
#checks it will be brought up byt the monitor
|
25
|
+
phantom_processes_number: 10
|
26
|
+
processes_check_retries: 3
|
27
|
+
processes_check_interval: 15
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'utils/cfg'
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'phantom/manager'
|
4
|
+
require 'phantom/collector'
|
5
|
+
|
6
|
+
module Monitors
|
7
|
+
class Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def run(custom_logger = $logger)
|
11
|
+
@logger = custom_logger
|
12
|
+
|
13
|
+
loop do
|
14
|
+
perform_check
|
15
|
+
sleep check_interval
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def perform_check
|
22
|
+
raise NotImplementedError.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def check_interval
|
26
|
+
raise NotImplementedError.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def running_instances
|
30
|
+
Phantom::Collector.get_running_instances
|
31
|
+
end
|
32
|
+
|
33
|
+
def logger
|
34
|
+
@logger ||= $logger
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'monitors/base'
|
2
|
+
require 'monitors/violations_recorders/memory'
|
3
|
+
|
4
|
+
module Monitors
|
5
|
+
class Memory < Base
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def perform_check
|
10
|
+
logger.info "Perfoming memory check..."
|
11
|
+
|
12
|
+
running_instances.each do |p|
|
13
|
+
if ViolationsRecorders::Memory.is_violating?(p)
|
14
|
+
logger.info "process #{p.pid} was found bad!"
|
15
|
+
Phantom::Manager.restart(p)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_interval
|
22
|
+
$cfg.memory_check_interval
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'monitors/base'
|
2
|
+
require 'monitors/violations_recorders/processes'
|
3
|
+
|
4
|
+
module Monitors
|
5
|
+
class Processes < Base
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def perform_check
|
9
|
+
logger.info "Perfoming processes check..."
|
10
|
+
|
11
|
+
missing_processes = Phantom::Collector.missing_ports.map do |port|
|
12
|
+
p = Phantom::Process.new
|
13
|
+
p.port = port
|
14
|
+
p
|
15
|
+
end
|
16
|
+
|
17
|
+
missing_processes.each do |p|
|
18
|
+
if ViolationsRecorders::Processes.is_violating?(p)
|
19
|
+
logger.info "found missing phantom on port #{p.port}"
|
20
|
+
Phantom::Manager.start(p)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
logger.info "All processes are running OK" if missing_processes.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_interval
|
28
|
+
$cfg.processes_check_interval
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'phantom/manager'
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'utils/cfg'
|
4
|
+
require 'utils/lock'
|
5
|
+
|
6
|
+
|
7
|
+
module Monitors
|
8
|
+
class RestartListener
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def run
|
12
|
+
Signal.trap("USR2") do
|
13
|
+
respond_to_signal
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to_signal
|
18
|
+
lock.acquire do
|
19
|
+
$logger.info "Initiating restart sequence"
|
20
|
+
|
21
|
+
Phantom::Collector.get_running_instances.each do |p|
|
22
|
+
$logger.info "Restarting process on port #{p.port}"
|
23
|
+
Phantom::Manager.restart(p)
|
24
|
+
|
25
|
+
sleep $cfg.phantom_termination_grace
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def lock
|
34
|
+
@lock ||= Utils::Lock.new
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
require 'phantom/process'
|
4
|
+
|
5
|
+
module Monitors
|
6
|
+
module ViolationsRecorders
|
7
|
+
class Base
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def inherited(base)
|
12
|
+
base.instance_variable_set(:@violations, {})
|
13
|
+
end
|
14
|
+
|
15
|
+
@violations = {}
|
16
|
+
|
17
|
+
def reset
|
18
|
+
@violations = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_violating?(process)
|
22
|
+
$logger.debug "checking #{process}"
|
23
|
+
update_violations_count(process)
|
24
|
+
$logger.debug "#{@violations}"
|
25
|
+
violating = @violations[process.send(process_attr)] == retries_limit
|
26
|
+
@violations[process.send(process_attr)] = 0 if violating
|
27
|
+
violating
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def update_violations_count(process)
|
33
|
+
@violations[process.send(process_attr)] ||= 0
|
34
|
+
if process_is_violating?(process)
|
35
|
+
@violations[process.send(process_attr)]+= 1
|
36
|
+
else
|
37
|
+
@violations[process.send(process_attr)] = 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def retries_limit
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_attr
|
46
|
+
raise NotImplementedError
|
47
|
+
end
|
48
|
+
|
49
|
+
def process_is_violating?(process)
|
50
|
+
raise NotImplementedError
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'monitors/violations_recorders/base'
|
2
|
+
|
3
|
+
module Monitors
|
4
|
+
module ViolationsRecorders
|
5
|
+
class Memory < Base
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def retries_limit
|
9
|
+
$cfg.memory_retries
|
10
|
+
end
|
11
|
+
|
12
|
+
def process_attr
|
13
|
+
:pid
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_is_violating?(process)
|
17
|
+
process.memory_usage > $cfg.memory_limit
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'monitors/violations_recorders/base'
|
2
|
+
|
3
|
+
module Monitors
|
4
|
+
module ViolationsRecorders
|
5
|
+
class Processes < Base
|
6
|
+
class << self
|
7
|
+
def retries_limit
|
8
|
+
$cfg.processes_check_retries
|
9
|
+
end
|
10
|
+
|
11
|
+
def process_attr
|
12
|
+
:port
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_is_violating?(process)
|
16
|
+
Phantom::Collector.missing_ports.include?(process.port)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
|
4
|
+
module Nginx
|
5
|
+
class Manager
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def remove(port)
|
9
|
+
$logger.info "removing #{port} from nginx"
|
10
|
+
modify_nginx do |ofile, iline|
|
11
|
+
ofile.puts(iline) unless iline =~ /#{port}/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(port)
|
16
|
+
$logger.info "adding #{port} to nginx"
|
17
|
+
if !port_defined?(port)
|
18
|
+
modify_nginx do |ofile, iline|
|
19
|
+
ofile.puts(iline)
|
20
|
+
ofile.puts(phantom_upstream(port)) if iline =~ /upstream phantomjs/
|
21
|
+
end
|
22
|
+
else
|
23
|
+
$logger.info "port #{port} already defined"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def phantom_upstream(port)
|
30
|
+
" server 127.0.0.1:#{port} fail_timeout=0; # #{Time.now}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def port_defined?(port)
|
34
|
+
File.readlines($cfg.nginx_conf).grep(/#{port}/).size > 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def switch_nginx_configs
|
38
|
+
$logger.info "switching nginx configurations"
|
39
|
+
`mv #{$cfg.new_nginx_conf} #{$cfg.nginx_conf}`
|
40
|
+
end
|
41
|
+
|
42
|
+
def reload_nginx
|
43
|
+
$logger.info "reloading nginx"
|
44
|
+
`nginx -s reload`
|
45
|
+
end
|
46
|
+
|
47
|
+
def modify_nginx
|
48
|
+
File.open($cfg.new_nginx_conf, "w") do |ofile|
|
49
|
+
File.foreach($cfg.nginx_conf) do |iline|
|
50
|
+
yield ofile, iline
|
51
|
+
end
|
52
|
+
end
|
53
|
+
switch_nginx_configs
|
54
|
+
reload_nginx
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
Binary file
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'phantom/process'
|
2
|
+
|
3
|
+
module Phantom
|
4
|
+
class Collector
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def on_port(port)
|
8
|
+
get_running_instances.find {|p| p.port == port}
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_running_instances
|
12
|
+
lines = running_phantoms_shell_output.split("\n")
|
13
|
+
lines.map {|l| Phantom::Process.from_string(l) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def missing_ports
|
17
|
+
required_ports - get_running_instances.map(&:port)
|
18
|
+
end
|
19
|
+
|
20
|
+
def required_ports
|
21
|
+
($cfg.phantom_base_port..($cfg.phantom_base_port+$cfg.phantom_processes_number-1)).to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def running_phantoms_shell_output
|
27
|
+
`#{running_phantoms_shell_command}`
|
28
|
+
end
|
29
|
+
|
30
|
+
def running_phantoms_shell_command
|
31
|
+
"ps -e -www -o pid,rss,command | grep 'phantomjs' | grep -v sh | grep -v grep"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "phantom/manager/version"
|
2
|
+
require 'utils/logger'
|
3
|
+
require 'utils/cfg'
|
4
|
+
require 'nginx/manager'
|
5
|
+
|
6
|
+
module Phantom
|
7
|
+
module Manager
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def restart(process)
|
11
|
+
$logger.info "restarting process #{process}"
|
12
|
+
stop process
|
13
|
+
start process
|
14
|
+
end
|
15
|
+
|
16
|
+
def start(process)
|
17
|
+
$logger.info "starting process #{process.port}"
|
18
|
+
process.start
|
19
|
+
Nginx::Manager.add(process.port)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def stop(process)
|
25
|
+
$logger.info "stopping process #{process}"
|
26
|
+
Nginx::Manager.remove(process.port)
|
27
|
+
sleep $cfg.phantom_termination_grace
|
28
|
+
process.kill
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'utils/logger'
|
2
|
+
require 'utils/cfg'
|
3
|
+
require 'utils/shell'
|
4
|
+
|
5
|
+
module Phantom
|
6
|
+
class Process
|
7
|
+
attr_accessor :pid, :memory_usage, :command, :port
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def from_string(str)
|
12
|
+
args = parse_string(str)
|
13
|
+
new(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parse_string(str)
|
19
|
+
parts = str.split
|
20
|
+
pid = parts[0].to_i
|
21
|
+
memory_usage = parts[1].to_i
|
22
|
+
command = parts[2..-1].join(" ")
|
23
|
+
port = parts.last.to_i
|
24
|
+
|
25
|
+
[pid, memory_usage, command, port]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(pid = nil, memory_usage = nil, command = nil, port = nil)
|
31
|
+
@pid = pid
|
32
|
+
@memory_usage = memory_usage
|
33
|
+
@command = command
|
34
|
+
@port = port
|
35
|
+
end
|
36
|
+
|
37
|
+
def kill
|
38
|
+
$logger.info "killing #{self}"
|
39
|
+
Utils::Shell.execute "kill #{pid}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def start
|
43
|
+
$logger.info "starting phantomjs on port #{port}"
|
44
|
+
Utils::Shell.execute start_command
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def start_command
|
50
|
+
"cd #{$cfg.rails_root} && phantomjs rndrme.js #{port} >>#{$cfg.phantom_log_path} 2>&1 &"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/utils/cfg.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class Cfg
|
5
|
+
def self.load
|
6
|
+
cfg = File.expand_path($options[:config])
|
7
|
+
env = $options[:env]
|
8
|
+
hash = YAML.load(File.open(cfg))[env]
|
9
|
+
hash.each do |k,v|
|
10
|
+
hash[k] = v.to_i if v =~ /^\d+$/
|
11
|
+
end
|
12
|
+
obj = OpenStruct.new hash
|
13
|
+
obj.new_nginx_conf = "#{obj.nginx_conf}.new"
|
14
|
+
|
15
|
+
$cfg = obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Cfg.load
|