Shellex
Shellex allows you to run shell commands from your ruby scripts in a more robust and secure way than the built-in options. We're using this code in Beanstalk to keep the shell commands we execute secure against shell injection and keep every executed command under a tight timeout. This code also helps us construct complex shell commands easily thanks to the interpolation strategies listed below.
Installation
Add this line to your application's Gemfile:
gem 'shellex'
And then execute:
$ bundle
Or install it yourself as:
$ gem install shellex
Usage
Grabbing STDOUT output:
stdout, stderr = shellex("echo hello, world!")
# stdout => "hello, world!\n"
# stderr => ""
Grabbing STDERR output:
stdout, stderr = shellex("echo error here 1>&2")
# stdout => ""
# stderr => "error here\n"
Convenience methods:
shellex("echo hello, world").to_s # => "hello, world\n"
shellex("echo hello, world").stdout # => "hello, world\n"
shellex("echo error here 1>&2").stderr # => "error here\n"
Providing STDIN input:
shellex("cat -", :input => "hello").stdout # => "hello"
By default if you don't provide input we close the STDIN stream, but if you want you can leave it open:
shellex("cat /dev/stdin", :close_stdin => false)
Timeouts (default timeout is set to 5 minutes):
shellex("sleep 10", :timeout => 1) # raises ShellExecutionTimeout exception
Interpolation of arguments:
# to_s gets called on all arguments
shellex("echo ? ? ?", 1, "blah", :symbol)
# executes: echo '1' 'blah' 'symbol'
# ?& interpolates each array element separately
shellex("? ?& ?", "echo", [1,2,3,4], "abc")
# executes: 'echo' '1' '2' '3' '4' 'abc'
# ?& requires array to be present in the respective position
shellex("? ?& ?", "echo", 1) # raises ShellArgumentMissing
# ?~ escapes question mark
shellex("? ?~", "echo", "ello")
# executes: 'echo' ?
# ? by default will turn nil into empty string
shellex("echo ?", nil)
# executes: echo ''
# ?? will skip the argument if it's nil
shellex("echo ??", nil)
# executes: echo
# Shell injection protection
shellex("echo ?", "'; rm -Rf /; '")
# executes harmless: echo ''\''; rm -Rf /; '\'''
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request