Parent

Included Modules

POSIX::Spawn::Child

POSIX::Spawn::Child includes logic for executing child processes and reading/writing from their standard input, output, and error streams. It's designed to take all input in a single string and provides all output (stderr and stdout) as single strings and is therefore not well-suited to streaming large quantities of data in and out of commands.

Create and run a process to completion:

>> child = POSIX::Spawn::Child.new('git', '--help')

Retrieve stdout or stderr output:

>> child.out
=> "usage: git [--version] [--exec-path[=GIT_EXEC_PATH]]\n ..."
>> child.err
=> ""

Check process exit status information:

>> child.status
=> #<Process::Status: pid=80718,exited(0)>

To write data on the new process’s stdin immediately after spawning:

>> child = POSIX::Spawn::Child.new('bc', :input => '40 + 2')
>> child.out
"42\n"

To access output from the process even if an exception was raised:

>> child = POSIX::Spawn::Child.build('git', 'log', :max => 1000)
>> begin
?>   child.exec!
?> rescue POSIX::Spawn::MaximumOutputExceeded
?>   # just so you know
?> end
>> child.out
"... first 1000 characters of log output ..."

Q: Why use POSIX::Spawn::Child instead of popen3, hand rolled fork/exec code, or Process::spawn?

Constants

BUFSIZE

Maximum buffer size for reading

Attributes

err[R]

All data written to the child process’s stderr stream as a String.

out[R]

All data written to the child process’s stdout stream as a String.

runtime[R]

Total command execution time (wall-clock time)

status[R]

A Process::Status object with information on how the child exited.

Public Class Methods

build(*args) click to toggle source

Set up a new process to spawn, but do not actually spawn it.

Invoke this just like the normal constructor to set up a process to be run. Call `exec!` to actually run the child process, send the input, read the output, and wait for completion. Use this alternative way of constructing a POSIX::Spawn::Child if you want to read any partial output from the child process even after an exception.

child = POSIX::Spawn::Child.build(... arguments ...)
child.exec!

The arguments are the same as the regular constructor.

Returns a new Child instance but does not run the underlying process.

# File lib/posix/spawn/child.rb, line 109
def self.build(*args)
  options =
    if args[-1].respond_to?(:to_hash)
      args.pop.to_hash
    else
      {}
    end
  new(*args, { :noexec => true }.merge(options))
end
new(*args) click to toggle source

Spawn a new process, write all input and read all output, and wait for the program to exit. Supports the standard spawn interface as described in the POSIX::Spawn module documentation:

new([env], command, [argv1, ...], [options])

The following options are supported in addition to the standard POSIX::Spawn options:

:input   => str      Write str to the new process's standard input.
:timeout => int      Maximum number of seconds to allow the process
                     to execute before aborting with a TimeoutExceeded
                     exception.
:max     => total    Maximum number of bytes of output to allow the
                     process to generate before aborting with a
                     MaximumOutputExceeded exception.

Returns a new Child instance whose underlying process has already executed to completion. The out, err, and status attributes are immediately available.

# File lib/posix/spawn/child.rb, line 84
def initialize(*args)
  @env, @argv, options = extract_process_spawn_arguments(*args)
  @options = options.dup
  @input = @options.delete(:input)
  @timeout = @options.delete(:timeout)
  @max = @options.delete(:max)
  @options.delete(:chdir) if @options[:chdir].nil?
  exec! if !@options.delete(:noexec)
end

Public Instance Methods

exec!() click to toggle source

Execute command, write input, and read output. This is called immediately when a new instance of this object is created, or can be called explicitly when creating the Child via `build`.

# File lib/posix/spawn/child.rb, line 139
def exec!
  # spawn the process and hook up the pipes
  pid, stdin, stdout, stderr = popen4(@env, *(@argv + [@options]))

  # async read from all streams into buffers
  read_and_write(@input, stdin, stdout, stderr, @timeout, @max)

  # grab exit status
  @status = waitpid(pid)
rescue Object => boom
  [stdin, stdout, stderr].each { |fd| fd.close rescue nil }
  if @status.nil?
    ::Process.kill('TERM', pid) rescue nil
    @status = waitpid(pid)      rescue nil
  end
  raise
ensure
  # let's be absolutely certain these are closed
  [stdin, stdout, stderr].each { |fd| fd.close rescue nil }
end
success?() click to toggle source

Determine if the process did exit with a zero exit status.

# File lib/posix/spawn/child.rb, line 132
def success?
  @status && @status.success?
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.