right_popen 1.0.4 → 1.0.5
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/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
|