Project

qbash

0.0
A long-lived project that still receives updates
With the help of Open3 executes bash command and conveniently returns its output and exit code
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Runtime

 Project Readme

Quick and Simple Executor of Bash Commands

DevOps By Rultor.com We recommend RubyMine

rake PDD status Gem Version Test Coverage Yard Docs Hits-of-Code License

How do you execute a new shell command from Ruby? There are many ways. None of them offers a one-liner that would execute a command, print its output to the console or a logger, and then raise an exception if the exit code is not zero. This small gem offers exactly this one-liner.

First, install it:

gem install qbash

Then, you can use qbash global function:

require 'qbash'
stdout = qbash('echo "Hello, world!"', log: $stdout)

If the command fails, an exception will be raised.

The function automatically merges stderr with stdout (you can't change this).

It's possible to provide the standard input and environment variables:

stdout = qbash('cat > $FILE', env: { 'FILE' => 'a.txt' }, stdin: 'Hello!')

It's possible to configure the logging facility too, for example, with the help of the loog gem (the output will be returned and printed to the logger):

require 'loog'
qbash('echo "Hello, world!"', log: Loog::VERBOSE)

You can also make it return both stdout and exit code, with the help of the both option set to true:

stdout, code = qbash('cat a.txt', both: true, accept: [])

Here, the accept param contains the list of exit codes that are "acceptable" and won't lead to runtime failures. When the list is empty, all exists are acceptable (there will be no failures ever).

The command may be provided as an array, which automatically will be converted to a string by joining all items with spaces between them.

qbash(
  [
    'echo "Hello, world!"',
    '&& echo "How are you?"',
    '&& cat /etc/passwd'
  ]
)

If a block is given to qbash, it will run the command in background mode, waiting for the block to finish. Once it's finished, the command will be terminated via the TERM signal:

qbash('sleep 9999') do |pid|
  # do something
end

It is very much recommended to escape all command-line values with the help of the Shellwords.escape() utility method, for example:

file = '/tmp/test.txt'
qbash("cat #{Shellwords.escape(file)}")

Without such an escaping, in this example, a space inside the file will lead to an unpredictable result of the execution.

If you want to stop sooner than the command finishes, use timeout gem:

require 'timeout'
Timeout.timeout(5) do
  qbash('sleep 100')
end

This command will raise Timeout::Error exception after five seconds of waiting for the sleep to finish.

How to contribute

Read these guidelines. Make sure your build is green before you contribute your pull request. You will need to have Ruby 3.0+ and Bundler installed. Then:

bundle update
bundle exec rake

If it's clean and you don't see any error messages, submit your pull request.