Class: Aruba::Processes::SpawnProcess

Inherits:
BasicProcess show all
Defined in:
lib/aruba/processes/spawn_process.rb

Overview

Spawn a process for command

‘SpawnProcess` is not meant for direct use - `SpawnProcess.new` - by users. Only it’s public methods are part of the public API of aruba, e.g. ‘#stdin`, `#stdout`.

Instance Attribute Summary

Attributes inherited from BasicProcess

#environment, #exit_status, #exit_timeout, #io_wait_timeout, #main_class, #startup_wait_time, #stop_signal, #working_directory

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BasicProcess

#after_run, #arguments, #before_run, #command, #commandline, #empty?, #inspect, #output, #restart, #started?, #stopped?, #timed_out?

Constructor Details

#initialize(cmd, exit_timeout, io_wait_timeout, working_directory, environment = Aruba.platform.environment_variables.hash_from_env, main_class = nil, stop_signal = nil, startup_wait_time = 0) ⇒ SpawnProcess

Create process

Parameters:

  • cmd (String)

    Command string

  • exit_timeout (Numeric)

    The timeout until we expect the command to be finished

  • io_wait_timeout (Numeric)

    The timeout until we expect the io to be finished

  • working_directory (String)

    The directory where the command will be executed

  • environment (Hash) (defaults to: Aruba.platform.environment_variables.hash_from_env)

    Environment variables

  • main_class (Class) (defaults to: nil)

    E.g. Cli::App::Runner

  • stop_signal (String) (defaults to: nil)

    Name of signal to send to stop process. E.g. ‘HUP’.

  • startup_wait_time (Numeric) (defaults to: 0)

    The amount of seconds to wait after Aruba has started a command.



129
130
131
132
133
134
135
136
137
# File 'lib/aruba/processes/spawn_process.rb', line 129

def initialize(cmd, exit_timeout, io_wait_timeout, working_directory, # rubocop:disable Metrics/ParameterLists
               environment = Aruba.platform.environment_variables.hash_from_env,
               main_class = nil, stop_signal = nil, startup_wait_time = 0)
  super

  @process      = nil
  @stdout_cache = nil
  @stderr_cache = nil
end

Class Method Details

.match?(_mode) ⇒ Boolean

Use as default launcher

Returns:

  • (Boolean)


100
101
102
# File 'lib/aruba/processes/spawn_process.rb', line 100

def self.match?(_mode)
  true
end

Instance Method Details

#close_io(name) ⇒ Object

Close io



243
244
245
246
247
# File 'lib/aruba/processes/spawn_process.rb', line 243

def close_io(name)
  return if stopped?

  @process.public_send(name.to_sym).close
end

#contentString

Content of command

Returns:

  • (String)

    The content of the script/command. This might be binary output as string if your command is a binary executable.



325
326
327
# File 'lib/aruba/processes/spawn_process.rb', line 325

def content
  File.read command_path
end

#filesystem_statusAruba::Platforms::FilesystemStatus

Return file system stats for the given command

Returns:



316
317
318
# File 'lib/aruba/processes/spawn_process.rb', line 316

def filesystem_status
  Aruba.platform.filesystem_status.new(command_path)
end

#interactive?Boolean

Returns:

  • (Boolean)


329
330
331
# File 'lib/aruba/processes/spawn_process.rb', line 329

def interactive?
  true
end

#pidObject

Output pid of process

This is the PID of the spawned process.



295
296
297
# File 'lib/aruba/processes/spawn_process.rb', line 295

def pid
  @process.pid
end

#send_signal(signal) ⇒ Object

Send command a signal

Parameters:

  • signal (String)

    The signal, i.e. ‘TERM’



303
304
305
306
307
308
309
310
# File 'lib/aruba/processes/spawn_process.rb', line 303

def send_signal(signal)
  error_message = %(Command "#{commandline}" with PID "#{pid}" has already stopped.)
  raise CommandAlreadyStoppedError, error_message if @process.exited?

  Process.kill signal, pid
