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
-
(Boolean)
-
def collect_err?; !!@collect_err; end
def collect_out?; !!@collect_out; end
-
(Boolean)
-
def collect_out?; !!@collect_out; end
def execute(*command, **options)
-
(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)
-
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
-
(Boolean)
-
def passthru_err?; !!@passthru_err; end
def passthru_out?; !!@passthru_out; end
-
(Boolean)
-
def passthru_out?; !!@passthru_out; end
def read_command_output(out_reader, err_reader)
- 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)
- 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)
- 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