open4 0.3.0 → 0.4.0
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/README +50 -0
- data/gemspec.rb +3 -3
- data/lib/{open4-0.3.0.rb → open4-0.4.0.rb} +63 -21
- data/lib/open4.rb +63 -21
- data/{open4-0.3.0.gem → open4-0.4.0.gem} +0 -0
- data/sample/bg.rb +21 -0
- metadata +6 -5
data/README
CHANGED
@@ -9,6 +9,10 @@ SYNOPSIS
|
|
9
9
|
|
10
10
|
HISTORY
|
11
11
|
|
12
|
+
0.4.0:
|
13
|
+
- improved error handling contributed by jordan breeding.
|
14
|
+
- introduction of background/bg method
|
15
|
+
|
12
16
|
0.3.0 :
|
13
17
|
- bug fix from jordan breeding. general clean up. added spawn method.
|
14
18
|
|
@@ -136,6 +140,52 @@ SAMPLES
|
|
136
140
|
"42"
|
137
141
|
""
|
138
142
|
|
143
|
+
|
144
|
+
----------------------------------------------------------------------------
|
145
|
+
the bg/background method is similar to spawn, but the process is
|
146
|
+
automatically set running in a thread. the returned thread has several
|
147
|
+
methods added dynamically which return the pid and blocking calls to the
|
148
|
+
exitstatus.
|
149
|
+
----------------------------------------------------------------------------
|
150
|
+
|
151
|
+
harp: > cat sample/bg.rb
|
152
|
+
require 'yaml'
|
153
|
+
require 'open4'
|
154
|
+
include Open4
|
155
|
+
|
156
|
+
stdin = '42'
|
157
|
+
stdout = ''
|
158
|
+
stderr = ''
|
159
|
+
|
160
|
+
t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
|
161
|
+
|
162
|
+
waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
|
163
|
+
|
164
|
+
while((status = t.status))
|
165
|
+
y "status" => status
|
166
|
+
sleep 1
|
167
|
+
end
|
168
|
+
|
169
|
+
waiter.join
|
170
|
+
|
171
|
+
y "stdout" => stdout
|
172
|
+
|
173
|
+
|
174
|
+
harp: > ruby sample/bg.rb
|
175
|
+
---
|
176
|
+
status: run
|
177
|
+
---
|
178
|
+
status: sleep
|
179
|
+
---
|
180
|
+
status: sleep
|
181
|
+
---
|
182
|
+
status: sleep
|
183
|
+
---
|
184
|
+
21357: 0
|
185
|
+
---
|
186
|
+
stdout: "42\n"
|
187
|
+
|
188
|
+
|
139
189
|
AUTHOR
|
140
190
|
|
141
191
|
ara.t.howard@noaa.gov
|
data/gemspec.rb
CHANGED
@@ -8,11 +8,11 @@ Gem::Specification::new do |spec|
|
|
8
8
|
spec.platform = Gem::Platform::RUBY
|
9
9
|
spec.summary = lib
|
10
10
|
|
11
|
-
# spec.files = Dir[ File::join("{lib,bin}", "*") ]
|
12
|
-
# spec.require_path = "lib"
|
13
|
-
|
14
11
|
spec.files = Dir::glob "**/**"
|
15
12
|
spec.executables = Dir::glob("bin/*").map{|exe| File::basename exe}
|
13
|
+
|
14
|
+
spec.require_path = "lib"
|
15
|
+
spec.autorequire = lib
|
16
16
|
|
17
17
|
spec.has_rdoc = File::exist? "doc"
|
18
18
|
spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
|
@@ -2,7 +2,9 @@ require 'fcntl'
|
|
2
2
|
|
3
3
|
module Open4
|
4
4
|
#--{{{
|
5
|
-
def self.version
|
5
|
+
def self.version
|
6
|
+
'0.4.0'
|
7
|
+
end
|
6
8
|
|
7
9
|
def popen4(*cmd)
|
8
10
|
#--{{{
|
@@ -46,11 +48,7 @@ module Open4
|
|
46
48
|
|
47
49
|
begin
|
48
50
|
e = Marshal.load ps.first
|
49
|
-
|
50
|
-
raise e
|
51
|
-
else
|
52
|
-
raise "unknown failure"
|
53
|
-
end
|
51
|
+
raise(Exception === e ? e : "unknown failure!")
|
54
52
|
rescue EOFError # If we get an EOF error, then the exec was successful
|
55
53
|
42
|
56
54
|
end
|
@@ -75,6 +73,20 @@ module Open4
|
|
75
73
|
module_function :popen4
|
76
74
|
module_function :open4
|
77
75
|
|
76
|
+
class Error < ::StandardError; end
|
77
|
+
class SpawnError < Error
|
78
|
+
#--{{{
|
79
|
+
attr 'cmd'
|
80
|
+
attr 'status'
|
81
|
+
def exitstatus
|
82
|
+
@status.exitstatus
|
83
|
+
end
|
84
|
+
def initialize cmd, status
|
85
|
+
@cmd, @status = cmd, status
|
86
|
+
super "cmd <#{ cmd }> failed with <#{ exitstatus }>"
|
87
|
+
end
|
88
|
+
#--}}}
|
89
|
+
end
|
78
90
|
def spawn cmd, opts = {}
|
79
91
|
#--{{{
|
80
92
|
getopt = lambda do |*args|
|
@@ -89,11 +101,13 @@ module Open4
|
|
89
101
|
end
|
90
102
|
end
|
91
103
|
|
92
|
-
|
104
|
+
ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
|
105
|
+
ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
|
93
106
|
exitstatus = getopt[ %w( exitstatus exit_status status ), 0 ]
|
94
107
|
stdin = getopt[ ['stdin', 'in', '0', 0] ]
|
95
108
|
stdout = getopt[ ['stdout', 'out', '1', 1] ]
|
96
109
|
stderr = getopt[ ['stderr', 'err', '2', 2] ]
|
110
|
+
pid = getopt[ 'pid' ]
|
97
111
|
|
98
112
|
started = false
|
99
113
|
|
@@ -102,32 +116,60 @@ module Open4
|
|
102
116
|
popen4(cmd) do |c, i, o, e|
|
103
117
|
started = true
|
104
118
|
|
105
|
-
if
|
106
|
-
|
107
|
-
elsif stdin.respond_to? :read
|
108
|
-
i << stdin.read
|
109
|
-
else
|
110
|
-
i << stdin.to_s
|
119
|
+
if pid.respond_to? '<<'
|
120
|
+
pid << c
|
111
121
|
end
|
112
122
|
|
113
|
-
i
|
123
|
+
it = Thread.new(i,stdin) do |i,stdin|
|
124
|
+
if stdin
|
125
|
+
if stdin.respond_to? :each
|
126
|
+
stdin.each{|buf| i << buf}
|
127
|
+
elsif stdin.respond_to? :read
|
128
|
+
i << stdin.read
|
129
|
+
else
|
130
|
+
i << stdin.to_s
|
131
|
+
end
|
132
|
+
end
|
133
|
+
i.close
|
134
|
+
end
|
114
135
|
|
115
|
-
ot = Thread.new(o){ o.each{|buf| stdout << buf if stdout}
|
116
|
-
et = Thread.new(e){ e.each{|buf| stderr << buf if stderr}
|
136
|
+
ot = Thread.new(o,stdout){|o,stdout| o.each{|buf| stdout << buf if stdout}}
|
137
|
+
et = Thread.new(e,stderr){|e,stderr| e.each{|buf| stderr << buf if stderr}}
|
117
138
|
|
118
|
-
|
119
|
-
|
139
|
+
it.join
|
140
|
+
ot.join if ot
|
141
|
+
et.join if et
|
120
142
|
end
|
121
143
|
rescue
|
122
|
-
raise unless(not started and
|
144
|
+
raise unless(not started and ignore_exec_failure)
|
123
145
|
end
|
124
146
|
|
125
|
-
raise
|
126
|
-
((status
|
147
|
+
raise SpawnError.new(cmd, status) unless
|
148
|
+
(ignore_exit_failure or (status.nil? and ignore_exec_failure) or (status.exitstatus == exitstatus))
|
127
149
|
|
128
150
|
status
|
129
151
|
#--}}}
|
130
152
|
end
|
131
153
|
module_function :spawn
|
154
|
+
|
155
|
+
def background cmd, opts = {}
|
156
|
+
#--{{{
|
157
|
+
require 'thread'
|
158
|
+
q = Queue.new
|
159
|
+
opts['pid'] = opts[:pid] = q
|
160
|
+
thread = Thread.new(cmd, opts){|cmd, opts| spawn cmd, opts}
|
161
|
+
pid = q.pop
|
162
|
+
sc = class << thread; self; end
|
163
|
+
sc.module_eval {
|
164
|
+
define_method(:pid){ pid }
|
165
|
+
define_method(:spawn_status){ @spawn_status ||= value }
|
166
|
+
define_method(:exitstatus){ spawn_status.exitstatus }
|
167
|
+
}
|
168
|
+
thread
|
169
|
+
#--}}}
|
170
|
+
end
|
171
|
+
alias bg background
|
172
|
+
module_function :background
|
173
|
+
module_function :bg
|
132
174
|
#--}}}
|
133
175
|
end
|
data/lib/open4.rb
CHANGED
@@ -2,7 +2,9 @@ require 'fcntl'
|
|
2
2
|
|
3
3
|
module Open4
|
4
4
|
#--{{{
|
5
|
-
def self.version
|
5
|
+
def self.version
|
6
|
+
'0.4.0'
|
7
|
+
end
|
6
8
|
|
7
9
|
def popen4(*cmd)
|
8
10
|
#--{{{
|
@@ -46,11 +48,7 @@ module Open4
|
|
46
48
|
|
47
49
|
begin
|
48
50
|
e = Marshal.load ps.first
|
49
|
-
|
50
|
-
raise e
|
51
|
-
else
|
52
|
-
raise "unknown failure"
|
53
|
-
end
|
51
|
+
raise(Exception === e ? e : "unknown failure!")
|
54
52
|
rescue EOFError # If we get an EOF error, then the exec was successful
|
55
53
|
42
|
56
54
|
end
|
@@ -75,6 +73,20 @@ module Open4
|
|
75
73
|
module_function :popen4
|
76
74
|
module_function :open4
|
77
75
|
|
76
|
+
class Error < ::StandardError; end
|
77
|
+
class SpawnError < Error
|
78
|
+
#--{{{
|
79
|
+
attr 'cmd'
|
80
|
+
attr 'status'
|
81
|
+
def exitstatus
|
82
|
+
@status.exitstatus
|
83
|
+
end
|
84
|
+
def initialize cmd, status
|
85
|
+
@cmd, @status = cmd, status
|
86
|
+
super "cmd <#{ cmd }> failed with <#{ exitstatus }>"
|
87
|
+
end
|
88
|
+
#--}}}
|
89
|
+
end
|
78
90
|
def spawn cmd, opts = {}
|
79
91
|
#--{{{
|
80
92
|
getopt = lambda do |*args|
|
@@ -89,11 +101,13 @@ module Open4
|
|
89
101
|
end
|
90
102
|
end
|
91
103
|
|
92
|
-
|
104
|
+
ignore_exit_failure = getopt[ 'ignore_exit_failure', getopt['quiet', false] ]
|
105
|
+
ignore_exec_failure = getopt[ 'ignore_exec_failure', !getopt['raise', true] ]
|
93
106
|
exitstatus = getopt[ %w( exitstatus exit_status status ), 0 ]
|
94
107
|
stdin = getopt[ ['stdin', 'in', '0', 0] ]
|
95
108
|
stdout = getopt[ ['stdout', 'out', '1', 1] ]
|
96
109
|
stderr = getopt[ ['stderr', 'err', '2', 2] ]
|
110
|
+
pid = getopt[ 'pid' ]
|
97
111
|
|
98
112
|
started = false
|
99
113
|
|
@@ -102,32 +116,60 @@ module Open4
|
|
102
116
|
popen4(cmd) do |c, i, o, e|
|
103
117
|
started = true
|
104
118
|
|
105
|
-
if
|
106
|
-
|
107
|
-
elsif stdin.respond_to? :read
|
108
|
-
i << stdin.read
|
109
|
-
else
|
110
|
-
i << stdin.to_s
|
119
|
+
if pid.respond_to? '<<'
|
120
|
+
pid << c
|
111
121
|
end
|
112
122
|
|
113
|
-
i
|
123
|
+
it = Thread.new(i,stdin) do |i,stdin|
|
124
|
+
if stdin
|
125
|
+
if stdin.respond_to? :each
|
126
|
+
stdin.each{|buf| i << buf}
|
127
|
+
elsif stdin.respond_to? :read
|
128
|
+
i << stdin.read
|
129
|
+
else
|
130
|
+
i << stdin.to_s
|
131
|
+
end
|
132
|
+
end
|
133
|
+
i.close
|
134
|
+
end
|
114
135
|
|
115
|
-
ot = Thread.new(o){ o.each{|buf| stdout << buf if stdout}
|
116
|
-
et = Thread.new(e){ e.each{|buf| stderr << buf if stderr}
|
136
|
+
ot = Thread.new(o,stdout){|o,stdout| o.each{|buf| stdout << buf if stdout}}
|
137
|
+
et = Thread.new(e,stderr){|e,stderr| e.each{|buf| stderr << buf if stderr}}
|
117
138
|
|
118
|
-
|
119
|
-
|
139
|
+
it.join
|
140
|
+
ot.join if ot
|
141
|
+
et.join if et
|
120
142
|
end
|
121
143
|
rescue
|
122
|
-
raise unless(not started and
|
144
|
+
raise unless(not started and ignore_exec_failure)
|
123
145
|
end
|
124
146
|
|
125
|
-
raise
|
126
|
-
((status
|
147
|
+
raise SpawnError.new(cmd, status) unless
|
148
|
+
(ignore_exit_failure or (status.nil? and ignore_exec_failure) or (status.exitstatus == exitstatus))
|
127
149
|
|
128
150
|
status
|
129
151
|
#--}}}
|
130
152
|
end
|
131
153
|
module_function :spawn
|
154
|
+
|
155
|
+
def background cmd, opts = {}
|
156
|
+
#--{{{
|
157
|
+
require 'thread'
|
158
|
+
q = Queue.new
|
159
|
+
opts['pid'] = opts[:pid] = q
|
160
|
+
thread = Thread.new(cmd, opts){|cmd, opts| spawn cmd, opts}
|
161
|
+
pid = q.pop
|
162
|
+
sc = class << thread; self; end
|
163
|
+
sc.module_eval {
|
164
|
+
define_method(:pid){ pid }
|
165
|
+
define_method(:spawn_status){ @spawn_status ||= value }
|
166
|
+
define_method(:exitstatus){ spawn_status.exitstatus }
|
167
|
+
}
|
168
|
+
thread
|
169
|
+
#--}}}
|
170
|
+
end
|
171
|
+
alias bg background
|
172
|
+
module_function :background
|
173
|
+
module_function :bg
|
132
174
|
#--}}}
|
133
175
|
end
|
File without changes
|
data/sample/bg.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'open4'
|
3
|
+
include Open4
|
4
|
+
|
5
|
+
stdin = '42'
|
6
|
+
stdout = ''
|
7
|
+
stderr = ''
|
8
|
+
|
9
|
+
t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
|
10
|
+
|
11
|
+
waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
|
12
|
+
|
13
|
+
while((status = t.status))
|
14
|
+
y "status" => status
|
15
|
+
sleep 1
|
16
|
+
end
|
17
|
+
|
18
|
+
waiter.join
|
19
|
+
|
20
|
+
y "stdout" => stdout
|
21
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: open4
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-04-
|
6
|
+
version: 0.4.0
|
7
|
+
date: 2006-04-26 00:00:00.000000 -06:00
|
8
8
|
summary: open4
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -12,7 +12,7 @@ email: ara.t.howard@noaa.gov
|
|
12
12
|
homepage: http://codeforpeople.com/lib/ruby/open4/
|
13
13
|
rubyforge_project:
|
14
14
|
description:
|
15
|
-
autorequire:
|
15
|
+
autorequire: open4
|
16
16
|
default_executable:
|
17
17
|
bindir: bin
|
18
18
|
has_rdoc: false
|
@@ -29,7 +29,6 @@ cert_chain:
|
|
29
29
|
authors:
|
30
30
|
- Ara T. Howard
|
31
31
|
files:
|
32
|
-
- open4-0.3.0.gem
|
33
32
|
- install.rb
|
34
33
|
- sample
|
35
34
|
- lib
|
@@ -37,11 +36,13 @@ files:
|
|
37
36
|
- build
|
38
37
|
- install
|
39
38
|
- gemspec.rb
|
39
|
+
- open4-0.4.0.gem
|
40
40
|
- sample/block.rb
|
41
41
|
- sample/simple.rb
|
42
42
|
- sample/exception.rb
|
43
43
|
- sample/spawn.rb
|
44
|
-
-
|
44
|
+
- sample/bg.rb
|
45
|
+
- lib/open4-0.4.0.rb
|
45
46
|
- lib/open4.rb
|
46
47
|
test_files: []
|
47
48
|
rdoc_options: []
|