process_control 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +23 -0
- data/.gemtest +0 -0
- data/History.txt +6 -0
- data/Manifest.txt +8 -0
- data/README.txt +93 -0
- data/Rakefile +26 -0
- data/bin/process_control +60 -0
- data/lib/process_control.rb +155 -0
- data/test/test_process_control.rb +16 -0
- metadata +114 -0
data/.autotest
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
# Autotest.add_hook :initialize do |at|
|
6
|
+
# at.extra_files << "../some/external/dependency.rb"
|
7
|
+
#
|
8
|
+
# at.libs << ":../some/external"
|
9
|
+
#
|
10
|
+
# at.add_exception 'vendor'
|
11
|
+
#
|
12
|
+
# at.add_mapping(/dependency.rb/) do |f, _|
|
13
|
+
# at.files_matching(/test_.*rb$/)
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# %w(TestA TestB).each do |klass|
|
17
|
+
# at.extra_class_map[klass] = "test/test_misc.rb"
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
# Autotest.add_hook :run_command do |at|
|
22
|
+
# system "rake build"
|
23
|
+
# end
|
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
= process_control
|
2
|
+
|
3
|
+
* http://cyberconnect.biz/opensource
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Process Control is a wrapper to allow easy control for any external daemon type process. The
|
8
|
+
Process Control app is minimal, such that there should never be any errors and the process can
|
9
|
+
run in a daemon state yielding a consistant means for controlling a child process. The child
|
10
|
+
process being controlled is done so via signals, QUIT, CONT, HUP, USR1 and TERM (see SIGNALS
|
11
|
+
section).
|
12
|
+
|
13
|
+
== FEATURES
|
14
|
+
|
15
|
+
* Monitor interval: Sleep time between each cycle.
|
16
|
+
* Monitor exec: Child command to execute. Command should be a standalone daemon
|
17
|
+
that doesn't not exit.
|
18
|
+
* Monitor exec_live_cfg, optional config file to be passed to the exec attribute if you have more
|
19
|
+
than one config file. If your application being controlled only requires one config file put
|
20
|
+
the config parameter in the exec string itself.
|
21
|
+
* Monitor exec_maintenance_cfg config file to use when your application is in maintenance mode
|
22
|
+
* Monitor kill_signal: Signal to use when stopping the child process, defalting to TERM.
|
23
|
+
* Monitor kill_children: If the child process defined by exec launches additional processes,
|
24
|
+
kill all children of the exec process.
|
25
|
+
* Monitor usr1: User defined Proc to execute. This is usefull for external system monitoring.
|
26
|
+
For example, the Proc could create a tmp file, and when USR1 is sent to the process_control pid
|
27
|
+
that tmp file would be created. Now the external monotor has an easy means to ensure that the
|
28
|
+
process_control process is functioning properly.
|
29
|
+
* Monitors the process launched defined by exec, and if not found running, starts it.
|
30
|
+
|
31
|
+
== SIGNALS
|
32
|
+
|
33
|
+
Signals need to be sent to the process_control process and not the child spawned. Process Control in turn will perform actions based on the signal provided.
|
34
|
+
|
35
|
+
* QUIT: Kill the child process, and puts the monitoring of the child process in a halt state. If exec_live_cfg and exec_maintenance_cfg are set, swap the config file from live to maintenance and start the process. Multiple config files are handy when you have down time to a web site and you need to display a certain page to the user while you upgrade your application.
|
36
|
+
* CONT: Start the child process, and enables the monitor to restart the child process if found not running. If exec_live_cfg and exec_maintenance_cfg are set the config file is set to live before the application is started.
|
37
|
+
* HUP: Restart the child process
|
38
|
+
* TERM: Stop both the child process and process_control itself
|
39
|
+
* USR1: Execute the Proc code block defined in the config
|
40
|
+
|
41
|
+
== SYNOPSIS:
|
42
|
+
|
43
|
+
/usr/bin/process_control --config <full path to config file>
|
44
|
+
|
45
|
+
Example config file for a web agent running as a daemon, outside of the web framework itself. If
|
46
|
+
the code below was saved in a file named /tmp/start_cert.rb you would launch cert.rb via process_control by:
|
47
|
+
|
48
|
+
process_control --config /tmp/start_cert.rb
|
49
|
+
|
50
|
+
ProcessControl.run { |monitor|
|
51
|
+
monitor.interval = 10
|
52
|
+
monitor.exec = "ruby /cyber_platform/vendor/plugins/phased_layer_tunnel/agents/cert.rb"
|
53
|
+
monitor.kill_children = true
|
54
|
+
monitor.kill_signal='TERM'
|
55
|
+
monitor.usr1 = Proc.new {
|
56
|
+
status_f = "/share/status/cyber_platform_cert.rb"
|
57
|
+
begin
|
58
|
+
FileUtils.rm_f status_f if File.exists?(status_f)
|
59
|
+
rescue => e
|
60
|
+
end
|
61
|
+
begin
|
62
|
+
fd = File.open(status_f, 'w+')
|
63
|
+
fd.close
|
64
|
+
rescue => e
|
65
|
+
end
|
66
|
+
}
|
67
|
+
monitor.monitor # required last line, or child process will not be launched
|
68
|
+
}
|
69
|
+
|
70
|
+
Example for nginx hosting a rails application given live and maintenance configurations. When QUIT is sent to process_control the maintenance config file will be utilized so that users will still be able to access the site, but given an explanation there's maintenance. And when CONT is sent, toggle the config back to live, restoring the full functionality of the application:
|
71
|
+
|
72
|
+
ProcessControl.run { |monitor|
|
73
|
+
monitor.interval = 10
|
74
|
+
monitor.exec = "/usr/local/nginx/sbin/nginx -c"
|
75
|
+
monitor.exec_live_cfg = "/cyber_platform/config/nginx.conf"
|
76
|
+
monitor.exec_maintenance_cfg = "/cyber_platform/config/nginx.conf.maintenance"
|
77
|
+
monitor.kill_children = false
|
78
|
+
monitor.kill_signal='QUIT'
|
79
|
+
monitor.monitor # required last line, or child process will not be launched
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
== REQUIREMENTS:
|
84
|
+
|
85
|
+
Tested on GNU/Linux, but should work on other variants of Unix type OS's as well.
|
86
|
+
|
87
|
+
== INSTALL:
|
88
|
+
|
89
|
+
* sudo gem install process_control
|
90
|
+
|
91
|
+
== LICENSE:
|
92
|
+
|
93
|
+
GPLv3: http://www.gnu.org/licenses/gpl.html
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
# Hoe.plugin :compiler
|
7
|
+
# Hoe.plugin :gem_prelude_sucks
|
8
|
+
# Hoe.plugin :inline
|
9
|
+
# Hoe.plugin :racc
|
10
|
+
# Hoe.plugin :rubyforge
|
11
|
+
|
12
|
+
Hoe.spec 'process_control' do
|
13
|
+
# HEY! If you fill these out in ~/.hoe_template/Rakefile.erb then
|
14
|
+
# you'll never have to touch them again!
|
15
|
+
# (delete this comment too, of course)
|
16
|
+
|
17
|
+
# developer('FIX', 'FIX@example.com')
|
18
|
+
|
19
|
+
# self.rubyforge_name = 'process_controlx' # if different than 'process_control'
|
20
|
+
developer('', 'cliff.cyphers@gmail.com')
|
21
|
+
extra_deps << 'platform_helpers'
|
22
|
+
extra_deps << 'wait_for'
|
23
|
+
extra_deps << 'process_mgt'
|
24
|
+
end
|
25
|
+
|
26
|
+
# vim: syntax=ruby
|
data/bin/process_control
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Authod: Cliff Cyphers
|
4
|
+
# Published as part of the cyberconnect's platform mainly used
|
5
|
+
# in hosting rails applications.
|
6
|
+
# Licesnse: GPLv3: http://www.gnu.org/licenses/gpl.html
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'process_mgt'
|
12
|
+
require 'process_control'
|
13
|
+
require 'getoptlong'
|
14
|
+
|
15
|
+
module Init
|
16
|
+
def run
|
17
|
+
opts = GetoptLong.new( [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
18
|
+
[ '--config', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
19
|
+
[ '--exec', '-e', GetoptLong::REQUIRED_ARGUMENT ] )
|
20
|
+
dir = nil
|
21
|
+
name = nil
|
22
|
+
repetitions = 1
|
23
|
+
opts.each { |opt, arg|
|
24
|
+
case opt
|
25
|
+
when '--help'
|
26
|
+
RDoc::usage
|
27
|
+
when '--config'
|
28
|
+
type = 'config'
|
29
|
+
f = File.expand_path("#{arg}")
|
30
|
+
raise StandardError, "config file not found: #{f}" unless File.exists?(f)
|
31
|
+
self_pid = Process.pid
|
32
|
+
#p "SELF: #{self_pid}"
|
33
|
+
all_pids = ProcessMgt.pids_with_children(:search => "--config #{arg}")
|
34
|
+
#p "ALL_PIDS: #{all_pids}"
|
35
|
+
kill_pids = all_pids.gsub(/#{self_pid}/, '')
|
36
|
+
#p "KILL_PIDS: #{kill_pids}"
|
37
|
+
ProcessMgt.kill(:pid_list => kill_pids)
|
38
|
+
#ProcessMgt.kill(:search => "--config #{arg}")
|
39
|
+
load f
|
40
|
+
when '--exec'
|
41
|
+
type = 'exec'
|
42
|
+
begin
|
43
|
+
ProcessControl.run { |monitor|
|
44
|
+
monitor.interval = 5
|
45
|
+
monitor.exec = arg
|
46
|
+
monitor.kill_children = true
|
47
|
+
monitor.kill_signal='TERM'
|
48
|
+
monitor.monitor
|
49
|
+
}
|
50
|
+
rescue => e
|
51
|
+
end
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
module_function :run
|
57
|
+
end
|
58
|
+
|
59
|
+
Init.run
|
60
|
+
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# Authod: Cliff Cyphers
|
2
|
+
# Published as part of the cyberconnect's platform mainly used
|
3
|
+
# in hosting rails applications.
|
4
|
+
# Licesnse: GPLv3: http://www.gnu.org/licenses/gpl.html
|
5
|
+
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'wait_for'
|
9
|
+
BASE = File.expand_path(File.dirname(__FILE__)) + '/..'
|
10
|
+
require "process_mgt"
|
11
|
+
|
12
|
+
|
13
|
+
class ProcessHellFire
|
14
|
+
attr_accessor :exec, :interval, :kill_children, :exec_live_cfg, :exec_maintenance_cfg, :kill_signal, :usr1
|
15
|
+
def initialize
|
16
|
+
@exec = ''
|
17
|
+
@orig_exec = ''
|
18
|
+
@wait_until_timeout = 0
|
19
|
+
@wait_until_proc = nil
|
20
|
+
@kill_children = kill_children
|
21
|
+
@interval = interval
|
22
|
+
@restart_items = []
|
23
|
+
@exec_live_cfg = ''
|
24
|
+
@exec_maintenance_cfg = ''
|
25
|
+
@kill_signal = 'TERM'
|
26
|
+
@restart = true
|
27
|
+
@usr1= ''
|
28
|
+
@mode = 'live'
|
29
|
+
end
|
30
|
+
|
31
|
+
def logger
|
32
|
+
begin
|
33
|
+
require BASE + '/lib/log'
|
34
|
+
include InlineLogger
|
35
|
+
rescue => e
|
36
|
+
puts "EEEEE: #{e.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def wait_until(timeout=10, proc_='')
|
41
|
+
raise StandardError unless proc_.kind_of?(Proc)
|
42
|
+
@wait_until_timeout = timeout
|
43
|
+
@wait_until_proc = proc_
|
44
|
+
end
|
45
|
+
|
46
|
+
def restart_on_condition(condition)
|
47
|
+
@restart_items << condition
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def monitor
|
52
|
+
raise StandardError if @exec == '' || @interval < 2
|
53
|
+
set_traps
|
54
|
+
while true
|
55
|
+
exec = use_exec
|
56
|
+
pids = ProcessMgt.pids_with_children(:search => exec, :exclude => 'process_control')
|
57
|
+
res=false
|
58
|
+
@restart_items.each { |item|
|
59
|
+
begin
|
60
|
+
next unless item.respond_to?(:call)
|
61
|
+
res = item.call
|
62
|
+
break if res == true
|
63
|
+
rescue => e
|
64
|
+
end
|
65
|
+
}
|
66
|
+
if (pids == '' || res) && @restart
|
67
|
+
restart
|
68
|
+
end
|
69
|
+
sleep @interval
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def stop
|
74
|
+
stop_items = []
|
75
|
+
|
76
|
+
if @exec_live_cfg == '' && @exec_maintenance_cfg == ''
|
77
|
+
stop_items << @exec
|
78
|
+
else
|
79
|
+
stop_items += [@exec_live_cfg, @exec_maintenance_cfg]
|
80
|
+
end
|
81
|
+
|
82
|
+
stop_items.each { |exec|
|
83
|
+
p "stop with exec: #{exec}"
|
84
|
+
begin
|
85
|
+
if @kill_children
|
86
|
+
ProcessMgt.kill(:search => exec, :with_children => nil, :force => true, :exclude => 'process_control')
|
87
|
+
else
|
88
|
+
ProcessMgt.kill(:search => exec, :signal => @kill_signal, :exclude => 'process_control')
|
89
|
+
end
|
90
|
+
rescue => e
|
91
|
+
puts "EEEEE: #{e.inspect}"
|
92
|
+
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def start
|
97
|
+
cfg = use_exec
|
98
|
+
Thread.new {
|
99
|
+
begin
|
100
|
+
Process.fork {Process.exec(cfg)}
|
101
|
+
@pid, status = Process.wait2
|
102
|
+
rescue => e
|
103
|
+
p e.inspect
|
104
|
+
end
|
105
|
+
}
|
106
|
+
wait_for(@wait_until_timeout) { @wait_until_proc } if @wait_until_proc.kind_of?(Proc)
|
107
|
+
end
|
108
|
+
|
109
|
+
def restart
|
110
|
+
stop
|
111
|
+
start
|
112
|
+
end
|
113
|
+
|
114
|
+
def use_exec
|
115
|
+
if @exec_live_cfg != '' && @exec_maintenance_cfg != ''
|
116
|
+
if @mode == 'live'
|
117
|
+
return "#{@exec} #{@exec_live_cfg}"
|
118
|
+
else
|
119
|
+
return "#{@exec} #{@exec_maintenance_cfg}"
|
120
|
+
end
|
121
|
+
else
|
122
|
+
return @exec
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def set_traps
|
127
|
+
trap('TERM') {
|
128
|
+
stop
|
129
|
+
exit
|
130
|
+
}
|
131
|
+
trap('HUP') { restart }
|
132
|
+
trap('QUIT') {
|
133
|
+
@mode = 'maintenance'
|
134
|
+
@restart = false
|
135
|
+
restart
|
136
|
+
}
|
137
|
+
trap('CONT') {
|
138
|
+
@mode = 'live'
|
139
|
+
restart
|
140
|
+
@restart = true
|
141
|
+
}
|
142
|
+
trap('USR1') { @usr1.call if @usr1.kind_of?(Proc) }
|
143
|
+
end
|
144
|
+
|
145
|
+
private :set_traps, :start, :stop, :restart, :use_exec
|
146
|
+
end
|
147
|
+
|
148
|
+
module ProcessControl
|
149
|
+
VERSION = '0.1.0'
|
150
|
+
def self.run(&blk)
|
151
|
+
raise ArgumentError unless block_given?
|
152
|
+
cfg = ProcessHellFire.new()
|
153
|
+
yield cfg
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Authod: Cliff Cyphers
|
2
|
+
# Published as part of the cyberconnect's platform mainly used
|
3
|
+
# in hosting rails applications.
|
4
|
+
# Licesnse: GPLv3: http://www.gnu.org/licenses/gpl.html
|
5
|
+
|
6
|
+
|
7
|
+
require "./lib/process_control"
|
8
|
+
require 'process_mgt'
|
9
|
+
require "test/unit"
|
10
|
+
|
11
|
+
class TestProcessControl < Test::Unit::TestCase
|
12
|
+
def test_
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: process_control
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- ""
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-22 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: platform_helpers
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: wait_for
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: process_mgt
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: hoe
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "2.12"
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
description: |-
|
60
|
+
Process Control is a wrapper to allow easy control for any external daemon type process. The
|
61
|
+
Process Control app is minimal, such that there should never be any errors and the process can
|
62
|
+
run in a daemon state yielding a consistant means for controlling a child process. The child
|
63
|
+
process being controlled is done so via signals, QUIT, CONT, HUP, USR1 and TERM (see SIGNALS
|
64
|
+
section).
|
65
|
+
email:
|
66
|
+
- cliff.cyphers@gmail.com
|
67
|
+
executables:
|
68
|
+
- process_control
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- History.txt
|
73
|
+
- Manifest.txt
|
74
|
+
- README.txt
|
75
|
+
files:
|
76
|
+
- .autotest
|
77
|
+
- History.txt
|
78
|
+
- Manifest.txt
|
79
|
+
- README.txt
|
80
|
+
- Rakefile
|
81
|
+
- bin/process_control
|
82
|
+
- lib/process_control.rb
|
83
|
+
- test/test_process_control.rb
|
84
|
+
- .gemtest
|
85
|
+
homepage: http://cyberconnect.biz/opensource
|
86
|
+
licenses: []
|
87
|
+
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options:
|
90
|
+
- --main
|
91
|
+
- README.txt
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project: process_control
|
109
|
+
rubygems_version: 1.8.8
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Process Control is a wrapper to allow easy control for any external daemon type process
|
113
|
+
test_files:
|
114
|
+
- test/test_process_control.rb
|