A
ara.t.howard
URIS
http://rubyforge.org/projects/codeforpeople/
http://www.codeforpeople.com/lib/ruby/
SYNOPSIS
open child process with handles on pid, stdin, stdout, and stderr: manage
child processes and their io handles easily.
HISTORY
0.6.0:
- added feature for exitstatus to be list of acceptable exit statuses
Open4.spawn 'ruby -e "exit 42"' # raises
Open4.spawn 'ruby -e "exit 42"', :exitstatus=>[0,42] # ok
- added :status switch, which will always simply return the status (no
error thrown for failure)
Open4.spawn 'ruby -e "exit 42"' # raises
status = Open4.spawn 'ruby -e "exit 42"', :status=>true # ok
note, however, that any SpawnError does in fact contain the failed
status so, even when they are thrown, error status can be retrieved:
include Open4
status =
begin
spawn 'ruby -e "exit 42"'
rescue SpawnError => e
warn{ e }
e.status
end
0.5.1:
- fixes a __critical__ but in ThreadEnsemble class that had a race
condition that could cause thread deadlock. sorry bout that folks.
0.5.0:
- on the suggestion of tim pease (thanks tim!), i added timeout features
to open4. the command run may have an overall timeout and individual
timeouts set for each of the io handles. for example
cmd = 'command_that_produce_out_at_one_second_intervals'
open4.spawn cmd, :stdout_timeout => 2
or
cmd = 'command_that_should_complete_in_about_one_minute'
open4.spawn cmd, :timeout => 60
or
cmd = 'consumes_input_at_one_line_per_second_rate'
input = %w( 42 forty-two 42.0 )
open4.spawn cmd, :stdin=>input, :stdin_timeout=>1
- added 'open4' alias so one can write
open4.spawn vs Open4.spawn
or even
open4(cmd) do |pid,i,o,e|
end
- added signal info to SpawnError
0.4.0:
- improved error handling contributed by jordan breeding.
- introduction of background/bg method
0.3.0 :
- bug fix from jordan breeding. general clean up. added spawn method.
0.2.0 :
- added exception marshaled from child -> parent when exec fails. thanks
to jordan breeding for a patch (yay!) and paul brannan for this most
excellent idea.
0.1.0 :
- fixed docs to correctly show return value of popen4 (pid first not last).
thanks Stefanie Tellex <[email protected]> for catching this.
0.0.0 :
- initial version
INSTALL
~> gem install open4
SAMPLES
----------------------------------------------------------------------------
simple usage
----------------------------------------------------------------------------
harp: > cat sample/simple.rb
require "open4"
pid, stdin, stdout, stderr = Open4:open4 "sh"
stdin.puts "echo 42.out"
stdin.puts "echo 42.err 1>&2"
stdin.close
ignored, status = Process::waitpid2 pid
puts "pid : #{ pid }"
puts "stdout : #{ stdout.read.strip }"
puts "stderr : #{ stderr.read.strip }"
puts "status : #{ status.inspect }"
puts "exitstatus : #{ status.exitstatus }"
harp: > ruby sample/simple.rb
pid : 17273
stdout : 42.out
stderr : 42.err
status : #<Process::Status: pid=17273,exited(0)>
exitstatus : 0
----------------------------------------------------------------------------
in block form - the child process is automatically waited for
----------------------------------------------------------------------------
harp: > cat sample/block.rb
require 'open4'
status =
Open4:open4("sh") do |pid, stdin, stdout, stderr|
stdin.puts "echo 42.out"
stdin.puts "echo 42.err 1>&2"
stdin.close
puts "pid : #{ pid }"
puts "stdout : #{ stdout.read.strip }"
puts "stderr : #{ stderr.read.strip }"
end
puts "status : #{ status.inspect }"
puts "exitstatus : #{ status.exitstatus }"
harp: > ruby sample/block.rb
pid : 17295
stdout : 42.out
stderr : 42.err
status : #<Process::Status: pid=17295,exited(0)>
exitstatus : 0
----------------------------------------------------------------------------
exceptions are marshaled from child to parent if fork/exec fails
----------------------------------------------------------------------------
harp: > cat sample/exception.rb
require "open4"
Open4:open4 "noexist"
harp: > ruby sample/exception.rb
/dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/open4.rb:100:in `popen4': No such file or directory - noexist (Errno::ENOENT)
from sample/exception.rb:3
----------------------------------------------------------------------------
the spawn method provides and even more convenient method of running a
process, allowing any object that supports 'each', 'read', or 'to_s' to be
given as stdin and any objects that support '<<' to be given as
stdout/stderr. an exception is thrown if the exec'd cmd fails (nonzero
exitstatus) unless the option 'raise'=>false is given
----------------------------------------------------------------------------
harp: > cat sample/spawn.rb
require 'open4'
include Open4
cat = ' ruby -e" ARGF.each{|line| STDOUT << line} " '
stdout, stderr = '', ''
status = spawn cat, 'stdin' => '42', 'stdout' => stdout, 'stderr' => stderr
p status
p stdout
p stderr
stdout, stderr = '', ''
status = spawn cat, 0=>'42', 1=>stdout, 2=>stderr
p status
p stdout
p stderr
harp: > RUBYLIB=lib ruby sample/spawn.rb
0
"42"
""
0
"42"
""
----------------------------------------------------------------------------
the bg/background method is similar to spawn, but the process is
automatically set running in a thread. the returned thread has several
methods added dynamically which return the pid and blocking calls to the
exitstatus.
----------------------------------------------------------------------------
harp: > cat sample/bg.rb
require 'yaml'
require 'open4'
include Open4
stdin = '42'
stdout = ''
stderr = ''
t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
while((status = t.status))
y "status" => status
sleep 1
end
waiter.join
y "stdout" => stdout
harp: > ruby sample/bg.rb
---
status: run
---
status: sleep
---
status: sleep
---
status: sleep
---
21357: 0
---
stdout: "42\n"
----------------------------------------------------------------------------
the timeout methods can be used to ensure execution is preceding at the
desired interval. note also how to setup a 'pipeline'
----------------------------------------------------------------------------
harp: > cat sample/stdin_timeout.rb
require 'open4'
producer = 'ruby -e" STDOUT.sync = true; loop{sleep(rand+rand) and puts 42} "'
consumer = 'ruby -e" STDOUT.sync = true; STDIN.each{|line| puts line} "'
open4(producer) do |pid, i, o, e|
open4.spawn consumer, :stdin=>o, :stdout=>STDOUT, :stdin_timeout => 1.4
end
harp: > ruby sample/stdin_timeout.rb
42
42
42
42
42
/dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
AUTHOR
(e-mail address removed)
LICENSE
ruby's
enjoy.
-a
http://rubyforge.org/projects/codeforpeople/
http://www.codeforpeople.com/lib/ruby/
SYNOPSIS
open child process with handles on pid, stdin, stdout, and stderr: manage
child processes and their io handles easily.
HISTORY
0.6.0:
- added feature for exitstatus to be list of acceptable exit statuses
Open4.spawn 'ruby -e "exit 42"' # raises
Open4.spawn 'ruby -e "exit 42"', :exitstatus=>[0,42] # ok
- added :status switch, which will always simply return the status (no
error thrown for failure)
Open4.spawn 'ruby -e "exit 42"' # raises
status = Open4.spawn 'ruby -e "exit 42"', :status=>true # ok
note, however, that any SpawnError does in fact contain the failed
status so, even when they are thrown, error status can be retrieved:
include Open4
status =
begin
spawn 'ruby -e "exit 42"'
rescue SpawnError => e
warn{ e }
e.status
end
0.5.1:
- fixes a __critical__ but in ThreadEnsemble class that had a race
condition that could cause thread deadlock. sorry bout that folks.
0.5.0:
- on the suggestion of tim pease (thanks tim!), i added timeout features
to open4. the command run may have an overall timeout and individual
timeouts set for each of the io handles. for example
cmd = 'command_that_produce_out_at_one_second_intervals'
open4.spawn cmd, :stdout_timeout => 2
or
cmd = 'command_that_should_complete_in_about_one_minute'
open4.spawn cmd, :timeout => 60
or
cmd = 'consumes_input_at_one_line_per_second_rate'
input = %w( 42 forty-two 42.0 )
open4.spawn cmd, :stdin=>input, :stdin_timeout=>1
- added 'open4' alias so one can write
open4.spawn vs Open4.spawn
or even
open4(cmd) do |pid,i,o,e|
end
- added signal info to SpawnError
0.4.0:
- improved error handling contributed by jordan breeding.
- introduction of background/bg method
0.3.0 :
- bug fix from jordan breeding. general clean up. added spawn method.
0.2.0 :
- added exception marshaled from child -> parent when exec fails. thanks
to jordan breeding for a patch (yay!) and paul brannan for this most
excellent idea.
0.1.0 :
- fixed docs to correctly show return value of popen4 (pid first not last).
thanks Stefanie Tellex <[email protected]> for catching this.
0.0.0 :
- initial version
INSTALL
~> gem install open4
SAMPLES
----------------------------------------------------------------------------
simple usage
----------------------------------------------------------------------------
harp: > cat sample/simple.rb
require "open4"
pid, stdin, stdout, stderr = Open4:open4 "sh"
stdin.puts "echo 42.out"
stdin.puts "echo 42.err 1>&2"
stdin.close
ignored, status = Process::waitpid2 pid
puts "pid : #{ pid }"
puts "stdout : #{ stdout.read.strip }"
puts "stderr : #{ stderr.read.strip }"
puts "status : #{ status.inspect }"
puts "exitstatus : #{ status.exitstatus }"
harp: > ruby sample/simple.rb
pid : 17273
stdout : 42.out
stderr : 42.err
status : #<Process::Status: pid=17273,exited(0)>
exitstatus : 0
----------------------------------------------------------------------------
in block form - the child process is automatically waited for
----------------------------------------------------------------------------
harp: > cat sample/block.rb
require 'open4'
status =
Open4:open4("sh") do |pid, stdin, stdout, stderr|
stdin.puts "echo 42.out"
stdin.puts "echo 42.err 1>&2"
stdin.close
puts "pid : #{ pid }"
puts "stdout : #{ stdout.read.strip }"
puts "stderr : #{ stderr.read.strip }"
end
puts "status : #{ status.inspect }"
puts "exitstatus : #{ status.exitstatus }"
harp: > ruby sample/block.rb
pid : 17295
stdout : 42.out
stderr : 42.err
status : #<Process::Status: pid=17295,exited(0)>
exitstatus : 0
----------------------------------------------------------------------------
exceptions are marshaled from child to parent if fork/exec fails
----------------------------------------------------------------------------
harp: > cat sample/exception.rb
require "open4"
Open4:open4 "noexist"
harp: > ruby sample/exception.rb
/dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/open4.rb:100:in `popen4': No such file or directory - noexist (Errno::ENOENT)
from sample/exception.rb:3
----------------------------------------------------------------------------
the spawn method provides and even more convenient method of running a
process, allowing any object that supports 'each', 'read', or 'to_s' to be
given as stdin and any objects that support '<<' to be given as
stdout/stderr. an exception is thrown if the exec'd cmd fails (nonzero
exitstatus) unless the option 'raise'=>false is given
----------------------------------------------------------------------------
harp: > cat sample/spawn.rb
require 'open4'
include Open4
cat = ' ruby -e" ARGF.each{|line| STDOUT << line} " '
stdout, stderr = '', ''
status = spawn cat, 'stdin' => '42', 'stdout' => stdout, 'stderr' => stderr
p status
p stdout
p stderr
stdout, stderr = '', ''
status = spawn cat, 0=>'42', 1=>stdout, 2=>stderr
p status
p stdout
p stderr
harp: > RUBYLIB=lib ruby sample/spawn.rb
0
"42"
""
0
"42"
""
----------------------------------------------------------------------------
the bg/background method is similar to spawn, but the process is
automatically set running in a thread. the returned thread has several
methods added dynamically which return the pid and blocking calls to the
exitstatus.
----------------------------------------------------------------------------
harp: > cat sample/bg.rb
require 'yaml'
require 'open4'
include Open4
stdin = '42'
stdout = ''
stderr = ''
t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
while((status = t.status))
y "status" => status
sleep 1
end
waiter.join
y "stdout" => stdout
harp: > ruby sample/bg.rb
---
status: run
---
status: sleep
---
status: sleep
---
status: sleep
---
21357: 0
---
stdout: "42\n"
----------------------------------------------------------------------------
the timeout methods can be used to ensure execution is preceding at the
desired interval. note also how to setup a 'pipeline'
----------------------------------------------------------------------------
harp: > cat sample/stdin_timeout.rb
require 'open4'
producer = 'ruby -e" STDOUT.sync = true; loop{sleep(rand+rand) and puts 42} "'
consumer = 'ruby -e" STDOUT.sync = true; STDIN.each{|line| puts line} "'
open4(producer) do |pid, i, o, e|
open4.spawn consumer, :stdin=>o, :stdout=>STDOUT, :stdin_timeout => 1.4
end
harp: > ruby sample/stdin_timeout.rb
42
42
42
42
42
/dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
AUTHOR
(e-mail address removed)
LICENSE
ruby's
enjoy.
-a