module CommandLine
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.
Constants
- VERSION
Public Instance Methods
Run a command and get back the result.
@param command [String] The command to run. @param args [Array] Any arguments passed to the command. All arguments will
be converted to strings using `to_s`.
@param [Hash] env: 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.
@param [Integer, Float, nil] Number 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.
@yield [stdin] Handle any input on stdin that the command needs. @yieldparam stdin [IO]
@example
command_line('echo', 'hello')
@example
command_line('command_expecting_input') do |stdin| stdin.puts "first input" stdin.puts "second input" end
@example
command_line('some_webserver', env: { PORT: '80' })
@return [Result]
# 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
Same as {CommandLine.command_line} except that a failure on exit raises an error.
@example
command_line!('echo', 'hello')
@example
command_line!('grep') # => CommandLine::ExitFailureError (usage: grep ...
@return [Result] @raise [CommandLine::ExitFailureError] If the application exits with an
error status. The message will be the contents of Result#stderr.
# 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