Module: CommandLine

Defined in:
lib/command_line.rb,
lib/command_line/result.rb,
lib/command_line/version.rb

Overview

CommandLine provides an easier way to run command-line applications. It captures all outputs, can handle applications that require stdin, and can pass environment variables. It's also helpful for testing commmand-line applications.

Defined Under Namespace

Classes: Error, ExitFailureError, Result, TimeoutError

Constant Summary collapse

VERSION =
'2.0.1'

Class Method Summary collapse

Class Method Details

.command_line(command, *args, env: {}, timeout: nil) {|stdin| ... } ⇒ Result

Run a command and get back the result.

Examples:

command_line('echo', 'hello')
command_line('command_expecting_input') do |stdin|
  stdin.puts "first input"
  stdin.puts "second input"
end
command_line('some_webserver', env: { PORT: '80' })

Parameters:

  • command (String)

    The command to run.

  • args (Array)

    Any arguments passed to the command. All arguments will be converted to strings using to_s.

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

    Pass environment variables to use. The key is the name of the environment variable. The value is the value you want that variable to have.

  • Number (Integer, Float, nil)

    of seconds to wait for the block to terminate. Floats can be used to specify fractional seconds. A value of 0 or nil will execute the block without any timeout.

Yields:

  • (stdin)

    Handle any input on stdin that the command needs.

Yield Parameters:

  • stdin (IO)

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/command_line.rb', line 53

def command_line(command, *args, env: {}, timeout: nil)
  stdout = ''
  stderr = ''
  status = nil

  full_command = [command, *args].map(&:to_s).join(' ')
  environment = env.transform_keys(&:to_s)
  Open3.popen3(environment, full_command) do |i, o, e, wait_thr|
    threads = []

    Timeout.timeout(timeout, TimeoutError) do
      yield i if block_given?

      threads << Thread.new { stdout = o.read }
      threads << Thread.new { stderr = e.read }
      threads.each(&:join)
      status = wait_thr.value
    end
  rescue TimeoutError => e
    threads.map(&:kill)

    raise e
  end

  Result.new(stdout, stderr, status)
end

.command_line!(*args, **kwargs, &block) ⇒ Result

Same as command_line except that a failure on exit raises an error.

Examples:

command_line!('echo', 'hello')
command_line!('grep')
# => CommandLine::ExitFailureError (usage: grep ...

Returns:

Raises:

See Also:



95
96
97
98
99
# File 'lib/command_line.rb', line 95

def command_line!(*args, **kwargs, &block)
  command_line(*args, **kwargs, &block).tap do |result|
    raise ExitFailureError, result.stderr if result.failure?
  end
end