Module: AwesomeSpawn

Extended by:
AwesomeSpawn
Included in:
AwesomeSpawn
Defined in:
lib/awesome_spawn.rb,
lib/awesome_spawn/version.rb,
lib/awesome_spawn/null_logger.rb,
lib/awesome_spawn/spec_helper.rb,
lib/awesome_spawn/command_result.rb,
lib/awesome_spawn/no_such_file_error.rb,
lib/awesome_spawn/command_line_builder.rb,
lib/awesome_spawn/command_result_error.rb

Defined Under Namespace

Modules: SpecHelper Classes: CommandLineBuilder, CommandResult, CommandResultError, NoSuchFileError, NullLogger

Constant Summary collapse

VERSION =
"1.4.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#loggerObject



15
16
17
# File 'lib/awesome_spawn.rb', line 15

def logger
  @logger ||= NullLogger.new
end

Instance Method Details

#build_command_line(command, params = nil) ⇒ String

Build the full command line.

Parameters:

  • command (String)

    The command to run

  • params (Hash, Array) (defaults to: nil)

    Optional command line parameters. They can be passed as a Hash or associative Array. The values are sanitized to prevent command line injection. Keys as Symbols are prefixed with --, and _ is replaced with -.

    • {:k => "value"} generates -k value
    • [[:k, "value"]] generates -k value
    • {:k => "value"} generates -k=value
    • [[:k=, "value"]] generates -k=value

    • {:key => "value"} generates --key value

    • [[:key, "value"]] generates --key value

    • {:key= => "value"} generates --key=value

    • [[:key=, "value"]] generates --key=value

    • {"--key" => "value"} generates --key value

    • [["--key", "value"]] generates --key value

    • {"--key=" => "value"} generates --key=value

    • [["--key=", "value"]] generates --key=value

    • {:key_name => "value"} generates --key-name value

    • [[:key_name, "value"]] generates --key-name value

    • {:key_name= => "value"} generates --key-name=value

    • [[:key_name=, "value"]] generates --key-name=value

    • {"-f" => ["file1", "file2"]} generates -f file1 file2

    • [["-f", "file1", "file2"]] generates -f file1 file2

    • {:key => nil} generates --key

    • [[:key, nil]] generates --key

    • [[:key]] generates --key

    • {nil => ["file1", "file2"]} generates file1 file2

    • [[nil, ["file1", "file2"]]] generates file1 file2

    • [[nil, "file1", "file2"]] generates file1 file2

    • [["file1", "file2"]] generates file1 file2

Returns:

  • (String)

    The full command line



112
113
114
# File 'lib/awesome_spawn.rb', line 112

def build_command_line(command, params = nil)
  CommandLineBuilder.new.build(command, params)
end

#run(command, options = {}) ⇒ CommandResult

Execute command synchronously via Kernel.spawn and gather the output stream, error stream, and exit status in a CommandResult.

Examples:

With normal output

result = AwesomeSpawn.run('echo Hi')
# => #<AwesomeSpawn::CommandResult:0x007f9d1d197320 @exit_status=0>
result.output       # => "Hi\n"
result.error        # => ""
result.exit_status  # => 0

With error output as well

result = AwesomeSpawn.run('echo Hi; echo "Hi2" 1>&2')
# => <AwesomeSpawn::CommandResult:0x007ff64b98d930 @exit_status=0>
result.output       # => "Hi\n"
result.error        # => "Hi2\n"
result.exit_status  # => 0

With exit status that is not 0

result = AwesomeSpawn.run('false')
#<AwesomeSpawn::CommandResult:0x007ff64b971410 @exit_status=1>
result.exit_status  # => 1

With parameters sanitized

result = AwesomeSpawn.run('echo', :params => {:out => "; rm /some/file"})
# => #<AwesomeSpawn::CommandResult:0x007ff64baa6650 @exit_status=0>
result.command_line
# => "echo --out \\;\\ rm\\ /some/file"

With data to be passed on stdin

result = AwesomeSpawn.run('cat', :in_data => "line1\nline2")
=> #<AwesomeSpawn::CommandResult:0x007fff05b0ab10 @exit_status=0>
result.output
=> "line1\nline2"

With environment variables passed in

result = AwesomeSpawn.run('echo ABC=${ABC}', :env => {"ABC" => "abcde"})
=> #<AwesomeSpawn::CommandResult:0x007f9421a35590 @exit_status=0>
result.output
=> "ABC=abcde\n"

Parameters:

  • command (String)

    The command to run

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

    The options for running the command. Also accepts any option that can be passed to Kernel.spawn, except :in, :out and :err.

Options Hash (options):

  • :params (Hash, Array)

    The command line parameters. See #build_command_line for how to specify params.

  • :in_data (String)

    Data to be passed on stdin.

  • :env (Hash<String,String>)

    Additional environment variables for sub process

Returns:

  • (CommandResult)

    the output stream, error stream, and exit status

Raises:

See Also:



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

def run(command, options = {})
  bad_keys = (options.keys.flatten & [:in, :out, :err]).map { |k| ":#{k}" }
  raise ArgumentError, "options cannot contain #{bad_keys.join(", ")}" if bad_keys.any?
  env, command_line, options = parse_command_options(command, options)

  if (in_data = options.delete(:in_data))
    options[:stdin_data] = in_data
  end

  output, error, status = launch(env, command_line, options)
rescue Errno::ENOENT => err
  raise NoSuchFileError.new(err.message) if NoSuchFileError.detected?(err.message)
  raise
else
  CommandResult.new(command_line, output, error, status)
end

#run!(command, options = {}) ⇒ CommandResult

Same as #run, additionally raising a CommandResultError if the exit status is not 0.

Examples:

With exit status that is not 0

error = AwesomeSpawn.run!('false') rescue $!
# => #<AwesomeSpawn::CommandResultError: false exit code: 1>
error.message # => false exit code: 1
error.result  # => #<AwesomeSpawn::CommandResult:0x007ff64ba08018 @exit_status=1>

Returns:

  • (CommandResult)

    the output stream, error stream, and exit status

Raises:



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/awesome_spawn.rb', line 98

def run!(command, options = {})
  command_result = run(command, options)

  if command_result.failure?
    message = CommandResultError.default_message(command, command_result.exit_status)
    logger.error("AwesomeSpawn: #{message}")
    logger.error("AwesomeSpawn: #{command_result.error}")
    raise CommandResultError.new(message, command_result)
  end

  command_result
end