class Scmd::Command
Constants
- DEFAULT_STOP_TIMEOUT
- READ_CHECK_TIMEOUT
- READ_SIZE
Attributes
cmd_str[R]
env[R]
exitstatus[R]
options[R]
pid[R]
stderr[R]
stdout[R]
Public Class Methods
new(cmd_str, opts = nil)
click to toggle source
# File lib/scmd/command.rb, line 21 def initialize(cmd_str, opts = nil) opts ||= {} @cmd_str = cmd_str @env = stringify_hash(opts[:env] || {}) @options = opts[:options] || {} reset_attrs end
Public Instance Methods
inspect()
click to toggle source
# File lib/scmd/command.rb, line 117 def inspect reference = "0x0%x" % (object_id << 1) "#<#{self.class}:#{reference}"\ " @cmd_str=#{cmd_str.inspect}"\ " @exitstatus=#{@exitstatus.inspect}>" end
kill(signal = nil)
click to toggle source
# File lib/scmd/command.rb, line 98 def kill(signal = nil) return unless running? send_kill(signal) wait # indefinitely until cmd is killed end
run(input = nil)
click to toggle source
# File lib/scmd/command.rb, line 29 def run(input = nil) begin run!(input) rescue RunError end self end
run!(input = nil)
click to toggle source
# File lib/scmd/command.rb, line 38 def run!(input = nil) start_err_msg, start_err_bt = nil, nil begin start(input) rescue => ex start_err_msg, start_err_bt = ex.message, ex.backtrace ensure wait # indefinitely until cmd is done running unless success? raise RunError.new(start_err_msg || @stderr, start_err_bt || caller) end end self end
running?()
click to toggle source
# File lib/scmd/command.rb, line 105 def running? !@child_process.nil? end
start(input = nil)
click to toggle source
# File lib/scmd/command.rb, line 54 def start(input = nil) setup_run @pid = @child_process.pid.to_i @child_process.write(input) @read_output_thread = Thread.new do while @child_process.check_for_exit begin read_output rescue EOFError # rubocop:disable Lint/SuppressedException end end @stop_w.write_nonblock(".") end end
stop(timeout = nil)
click to toggle source
# File lib/scmd/command.rb, line 87 def stop(timeout = nil) return unless running? send_term begin wait(timeout || DEFAULT_STOP_TIMEOUT) rescue TimeoutError kill end end
success?()
click to toggle source
# File lib/scmd/command.rb, line 109 def success? @exitstatus == 0 end
to_s()
click to toggle source
# File lib/scmd/command.rb, line 113 def to_s @cmd_str.to_s end
wait(timeout = nil)
click to toggle source
# File lib/scmd/command.rb, line 70 def wait(timeout = nil) return unless running? wait_for_exit(timeout) if @child_process.running? kill raise(TimeoutError, "`#{@cmd_str}` timed out (#{timeout}s).") end @read_output_thread.join @stdout << @child_process.flush_stdout @stderr << @child_process.flush_stderr @exitstatus = @child_process.exitstatus teardown_run end
Private Instance Methods
read_output()
click to toggle source
# File lib/scmd/command.rb, line 126 def read_output @child_process.read(READ_SIZE) do |out, err| @stdout += out @stderr += err end end
reset_attrs()
click to toggle source
# File lib/scmd/command.rb, line 138 def reset_attrs @stdout, @stderr, @pid, @exitstatus = +"", +"", nil, nil end
send_kill(signal = nil)
click to toggle source
# File lib/scmd/command.rb, line 161 def send_kill(signal = nil) send_signal(signal || "KILL") end
send_signal(sig)
click to toggle source
# File lib/scmd/command.rb, line 165 def send_signal(sig) return unless running? @child_process.send_signal(sig) end
send_term()
click to toggle source
# File lib/scmd/command.rb, line 157 def send_term send_signal "TERM" end
setup_run()
click to toggle source
# File lib/scmd/command.rb, line 142 def setup_run reset_attrs @stop_r, @stop_w = IO.pipe @read_output_thread = nil @child_process = ChildProcess.new(@cmd_str, @env, @options) end
stringify_hash(hash)
click to toggle source
# File lib/scmd/command.rb, line 170 def stringify_hash(hash) hash.inject({}) do |h, (k, v)| h.merge(k.to_s => v.to_s) end end
teardown_run()
click to toggle source
# File lib/scmd/command.rb, line 149 def teardown_run @child_process.teardown [@stop_r, @stop_w].each{ |fd| fd.close if fd && !fd.closed? } @stop_r, @stop_w = nil, nil @child_process, @read_output_thread = nil, nil true end
wait_for_exit(timeout)
click to toggle source
# File lib/scmd/command.rb, line 133 def wait_for_exit(timeout) ios, _, _ = IO.select([@stop_r], nil, nil, timeout) @stop_r.read_nonblock(1) if ios&.include?(@stop_r) end