cmdb 2.6.2 → 3.0.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +71 -34
- data/Gemfile +4 -3
- data/Gemfile.lock +6 -19
- data/LICENSE +25 -0
- data/README.md +138 -166
- data/Rakefile +13 -0
- data/cmdb.gemspec +1 -3
- data/docker-compose.yml +15 -0
- data/exe/cmdb +36 -9
- data/lib/cmdb/commands/help.rb +21 -66
- data/lib/cmdb/commands/shell.rb +165 -0
- data/lib/cmdb/commands/shim.rb +13 -128
- data/lib/cmdb/commands.rb +1 -0
- data/lib/cmdb/interface.rb +51 -59
- data/lib/cmdb/shell/dsl.rb +73 -0
- data/lib/cmdb/shell/printer.rb +115 -0
- data/lib/cmdb/shell/text.rb +65 -0
- data/lib/cmdb/shell.rb +8 -0
- data/lib/cmdb/source/consul.rb +90 -0
- data/lib/cmdb/{file_source.rb → source/file.rb} +15 -34
- data/lib/cmdb/source/memory.rb +39 -0
- data/lib/cmdb/source/network.rb +104 -0
- data/lib/cmdb/source.rb +94 -0
- data/lib/cmdb/version.rb +1 -1
- data/lib/cmdb.rb +26 -17
- metadata +18 -36
- data/TODO.md +0 -3
- data/lib/cmdb/consul_source.rb +0 -83
data/docker-compose.yml
ADDED
data/exe/cmdb
CHANGED
@@ -20,37 +20,64 @@ CMDB::Commands.constants.each do |konst|
|
|
20
20
|
commands[name] = CMDB::Commands.const_get(konst.to_sym)
|
21
21
|
end
|
22
22
|
|
23
|
-
# Use a Trollop parser for help/banner display, but do not actually parse
|
24
|
-
# anything just yet.
|
25
23
|
command_list = commands.keys - ['help']
|
26
24
|
command_info = command_list.map { |c| " * #{c}" }.join("\n")
|
25
|
+
|
26
|
+
# Use a Trollop parser for help/banner display, but do not actually parse
|
27
|
+
# anything just yet.
|
27
28
|
p = Trollop::Parser.new do
|
28
29
|
version "cmdb #{gemspec_version} (c) 2013-2014 RightScale, Inc."
|
29
30
|
banner <<-EOS
|
30
31
|
A command-line interface for configuration management.
|
31
32
|
|
32
33
|
Usage:
|
33
|
-
cmdb <command> [options]
|
34
|
+
cmdb [options] <command> [command-options]
|
34
35
|
|
35
36
|
Where <command> is one of:
|
36
37
|
#{command_info}
|
37
38
|
|
38
|
-
To get help on a command:
|
39
|
-
cmdb help command
|
39
|
+
To get help on a specific command and its options:
|
40
|
+
cmdb help <command>
|
41
|
+
|
42
|
+
Common options that apply to all commands:
|
40
43
|
EOS
|
41
44
|
|
45
|
+
opt :source,
|
46
|
+
"Source of CMDB inputs e.g. file:///foo.yml or consul://localhost",
|
47
|
+
type: :string,
|
48
|
+
multi: true
|
49
|
+
|
50
|
+
opt :quiet,
|
51
|
+
"Suppress unnecessary output",
|
52
|
+
default: false
|
53
|
+
|
42
54
|
stop_on commands.keys
|
43
55
|
end
|
44
56
|
|
45
57
|
Trollop.with_standard_exception_handling p do
|
46
58
|
raise Trollop::HelpNeeded if ARGV.empty?
|
47
|
-
|
59
|
+
|
60
|
+
# Apply global options
|
61
|
+
options = p.parse ARGV
|
62
|
+
CMDB.log.level = Logger::FATAL if options[:quiet]
|
63
|
+
|
64
|
+
if options[:source].empty?
|
65
|
+
sources = CMDB::Source.detect
|
66
|
+
else
|
67
|
+
sources = options[:source].map do |source|
|
68
|
+
CMDB::Source.create(source)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
interface = CMDB::Interface.new(*sources)
|
73
|
+
|
74
|
+
# Identify the subcommand and run it (or print help).
|
75
|
+
raise Trollop::HelpNeeded if ARGV.empty?
|
48
76
|
cmd = ARGV.shift
|
49
77
|
klass = commands[cmd]
|
50
|
-
|
51
78
|
if klass
|
52
|
-
klass.create.run
|
79
|
+
klass.create(interface).run
|
53
80
|
else
|
54
|
-
|
81
|
+
CMDB.log.fatal "Unrecognized command '#{cmd}'; try 'cmdb --help'"
|
55
82
|
end
|
56
83
|
end
|
data/lib/cmdb/commands/help.rb
CHANGED
@@ -1,77 +1,32 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'logger'
|
3
|
-
require 'listen'
|
4
2
|
|
5
3
|
module CMDB::Commands
|
6
4
|
class Help
|
7
|
-
def self.create
|
8
|
-
|
9
|
-
|
10
|
-
The 'shim' command adapts your applications for use with CMDB without coupling them to
|
11
|
-
the CMDB RubyGem (or forcing you to write your applications in Ruby). It works by
|
12
|
-
manipulating the environment or filesystem to make CMDB inputs visible, then invoking
|
13
|
-
your app.
|
14
|
-
|
15
|
-
To use the shim with apps that read configuration from the filesystem, use the --dir
|
16
|
-
option to tell the shim where to rewrite configuration files. It will look for tokens
|
17
|
-
in JSON or YML that look like <<cmdb.key.name>> and replace them with the value of
|
18
|
-
the specified key.
|
19
|
-
|
20
|
-
To use the shim with 12-factor apps, use the --env option to tell the shim to load
|
21
|
-
every CMDB key into the environment. When using --env, the prefix of each key is
|
22
|
-
omitted from the environment variable name, e.g. "common.database.host" is
|
23
|
-
represented as DATABASE_HOST.
|
24
|
-
|
25
|
-
To support "development mode" and reload your app whenever its files change on disk,
|
26
|
-
use the --reload option and specify the name of a CMDB key that will enable this
|
27
|
-
behavior.
|
28
|
-
|
29
|
-
Usage:
|
30
|
-
cmdb shim [options] -- <command_to_exec> [options_for_command]
|
31
|
-
|
32
|
-
Where [options] are selected from:
|
33
|
-
EOS
|
34
|
-
opt :dir,
|
35
|
-
'Directory to scan for key-replacement tokens in data files',
|
36
|
-
type: :string
|
37
|
-
opt :consul_url,
|
38
|
-
'The URL for talking to consul',
|
39
|
-
type: :string
|
40
|
-
opt :consul_prefix,
|
41
|
-
'The prefix to use when getting keys from consul, can be specified more than once',
|
42
|
-
type: :string,
|
43
|
-
multi: true
|
44
|
-
opt :keys,
|
45
|
-
'Override search path(s) for CMDB key files',
|
46
|
-
type: :strings
|
47
|
-
opt :pretend,
|
48
|
-
'Check for errors, but do not actually launch the app or rewrite files',
|
49
|
-
default: false
|
50
|
-
opt :quiet,
|
51
|
-
"Don't print any output",
|
52
|
-
default: false
|
53
|
-
opt :reload,
|
54
|
-
'CMDB key that enables reload-on-edit',
|
55
|
-
type: :string
|
56
|
-
opt :reload_signal,
|
57
|
-
'Signal to send to app server when code is edited',
|
58
|
-
type: :string,
|
59
|
-
default: 'HUP'
|
60
|
-
opt :env,
|
61
|
-
"Add CMDB keys to the app server's process environment",
|
62
|
-
default: false
|
63
|
-
opt :user,
|
64
|
-
'Switch to named user before executing app',
|
65
|
-
type: :string
|
66
|
-
opt :root,
|
67
|
-
'Promote named subkey to the root when it is present in a namespace',
|
68
|
-
type: :string
|
69
|
-
end
|
5
|
+
def self.create(interface)
|
6
|
+
new(interface, ARGV.first)
|
7
|
+
end
|
70
8
|
|
71
|
-
|
9
|
+
def initialize(interface, command)
|
10
|
+
@cmdb = interface
|
11
|
+
@command = command
|
72
12
|
end
|
73
13
|
|
74
14
|
def run
|
15
|
+
if @command.nil? || @command.empty?
|
16
|
+
# Same as "--help"
|
17
|
+
raise Trollop::HelpNeeded
|
18
|
+
end
|
19
|
+
|
20
|
+
# Find the command the user was talking about and print some help
|
21
|
+
konst = CMDB::Commands.constants.detect { |konst| konst.to_s.downcase == @command }
|
22
|
+
if konst
|
23
|
+
klass = CMDB::Commands.const_get(konst)
|
24
|
+
ARGV.clear ; ARGV.push('--help')
|
25
|
+
klass.create(@cmdb)
|
26
|
+
else
|
27
|
+
CMDB.log.fatal "CMDB: Unknown command '#{@command}'; try 'cmdb --help' for a list of commands"
|
28
|
+
exit 1
|
29
|
+
end
|
75
30
|
end
|
76
31
|
end
|
77
32
|
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CMDB::Commands
|
4
|
+
class Shell
|
5
|
+
# Character that acts as a separator between key components. The standard
|
6
|
+
# notation uses `.` but Shell allow allows `/` for a more filesystem-like
|
7
|
+
# user experience.
|
8
|
+
ALT_SEPARATOR = '/'.freeze
|
9
|
+
|
10
|
+
# Directory navigation shortcuts ('.' and '..')
|
11
|
+
NAVIGATION = /^#{Regexp.escape(CMDB::SEPARATOR + CMDB::SEPARATOR)}?$/.freeze
|
12
|
+
|
13
|
+
def self.create(interface)
|
14
|
+
require 'cmdb/shell'
|
15
|
+
|
16
|
+
options = Trollop.options do
|
17
|
+
banner <<-EOS
|
18
|
+
The 'shell' command enters a Unix-like shell where you can interact with
|
19
|
+
CMDB sources and inspect the value of keys.
|
20
|
+
|
21
|
+
Usage:
|
22
|
+
cmdb shell
|
23
|
+
EOS
|
24
|
+
end
|
25
|
+
|
26
|
+
new(interface)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [CMDB::Interface]
|
30
|
+
attr_reader :cmdb
|
31
|
+
|
32
|
+
# @return [Array] the "present working directory" (i.e. key prefix) for shell commands
|
33
|
+
attr_accessor :pwd
|
34
|
+
|
35
|
+
# @return [Object] esult of the most recent command
|
36
|
+
attr_accessor :_
|
37
|
+
|
38
|
+
# @param [CMDB::Interface] interface
|
39
|
+
def initialize(interface)
|
40
|
+
@cmdb = interface
|
41
|
+
@pwd = []
|
42
|
+
@out = CMDB::Shell::Printer.new
|
43
|
+
end
|
44
|
+
|
45
|
+
# Run the shim.
|
46
|
+
#
|
47
|
+
# @raise [SystemExit] if something goes wrong
|
48
|
+
def run
|
49
|
+
@dsl = CMDB::Shell::DSL.new(self, @out)
|
50
|
+
repl
|
51
|
+
end
|
52
|
+
|
53
|
+
# Given a key name/prefix relative to `pwd`, return the absolute
|
54
|
+
# name/prefix. If `pwd` is empty, just return `subpath`. The subpath
|
55
|
+
# can use either dotted or slash notation, and directory navigation
|
56
|
+
# symbols (`.` and `..`) are applied as expected if the subpath uses
|
57
|
+
# slash notation.
|
58
|
+
#
|
59
|
+
# @return [String] absolute key in dotted notation
|
60
|
+
def expand_path(subpath)
|
61
|
+
pieces = subpath.split(ALT_SEPARATOR)
|
62
|
+
|
63
|
+
if subpath[0] == ALT_SEPARATOR
|
64
|
+
result = []
|
65
|
+
else
|
66
|
+
result = pwd.dup
|
67
|
+
end
|
68
|
+
|
69
|
+
if subpath.include?(ALT_SEPARATOR) || subpath =~ NAVIGATION
|
70
|
+
# filesystem-like subpath
|
71
|
+
# apply Unix-style directory navigation shortcuts
|
72
|
+
pieces.each do |piece|
|
73
|
+
case piece
|
74
|
+
when '..' then result.pop
|
75
|
+
when '.' then nil
|
76
|
+
else result.push(piece)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
result.join(CMDB::SEPARATOR)
|
81
|
+
else
|
82
|
+
# standard dotted notation
|
83
|
+
result += pieces
|
84
|
+
end
|
85
|
+
|
86
|
+
result.join(CMDB::SEPARATOR)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def repl
|
92
|
+
require 'readline'
|
93
|
+
while line = Readline.readline(@out.prompt(self), true)
|
94
|
+
begin
|
95
|
+
line = line.chomp
|
96
|
+
next if line.nil? || line.empty?
|
97
|
+
words = line.split(/\s+/)
|
98
|
+
command, args = words.first.to_sym, words[1..-1]
|
99
|
+
|
100
|
+
run_ruby(command, args) || run_getter(line) || run_setter(line) ||
|
101
|
+
fail(CMDB::BadCommand.new(command))
|
102
|
+
handle_output(self._)
|
103
|
+
rescue => e
|
104
|
+
handle_error(e) || raise
|
105
|
+
end
|
106
|
+
end
|
107
|
+
rescue Interrupt
|
108
|
+
return 0
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Boolean] true if line was handled as a normal command
|
112
|
+
def run_ruby(command, args)
|
113
|
+
self._ = @dsl.__send__(command, *args)
|
114
|
+
true
|
115
|
+
rescue NoMethodError
|
116
|
+
false
|
117
|
+
rescue ArgumentError => e
|
118
|
+
raise CMDB::BadCommand.new(e.message, command)
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Boolean] true if line was handled as a getter
|
122
|
+
def run_getter(key)
|
123
|
+
if value = @dsl.get(key)
|
124
|
+
self._ = value
|
125
|
+
true
|
126
|
+
else
|
127
|
+
false
|
128
|
+
end
|
129
|
+
rescue CMDB::Error
|
130
|
+
false
|
131
|
+
end
|
132
|
+
|
133
|
+
# @return [Boolean] true if line was handled as a setter
|
134
|
+
def run_setter(line)
|
135
|
+
key, value = line.strip.split(/\s*=\s*/, 2)
|
136
|
+
return false unless key && value
|
137
|
+
|
138
|
+
value = nil unless value && value.length > 0
|
139
|
+
self._ = @dsl.set(key, value)
|
140
|
+
true
|
141
|
+
rescue CMDB::Error
|
142
|
+
false
|
143
|
+
end
|
144
|
+
|
145
|
+
def handle_output(obj)
|
146
|
+
case obj
|
147
|
+
when Hash
|
148
|
+
@out.keys_values(obj)
|
149
|
+
else
|
150
|
+
@out.value(obj)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [Boolean] print message and return true if error is handled; else return false
|
155
|
+
def handle_error(e)
|
156
|
+
case e
|
157
|
+
when CMDB::BadCommand
|
158
|
+
@out.error "#{e.command}: #{e.message}"
|
159
|
+
true
|
160
|
+
else
|
161
|
+
false
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/cmdb/commands/shim.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require 'logger'
|
3
|
-
require 'listen'
|
4
2
|
|
5
3
|
module CMDB::Commands
|
6
4
|
class Shim
|
7
|
-
def self.create
|
5
|
+
def self.create(interface)
|
8
6
|
options = Trollop.options do
|
9
7
|
banner <<-EOS
|
10
8
|
The 'shim' command adapts your applications for use with CMDB without coupling them to
|
@@ -12,7 +10,7 @@ the CMDB RubyGem (or forcing you to write your applications in Ruby). It works b
|
|
12
10
|
manipulating the environment or filesystem to make CMDB inputs visible, then invoking
|
13
11
|
your app.
|
14
12
|
|
15
|
-
To use the shim with apps that read configuration from the filesystem, use the --
|
13
|
+
To use the shim with apps that read configuration from the filesystem, use the --rewrite
|
16
14
|
option to tell the shim where to rewrite configuration files. It will look for tokens
|
17
15
|
in JSON or YML that look like <<cmdb.key.name>> and replace them with the value of
|
18
16
|
the specified key.
|
@@ -22,53 +20,28 @@ every CMDB key into the environment. When using --env, the prefix of each key is
|
|
22
20
|
omitted from the environment variable name, e.g. "common.database.host" is
|
23
21
|
represented as DATABASE_HOST.
|
24
22
|
|
25
|
-
To support "development mode" and reload your app whenever its files change on disk,
|
26
|
-
use the --reload option and specify the name of a CMDB key that will enable this
|
27
|
-
behavior.
|
28
|
-
|
29
23
|
Usage:
|
30
24
|
cmdb shim [options] -- <command_to_exec> [options_for_command]
|
31
25
|
|
32
26
|
Where [options] are selected from:
|
33
27
|
EOS
|
34
|
-
opt :
|
28
|
+
opt :rewrite,
|
35
29
|
'Directory to scan for key-replacement tokens in data files',
|
36
30
|
type: :string
|
37
|
-
opt :consul_url,
|
38
|
-
'The URL for talking to consul',
|
39
|
-
type: :string
|
40
|
-
opt :consul_prefix,
|
41
|
-
'The prefix to use when getting keys from consul, can be specified more than once',
|
42
|
-
type: :string,
|
43
|
-
multi: true
|
44
|
-
opt :keys,
|
45
|
-
'Override search path(s) for CMDB key files',
|
46
|
-
type: :strings
|
47
31
|
opt :pretend,
|
48
32
|
'Check for errors, but do not actually launch the app or rewrite files',
|
49
33
|
default: false
|
50
|
-
opt :quiet,
|
51
|
-
"Don't print any output",
|
52
|
-
default: false
|
53
|
-
opt :reload,
|
54
|
-
'CMDB key that enables reload-on-edit',
|
55
|
-
type: :string
|
56
|
-
opt :reload_signal,
|
57
|
-
'Signal to send to app server when code is edited',
|
58
|
-
type: :string,
|
59
|
-
default: 'HUP'
|
60
34
|
opt :env,
|
61
35
|
"Add CMDB keys to the app server's process environment",
|
62
36
|
default: false
|
63
37
|
opt :user,
|
64
38
|
'Switch to named user before executing app',
|
65
39
|
type: :string
|
66
|
-
opt :root,
|
67
|
-
'Promote named subkey to the root when it is present in a namespace',
|
68
|
-
type: :string
|
69
40
|
end
|
41
|
+
options.delete(:help)
|
70
42
|
|
71
|
-
|
43
|
+
options.delete_if { |k, v| k.to_s =~ /_given$/i }
|
44
|
+
new(interface, ARGV, **options)
|
72
45
|
end
|
73
46
|
|
74
47
|
# Irrevocably change the current user for this Unix process by calling the
|
@@ -90,35 +63,18 @@ Where [options] are selected from:
|
|
90
63
|
|
91
64
|
# Create a Shim.
|
92
65
|
# @param [Array] command collection of string to pass to Kernel#exec; 0th element is the command name
|
93
|
-
|
94
|
-
|
66
|
+
def initialize(interface, command, rewrite:, pretend:, user:)
|
67
|
+
@cmdb = interface
|
95
68
|
@command = command
|
96
|
-
@dir =
|
97
|
-
@
|
98
|
-
@
|
99
|
-
@keys = options[:keys] || []
|
100
|
-
@pretend = options[:pretend]
|
101
|
-
@reload = options[:reload]
|
102
|
-
@signal = options[:reload_signal]
|
103
|
-
@env = options[:env]
|
104
|
-
@user = options[:user]
|
105
|
-
@root = options[:root]
|
106
|
-
|
107
|
-
CMDB::FileSource.base_directories = @keys unless @keys.empty?
|
108
|
-
CMDB::ConsulSource.url = @consul_url unless @consul_url.nil?
|
109
|
-
if !@consul_prefixes.nil? && !@consul_prefixes.empty?
|
110
|
-
CMDB::ConsulSource.prefixes = @consul_prefixes
|
111
|
-
end
|
112
|
-
|
113
|
-
CMDB.log.level = Logger::FATAL if options[:quiet]
|
69
|
+
@dir = rewrite
|
70
|
+
@pretend = pretend
|
71
|
+
@user = user
|
114
72
|
end
|
115
73
|
|
116
74
|
# Run the shim.
|
117
75
|
#
|
118
76
|
# @raise [SystemExit] if something goes wrong
|
119
77
|
def run
|
120
|
-
@cmdb = CMDB::Interface.new(root: @root)
|
121
|
-
|
122
78
|
rewrote = rewrite_files
|
123
79
|
populated = populate_environment
|
124
80
|
|
@@ -187,8 +143,6 @@ Where [options] are selected from:
|
|
187
143
|
|
188
144
|
# @return [Boolean]
|
189
145
|
def populate_environment
|
190
|
-
return false unless @env
|
191
|
-
|
192
146
|
env = @cmdb.to_h
|
193
147
|
|
194
148
|
env.keys.each do |k|
|
@@ -207,81 +161,12 @@ Where [options] are selected from:
|
|
207
161
|
|
208
162
|
def launch_app
|
209
163
|
if @command.any?
|
210
|
-
# log this now, so that it gets logged even if @pretend
|
211
164
|
CMDB.log.info "App will run as user #{@user}" if @user
|
212
|
-
|
213
|
-
|
214
|
-
CMDB.log.info "SIG#{@signal}-on-edit is enabled; fork app"
|
215
|
-
fork_and_watch_app unless @pretend
|
216
|
-
else
|
217
|
-
CMDB.log.info "SIG#{@signal}-on-edit is disabled; exec app"
|
218
|
-
exec_app unless @pretend
|
219
|
-
end
|
165
|
+
self.class.drop_privileges(@user) if @user
|
166
|
+
exec(*@command)
|
220
167
|
end
|
221
168
|
end
|
222
169
|
|
223
|
-
def exec_app
|
224
|
-
self.class.drop_privileges(@user) if @user
|
225
|
-
exec(*@command)
|
226
|
-
end
|
227
|
-
|
228
|
-
def fork_and_watch_app
|
229
|
-
# let the child share our stdio handles on purpose
|
230
|
-
pid = fork do
|
231
|
-
exec_app
|
232
|
-
end
|
233
|
-
|
234
|
-
CMDB.log.info('App (pid %d) has been forked; watching %s' % [pid, ::Dir.pwd])
|
235
|
-
|
236
|
-
t0 = Time.at(0)
|
237
|
-
|
238
|
-
listener = Listen.to(::Dir.pwd) do |modified, added, removed|
|
239
|
-
modified = modified.select { |fn| interesting?(fn) }
|
240
|
-
added = added.select { |fn| interesting?(fn) }
|
241
|
-
removed = removed.select { |fn| interesting?(fn) }
|
242
|
-
next if modified.empty? && added.empty? && removed.empty?
|
243
|
-
|
244
|
-
begin
|
245
|
-
dt = Time.now - t0
|
246
|
-
if dt > 15
|
247
|
-
Process.kill(@signal, pid)
|
248
|
-
CMDB.log.info 'Sent SIG%s to app (pid %d) because (modified,created,deleted)=(%d,%d,%d)' %
|
249
|
-
[@signal, pid, modified.size, added.size, removed.size]
|
250
|
-
t0 = Time.now
|
251
|
-
else
|
252
|
-
CMDB.log.error 'Skipped SIG%s to app (pid %d) due to timeout (%d)' %
|
253
|
-
[@signal, pid, dt]
|
254
|
-
end
|
255
|
-
rescue
|
256
|
-
CMDB.log.error 'Skipped SIG%s to app (pid %d) due to %s' %
|
257
|
-
[@signal, pid, $ERROR_INFO.to_s]
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
listener.start
|
262
|
-
|
263
|
-
wpid = nil
|
264
|
-
wstatus = nil
|
265
|
-
|
266
|
-
loop do
|
267
|
-
begin
|
268
|
-
wpid, wstatus = Process.wait2(-1, Process::WNOHANG)
|
269
|
-
if wpid
|
270
|
-
break if wstatus.exited?
|
271
|
-
CMDB.log.info('Descendant (pid %d) has waited with %s' % [wpid, wstatus.inspect])
|
272
|
-
end
|
273
|
-
rescue
|
274
|
-
CMDB.log.error 'Skipped wait2 to app (pid %d) due to %s' %
|
275
|
-
[pid, $ERROR_INFO.to_s]
|
276
|
-
end
|
277
|
-
sleep(1)
|
278
|
-
end
|
279
|
-
|
280
|
-
CMDB.log.info('App (pid %d) has exited with %s' % [wpid, wstatus.inspect])
|
281
|
-
listener.stop
|
282
|
-
exit(wstatus.exitstatus || 43)
|
283
|
-
end
|
284
|
-
|
285
170
|
def report_rewrite(total)
|
286
171
|
CMDB.log.info "Replaced #{total} variables in #{@dir}"
|
287
172
|
end
|