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.



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

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)


102
103
104
# File 'lib/aruba/processes/spawn_process.rb', line 102

def self.match?(_mode)
  true
end

Instance Method Details

#close_io(name) ⇒ Object

Close io



245
246
247
248
249
# File 'lib/aruba/processes/spawn_process.rb', line 245

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.



327
328
329
# File 'lib/aruba/processes/spawn_process.rb', line 327

def content
  File.read command_path
end

#filesystem_statusAruba::Platforms::FilesystemStatus

Return file system stats for the given command

Returns:



318
319
320
# File 'lib/aruba/processes/spawn_process.rb', line 318

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

#interactive?Boolean

Returns:

  • (Boolean)


331
332
333
# File 'lib/aruba/processes/spawn_process.rb', line 331

def interactive?
  true
end

#pidObject

Output pid of process

This is the PID of the spawned process.



297
298
299
# File 'lib/aruba/processes/spawn_process.rb', line 297

def pid
  @process.pid
end

#send_signal(signal) ⇒ Object

Send command a signal

Parameters:

  • signal (String)

    The signal, i.e. ‘TERM’



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

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:



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
187
188
# File 'lib/aruba/processes/spawn_process.rb', line 146

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



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

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



191
192
193
194
195
# File 'lib/aruba/processes/spawn_process.rb', line 191

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



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

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



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

def stop(*)
  return @exit_status if stopped?

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

  terminate
end

#terminateObject

Terminate command



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
291
292
# File 'lib/aruba/processes/spawn_process.rb', line 266

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



261
262
263
# File 'lib/aruba/processes/spawn_process.rb', line 261

def wait
  @process.wait
end

#write(input) ⇒ Object



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

def write(input)
  return if stopped?

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

  self
end