Class: RobotLab::To::Tools::Bash

Inherits:
FileTool
  • Object
show all
Defined in:
lib/robot_lab/to/tools/bash.rb

Overview

Run a shell command in the working directory and return combined stdout+stderr plus the exit status. Output is capped and the command is killed past a timeout so a runaway process can't stall an overnight loop.

Constant Summary collapse

DEFAULT_TIMEOUT =
120
MAX_OUTPUT =
30_000

Instance Method Summary collapse

Methods inherited from FileTool

#name, name_segment, short_name

Constructor Details

#initialize(robot: nil, timeout: DEFAULT_TIMEOUT) ⇒ Bash

Returns a new instance of Bash.



23
24
25
26
# File 'lib/robot_lab/to/tools/bash.rb', line 23

def initialize(robot: nil, timeout: DEFAULT_TIMEOUT)
  super(robot: robot)
  @default_timeout = timeout
end

Instance Method Details

#execute(command:, timeout: nil) ⇒ Object



28
29
30
31
# File 'lib/robot_lab/to/tools/bash.rb', line 28

def execute(command:, timeout: nil, **)
  out, status = run(command, (timeout || @default_timeout).to_i)
  format_result(out, status)
end

#run(command, timeout) ⇒ Array(String, String)

Run command, returning [combined_output, status_string]. status_string is "0".."n" for an exit code, or "timeout"/"error: ...".

Returns:

  • (Array(String, String))


37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/robot_lab/to/tools/bash.rb', line 37

def run(command, timeout)
  out_str = +""
  status = nil
  Open3.popen2e(command, chdir: Dir.pwd) do |_stdin, out, wait|
    reader = Thread.new { out.each_char { |c| out_str << c } }
    status = finished_within?(wait, timeout) ? wait.value.exitstatus.to_s : kill(wait)
    reader.join(1)
  end
  [out_str, status]
rescue SystemCallError, IOError => e
  ["", "error: #{e.message}"]
end