rescue Errno::ESRCH
  raise CommandAlreadyStoppedError, error_message
end

#start {|SpawnProcess| ... } ⇒ Object

Run the command

Yields:



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/aruba/processes/spawn_process.rb', line 144

def start
  if started?
    error_message =
      "Command \"#{commandline}\" has already been started." \
      " Please `#stop` the command first and `#start` it again." \
      " Alternatively use `#restart`."
    raise CommandAlreadyStartedError, error_message
  end

  @started = true

  @process = ProcessRunner.new(command_string.to_a)

  @stdout_file = Tempfile.new("aruba-stdout-")
  @stderr_file = Tempfile.new("aruba-stderr-")

  @stdout_file.sync = true
  @stderr_file.sync = true

  @stdout_file.set_encoding("ASCII-8BIT")
  @stderr_file.set_encoding("ASCII-8BIT")

  @exit_status = nil

  before_run

  @process.stdout = @stdout_file
  @process.stderr = @stderr_file
  @process.cwd    = @working_directory

  @process.environment = environment

  begin
    @process.start
    sleep startup_wait_time
  rescue SystemCallError => e
    raise LaunchError, "It tried to start #{commandline}. " + e.message
  end

  after_run

  yield self if block_given?
end

#stderr(opts = {}) ⇒ String

Access to stderr of process

Parameters:

  • opts (Hash) (defaults to: {})

    Options

  • [Integer] (Hash)

    a customizable set of options

Returns:

  • (String)

    The content of stderr



224
225
226
227
228
229
230
231
# File 'lib/aruba/processes/spawn_process.rb', line 224

def stderr(opts = {})
  return @stderr_cache if stopped?

  wait_for_io opts.fetch(:wait_for_io, io_wait_timeout) do
    @process.stderr.flush
    open(@stderr_file.path).read
  end
end

#stdinObject

Access to stdin of process



189
190
191
192
193
# File 'lib/aruba/processes/spawn_process.rb', line 189

def stdin
  return if @process.exited?

  @process.io.stdin
end

#stdout(opts = {}) ⇒ String

Access to stdout of process

Parameters:

  • opts (Hash) (defaults to: {})

    Options

  • [Integer] (Hash)

    a customizable set of options

Returns:

  • (String)

    The content of stdout



205
206
207
208
209
210
211
212
# File 'lib/aruba/processes/spawn_process.rb', line 205

def stdout(opts = {})
  return @stdout_cache if stopped?

  wait_for_io opts.fetch(:wait_for_io, io_wait_timeout) do
    @process.stdout.flush
    open(@stdout_file.path).read
  end
end

#stopObject

Stop command



250
251
252
253
254
255
256
# File 'lib/aruba/processes/spawn_process.rb', line 250

def stop(*)
  return @exit_status if stopped?

  @process.poll_for_exit(@exit_timeout) or @timed_out = true

  terminate
end

#terminateObject

Terminate command



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/aruba/processes/spawn_process.rb', line 264

def terminate
  return @exit_status if stopped?

  unless @process.exited?
    if @stop_signal
      # send stop signal ...
      send_signal @stop_signal
      # ... and set the exit status
      wait
    else
      begin
        @process.stop
      rescue Errno::EPERM # This can occur on MacOS
        nil
      end
    end
  end

  @exit_status = @process.exit_code

  @stdout_cache = read_temporary_output_file @stdout_file
  @stderr_cache = read_temporary_output_file @stderr_file

  @started = false

  @exit_status
end

#waitObject

Wait for command to finish



259
260
261
# File 'lib/aruba/processes/spawn_process.rb', line 259

def wait
  @process.wait
end

#write(input) ⇒ Object



233
234
235
236
237
238
239
240
# File 'lib/aruba/processes/spawn_process.rb', line 233

def write(input)
  return if stopped?

  @process.stdin.write(input)
  @process.stdin.flush

  self
end