Class: Scmd::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/scmd/command.rb

Defined Under Namespace

Classes: ChildProcess

Constant Summary collapse

READ_SIZE =

bytes

10240
READ_CHECK_TIMEOUT =

seconds

0.001
DEFAULT_STOP_TIMEOUT =

seconds

3

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cmd_str, opts = nil) ⇒ Command

Returns a new instance of Command.



21
22
23
24
25
26
27
# 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

Instance Attribute Details

#cmd_strObject (readonly)

Returns the value of attribute cmd_str.



18
19
20
# File 'lib/scmd/command.rb', line 18

def cmd_str
  @cmd_str
end

#envObject (readonly)

Returns the value of attribute env.



18
19
20
# File 'lib/scmd/command.rb', line 18

def env
  @env
end

#exitstatusObject (readonly)

Returns the value of attribute exitstatus.



19
20
21
# File 'lib/scmd/command.rb', line 19

def exitstatus
  @exitstatus
end

#optionsObject (readonly)

Returns the value of attribute options.



18
19
20
# File 'lib/scmd/command.rb', line 18

def options
  @options
end

#pidObject (readonly)

Returns the value of attribute pid.



19
20
21
# File 'lib/scmd/command.rb', line 19

def pid
  @pid
end

#stderrObject (readonly)

Returns the value of attribute stderr.



19
20
21
# File 'lib/scmd/command.rb', line 19

def stderr
  @stderr
end

#stdoutObject (readonly)

Returns the value of attribute stdout.



19
20
21
# File 'lib/scmd/command.rb', line 19

def stdout
  @stdout
end

Instance Method Details

#inspectObject



118
119
120
121
122
123
# File 'lib/scmd/command.rb', line 118

def inspect
  reference = "0x0%x" % (object_id << 1)
  "#<#{self.class}:#{reference}"\
  " @cmd_str=#{cmd_str.inspect}"\
  " @exitstatus=#{@exitstatus.inspect}>"
end

#kill(signal = nil) ⇒ Object



99
100
101
102
103
104
# File 'lib/scmd/command.rb', line 99

def kill(signal = nil)
  return unless running?

  send_kill(signal)
  wait # indefinitely until cmd is killed
end

#run(input = nil) ⇒ Object



29
30
31
32
33
34
35
36
# File 'lib/scmd/command.rb', line 29

def run(input = nil)
  begin
    run!(input)
  rescue
    RunError
  end
  self
end

#run!(input = nil) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 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?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'lib/scmd/command.rb', line 106

def running?
  !@child_process.nil?
end

#start(input = nil) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 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) ⇒ Object



88
89
90
91
92
93
94
95
96
97
# File 'lib/scmd/command.rb', line 88

def stop(timeout = nil)
  return unless running?

  send_term
  begin
    wait(timeout || DEFAULT_STOP_TIMEOUT)
  rescue TimeoutError
    kill
  end
end

#success?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/scmd/command.rb', line 110

def success?
  @exitstatus == 0
end

#to_sObject



114
115
116
# File 'lib/scmd/command.rb', line 114

def to_s
  @cmd_str.to_s
end

#wait(timeout = nil) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/scmd/command.rb', line 71

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