class ProcessExecuter


@api public
pass the output through to this process’s stdout/stderr.
Execute a process and capture the output to a string, a file, and/or

def collect_err?; !!@collect_err; end

Returns:
  • (Boolean) -
def collect_err?; !!@collect_err; end

def collect_out?; !!@collect_out; end

Returns:
  • (Boolean) -
def collect_out?; !!@collect_out; end

def execute(*command, **options)

Returns:
  • (ProcessExecuter::Result) - the result of the command execution

Parameters:
  • options (Hash) -- options to pass to Process.spawn
  • command (String, Array) -- the command to pass to Process.spawn

Other tags:
    Example: Execute a command with specific environment variables -
    Example: Execute a command in a specific directory -
    Example: Execute a command as with each argument as a separate string -
    Example: Execute a command as a single string -
def execute(*command, **options)
  @status = nil
  @out = (collect_out? ? '' : nil)
  @err = (collect_err? ? '' : nil)
  out_reader, out_writer = IO.pipe
  err_reader, err_writer = IO.pipe
  options[:out] = out_writer
  options[:err] = err_writer
  pid = Process.spawn(*command, options)
  loop do
    read_command_output(out_reader, err_reader)
    _pid, @status = Process.wait2(pid, Process::WNOHANG)
    break if @status
    # puts "finished_pid: #{finished_pid}"
    # puts "status: #{status}"
    # puts 'starting select'
    # readers, writers, exceptions = IO.select([stdout_reader, stderr_reader], nil, nil, 0.1)
    IO.select([out_reader, err_reader], nil, nil, 0.05)
    # puts "readers: #{readers}"
    # puts "writers: #{writers}"
    # puts "exceptions: #{exceptions}"
    # break unless readers || writers || exceptions
    _pid, @status = Process.wait2(pid, Process::WNOHANG)
    break if @status
    # puts "finished_pid: #{finished_pid}"
    # puts "status: #{status}"
  end
  out_writer.close
  err_writer.close
  # Read whatever is left over after the process terminates
  read_command_output(out_reader, err_reader)
  ProcessExecuter::Result.new(@status, @out, @err)
end

def initialize(passthru_out: false, passthru_err: false, collect_out: true, collect_err: true)

Parameters:
  • collect_err (Boolean) -- collect the command's stderr the :err string
  • collect_out (Boolean) -- collect the command's stdout the :out string
  • passthru_err (Boolean) -- show the command's stderr on this process's stderr
  • passthru_out (Boolean) -- show the command's stdout on this process's stdout
def initialize(passthru_out: false, passthru_err: false, collect_out: true, collect_err: true)
  @passthru_out = passthru_out
  @passthru_err = passthru_err
  @collect_out = collect_out
  @collect_err = collect_err
end

def passthru_err?; !!@passthru_err; end

Returns:
  • (Boolean) -
def passthru_err?; !!@passthru_err; end

def passthru_out?; !!@passthru_out; end

Returns:
  • (Boolean) -
def passthru_out?; !!@passthru_out; end

def read_command_output(out_reader, err_reader)

Other tags:
    Api: - private

Returns:
  • (void) -
def read_command_output(out_reader, err_reader)
  loop do
    # Keep reading until there is nothing left to read
    break unless read_out(out_reader) || read_err(err_reader)
  end
end

def read_err(reader)

Other tags:
    Api: - private

Returns:
  • (void) -
def read_err(reader)
  new_data = reader.read_nonblock(1024)
  # puts "new_stderr: '#{new_data}'"
  @err += new_data if new_data && collect_err?
  warn new_data if new_data && passthru_err?
  true
rescue EOFError, IO::EAGAINWaitReadable
  # Nothing to read at this time
  false
end

def read_out(reader)

Other tags:
    Api: - private

Returns:
  • (void) -
def read_out(reader)
  new_data = reader.read_nonblock(1024)
  # puts "new_stdout: '#{new_data}'"
  @out += new_data if new_data && collect_out?
  puts new_data if new_data && passthru_out?
  true
rescue EOFError, IO::EAGAINWaitReadable
  # Nothing to read at this time
  false
end