right_popen 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/linux/right_popen.rb +25 -23
- data/lib/right_popen.rb +35 -2
- data/right_popen.gemspec +1 -1
- data/spec/print_env.rb +1 -0
- data/spec/right_popen_spec.rb +35 -7
- data/spec/spec_helper.rb +3 -1
- metadata +3 -2
data/lib/linux/right_popen.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#--
|
2
2
|
# Copyright (c) 2009 RightScale Inc
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
|
22
|
+
#++
|
23
23
|
|
24
24
|
# RightScale.popen3 allows running external processes aynchronously
|
25
25
|
# while still capturing their standard and error outputs.
|
@@ -99,33 +99,35 @@ module RightScale
|
|
99
99
|
# Forks process to run given command asynchronously, hooking all three
|
100
100
|
# standard streams of the child process.
|
101
101
|
#
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
# Calls given exit handler upon command process termination, passing in the
|
106
|
-
# resulting Process::Status.
|
107
|
-
#
|
108
|
-
# All handlers must be methods exposed by the given target.
|
109
|
-
#
|
110
|
-
# === Parameters
|
111
|
-
# cmd(String):: command to execute, including any arguments.
|
112
|
-
# target(Object):: object defining handler methods to be called.
|
113
|
-
# stdout_handler(String):: token for stdout handler method name.
|
114
|
-
# stderr_handler(String):: token for stderr handler method name.
|
115
|
-
# exit_handler(String):: token for exit handler method name.
|
116
|
-
#
|
117
|
-
# === Returns
|
118
|
-
# true:: Always returns true
|
119
|
-
def self.popen3(cmd, target, stdout_handler = nil, stderr_handler = nil, exit_handler = nil)
|
120
|
-
raise "EventMachine reactor must be started" unless EM.reactor_running?
|
102
|
+
# See RightScale.popen3
|
103
|
+
def self.popen3_imp(options)
|
104
|
+
cmd = options[:command].dup
|
121
105
|
GC.start # To garbage collect open file descriptors from passed executions
|
122
106
|
EM.next_tick do
|
123
107
|
saved_stderr = $stderr.dup
|
124
108
|
r, w = Socket::pair(Socket::AF_LOCAL, Socket::SOCK_STREAM, 0)#IO::pipe
|
125
109
|
|
126
110
|
$stderr.reopen w
|
127
|
-
c = EM.attach(r, StdErrHandler, target, stderr_handler, r) if stderr_handler
|
128
|
-
|
111
|
+
c = EM.attach(r, StdErrHandler, options[:target], options[:stderr_handler], r) if options[:stderr_handler]
|
112
|
+
|
113
|
+
# Setup environment for child process
|
114
|
+
envs = {}
|
115
|
+
options[:environment].each { |k, v| envs[k.to_s] = v } if options[:environment]
|
116
|
+
unless envs.empty?
|
117
|
+
old_envs = {}
|
118
|
+
ENV.each { |k, v| old_envs[k] = v if envs.include?(k) }
|
119
|
+
envs.each { |k, v| ENV[k] = v }
|
120
|
+
end
|
121
|
+
|
122
|
+
# Launch child process
|
123
|
+
EM.popen(cmd, StdOutHandler, options[:target], options[:stdout_handler], options[:exit_handler], c, r, w)
|
124
|
+
|
125
|
+
# Restore environment variables
|
126
|
+
unless envs.empty?
|
127
|
+
envs.each { |k, _| ENV[k] = nil }
|
128
|
+
old_envs.each { |k, v| ENV[k] = v }
|
129
|
+
end
|
130
|
+
|
129
131
|
# Do not close 'w', strange things happen otherwise
|
130
132
|
# (command protocol socket gets closed during decommission)
|
131
133
|
$stderr.reopen saved_stderr
|
data/lib/right_popen.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#--
|
2
2
|
# Copyright (c) 2009 RightScale Inc
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
20
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
21
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
-
|
22
|
+
#++
|
23
23
|
|
24
24
|
# RightScale.popen3 allows running external processes aynchronously
|
25
25
|
# while still capturing their standard and error outputs.
|
@@ -30,3 +30,36 @@ if RUBY_PLATFORM =~ /mswin/
|
|
30
30
|
else
|
31
31
|
require File.expand_path(File.join(File.dirname(__FILE__), 'linux', 'right_popen'))
|
32
32
|
end
|
33
|
+
|
34
|
+
module RightScale
|
35
|
+
|
36
|
+
# Spawn process to run given command asynchronously, hooking all three
|
37
|
+
# standard streams of the child process.
|
38
|
+
#
|
39
|
+
# Streams the command's stdout and stderr to the given handlers. Time-
|
40
|
+
# ordering of bytes sent to stdout and stderr is not preserved.
|
41
|
+
#
|
42
|
+
# Calls given exit handler upon command process termination, passing in the
|
43
|
+
# resulting Process::Status.
|
44
|
+
#
|
45
|
+
# All handlers must be methods exposed by the given target.
|
46
|
+
#
|
47
|
+
# === Parameters
|
48
|
+
# options[:command](String):: Command to execute, including any arguments
|
49
|
+
# options[:environment](Hash):: Hash of environment variables values keyed by name
|
50
|
+
# options[:target](Object):: object defining handler methods to be called, optional (no handlers can be defined if not specified)
|
51
|
+
# options[:stdout_handler](String):: Stdout handler method name, optional
|
52
|
+
# options[:stderr_handler](String):: Stderr handler method name, optional
|
53
|
+
# options[:exit_handler](String):: Exit handler method name, optional
|
54
|
+
#
|
55
|
+
# === Returns
|
56
|
+
# true:: Always returns true
|
57
|
+
def self.popen3(options)
|
58
|
+
raise "EventMachine reactor must be started" unless EM.reactor_running?
|
59
|
+
raise "Missing command" unless options[:command]
|
60
|
+
raise "Missing target" unless options[:target] || !options[:stdout_handler] && !options[:stderr_handler] && !options[:exit_handler]
|
61
|
+
RightScale.popen3_imp(options)
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/right_popen.gemspec
CHANGED
@@ -4,7 +4,7 @@ spec = Gem::Specification.new do |spec|
|
|
4
4
|
is_windows = RUBY_PLATFORM =~ /mswin/
|
5
5
|
|
6
6
|
spec.name = 'right_popen'
|
7
|
-
spec.version = '1.0.
|
7
|
+
spec.version = '1.0.5'
|
8
8
|
spec.authors = ['Scott Messier', 'Raphael Simon']
|
9
9
|
spec.email = 'scott@rightscale.com'
|
10
10
|
spec.homepage = 'https://github.com/rightscale/right_popen'
|
data/spec/print_env.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ENV.each { |k, v| $stdout.puts "#{k}=#{v}\n" }
|
data/spec/right_popen_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
-
require 'right_popen'
|
3
2
|
|
4
3
|
RUBY_CMD = 'ruby'
|
5
4
|
STANDARD_MESSAGE = 'Standard message'
|
@@ -29,18 +28,23 @@ describe 'RightScale::popen3' do
|
|
29
28
|
|
30
29
|
attr_reader :output_text, :error_text, :status
|
31
30
|
|
32
|
-
def do_right_popen(command)
|
31
|
+
def do_right_popen(command, env=nil)
|
33
32
|
@output_text = ''
|
34
33
|
@error_text = ''
|
35
34
|
@status = nil
|
36
|
-
RightScale.popen3(command
|
35
|
+
RightScale.popen3(:command => command,
|
36
|
+
:target => self,
|
37
|
+
:environment => env,
|
38
|
+
:stdout_handler => :on_read_stdout,
|
39
|
+
:stderr_handler => :on_read_stderr,
|
40
|
+
:exit_handler => :on_exit)
|
37
41
|
end
|
38
42
|
|
39
|
-
def run_right_popen(command, count = 1)
|
43
|
+
def run_right_popen(command, env=nil, count = 1)
|
40
44
|
puts "#{count}>" if count > 1
|
41
45
|
last_iteration = 0
|
42
46
|
EM.next_tick do
|
43
|
-
do_right_popen(command)
|
47
|
+
do_right_popen(command, env)
|
44
48
|
end
|
45
49
|
EM.run do
|
46
50
|
timer = EM::PeriodicTimer.new(0.05) do
|
@@ -54,7 +58,7 @@ describe 'RightScale::popen3' do
|
|
54
58
|
print '+'
|
55
59
|
STDOUT.flush
|
56
60
|
end
|
57
|
-
do_right_popen(command)
|
61
|
+
do_right_popen(command, env)
|
58
62
|
end
|
59
63
|
else
|
60
64
|
puts "<" if count > 1
|
@@ -162,11 +166,35 @@ describe 'RightScale::popen3' do
|
|
162
166
|
end
|
163
167
|
runner.error_text.should == results
|
164
168
|
end
|
169
|
+
|
170
|
+
it 'should setup environment variables' do
|
171
|
+
command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
|
172
|
+
runner = RightPopenSpec::Runner.new
|
173
|
+
runner.run_right_popen(command)
|
174
|
+
runner.status.exitstatus.should == 0
|
175
|
+
runner.output_text.should_not include('_test_')
|
176
|
+
runner.run_right_popen(command, :__test__ => '42')
|
177
|
+
runner.status.exitstatus.should == 0
|
178
|
+
runner.output_text.should match(/^__test__=42$/)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should restore environment variables' do
|
182
|
+
ENV['__test__'] = '41'
|
183
|
+
old_envs = {}
|
184
|
+
ENV.each { |k, v| old_envs[k] = v }
|
185
|
+
command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
|
186
|
+
runner = RightPopenSpec::Runner.new
|
187
|
+
runner.run_right_popen(command, :__test__ => '42')
|
188
|
+
runner.status.exitstatus.should == 0
|
189
|
+
runner.output_text.should match(/^__test__=42$/)
|
190
|
+
ENV.each { |k, v| old_envs[k].should == v }
|
191
|
+
old_envs.each { |k, v| ENV[k].should == v }
|
192
|
+
end
|
165
193
|
|
166
194
|
it 'should run repeatedly without leaking resources' do
|
167
195
|
command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
|
168
196
|
runner = RightPopenSpec::Runner.new
|
169
|
-
runner.run_right_popen(command, REPEAT_TEST_COUNTER)
|
197
|
+
runner.run_right_popen(command, nil, REPEAT_TEST_COUNTER)
|
170
198
|
runner.status.exitstatus.should == 0
|
171
199
|
runner.output_text.should == STANDARD_MESSAGE + "\n"
|
172
200
|
runner.error_text.should == ERROR_MESSAGE + "\n"
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_popen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Messier
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-02-
|
13
|
+
date: 2010-02-19 00:00:00 -08:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- lib/linux/right_popen.rb
|
44
44
|
- lib/right_popen.rb
|
45
45
|
- right_popen.gemspec
|
46
|
+
- spec/print_env.rb
|
46
47
|
- spec/produce_mixed_output.rb
|
47
48
|
- spec/produce_output.rb
|
48
49
|
- spec/produce_status.rb
|