Giter Site home page Giter Site logo

cocaine's Introduction

Cocaine Build Status

A small library for doing (command) lines.

API reference

Usage

The basic, normal stuff:

line = Cocaine::CommandLine.new("echo", "hello 'world'")
line.command # => "echo hello 'world'"
line.run # => "hello world\n"

Interpolated arguments:

line = Cocaine::CommandLine.new("convert", ":in -scale :resolution :out")
line.command(in: "omg.jpg",
             resolution: "32x32",
             out: "omg_thumb.jpg")
# => "convert 'omg.jpg' -scale '32x32' 'omg_thumb.jpg'"

It prevents attempts at being bad:

line = Cocaine::CommandLine.new("cat", ":file")
line.command(file: "haha`rm -rf /`.txt") # => "cat 'haha`rm -rf /`.txt'"

line = Cocaine::CommandLine.new("cat", ":file")
line.command(file: "ohyeah?'`rm -rf /`.ha!") # => "cat 'ohyeah?'\\''`rm -rf /`.ha!'"

NOTE: It only does that for arguments interpolated via run, NOT arguments passed into new (see 'Security' below):

line = Cocaine::CommandLine.new("echo", "haha`whoami`")
line.command # => "echo haha`whoami`"
line.run # => "hahawebserver"

You can ignore the result:

line = Cocaine::CommandLine.new("noisy", "--extra-verbose", swallow_stderr: true)
line.command # => "noisy --extra-verbose 2>/dev/null"

# ... and on Windows...
line.command # => "noisy --extra-verbose 2>NUL"

If your command errors, you get an exception:

line = Cocaine::CommandLine.new("git", "commit")
begin
  line.run
rescue Cocaine::ExitStatusError => e
  e.message # => "Command 'git commit' returned 1. Expected 0"
end

If your command might return something non-zero, and you expect that, it's cool:

line = Cocaine::CommandLine.new("/usr/bin/false", "", expected_outcodes: [0, 1])
begin
  line.run
rescue Cocaine::ExitStatusError => e
  # => You never get here!
end

You don't have the command? You get an exception:

line = Cocaine::CommandLine.new("lolwut")
begin
  line.run
rescue Cocaine::CommandNotFoundError => e
  e # => the command isn't in the $PATH for this process.
end

But don't fear, you can specify where to look for the command:

Cocaine::CommandLine.path = "/opt/bin"
line = Cocaine::CommandLine.new("lolwut")
line.command # => "lolwut", but it looks in /opt/bin for it.

You can even give it a bunch of places to look:

    FileUtils.rm("/opt/bin/lolwut")
    File.open('/usr/local/bin/lolwut') {|f| f.write('echo Hello') }
    Cocaine::CommandLine.path = ["/opt/bin", "/usr/local/bin"]
    line = Cocaine::CommandLine.new("lolwut")
    line.run # => prints 'Hello', because it searches the path

Or just put it in the command:

line = Cocaine::CommandLine.new("/opt/bin/lolwut")
line.command # => "/opt/bin/lolwut"

You can see what's getting run. The 'Command' part it logs is in green for visibility!

line = Cocaine::CommandLine.new("echo", ":var", logger: Logger.new(STDOUT))
line.run(var: "LOL!") # => Logs this with #info -> Command :: echo 'LOL!'

Or log every command:

Cocaine::CommandLine.logger = Logger.new(STDOUT)
Cocaine::CommandLine.new("date").run # => Logs this -> Command :: date

Security

Short version: Only pass user-generated data into the run method and NOT new.

As shown in examples above, Cocaine will only shell-escape what is passed in as interpolations to the run method. It WILL NOT escape what is passed in to the second argument of new. Cocaine assumes that you will not be manually passing user-generated data to that argument and will be using it as a template for your command line's structure.

POSIX Spawn

You can potentially increase performance by installing the posix-spawn gem. This gem can keep your application's heap from being copied when forking command line processes. For applications with large heaps the gain can be significant. To include posix-spawn, simply add it to your Gemfile or, if you don't use bundler, install the gem.

Runners

Cocaine will attempt to choose from among 3 different ways of running commands. The simplest is using backticks, and is the default in 1.8. In Ruby 1.9, it will attempt to use Process.spawn. And, as mentioned above, if the posix-spawn gem is installed, it will attempt to use that. If for some reason one of the .spawn runners don't work for you, you can override them manually by setting a new runner, like so:

Cocaine::CommandLine.runner = Cocaine::CommandLine::BackticksRunner.new

And if you really want to, you can define your own Runner, though I can't imagine why you would.

JRuby issues

Caveat

If you get Error::ECHILD errors and are using JRuby, there is a very good chance that the error is actually in JRuby. This was brought to our attention in thoughtbot#24 and probably fixed in http://jira.codehaus.org/browse/JRUBY-6162. You will want to use the BackticksRunner if you are unable to update JRuby.

Spawn warning

If you get unsupported spawn option: out warning (like in issue 38), try to use PopenRunner:

Cocaine::CommandLine.runner = Cocaine::CommandLine::PopenRunner.new

Thread Safety

Cocaine should be thread safe. As discussed here, in this climate_control thread, climate_control, which modifies the environment under which commands are run for the BackticksRunner and PopenRunner, is thread-safe but not reentrant. Please let us know if you find this is ever not the case.

Feedback

Security concerns must be privately emailed to [email protected].

Question? Idea? Problem? Bug? Comment? Concern? Like using question marks?

GitHub Issues For All!

Credits

Thank you to all the contributors!

thoughtbot

Cocaine is maintained and funded by thoughtbot, inc

The names and logos for thoughtbot are trademarks of thoughtbot, inc.

License

Copyright 2011-2014 Jon Yurek and thoughtbot, inc. This is free software, and may be redistributed under the terms specified in the LICENSE file.

cocaine's People

Contributors

alindeman avatar arunagw avatar baldowl avatar bitgangsta avatar brixen avatar citrus avatar cthulhu666 avatar gabebw avatar gpg0 avatar hron avatar jjb avatar jneander avatar joshuaclayton avatar ka8725 avatar kirs avatar ktdreyer avatar mike-burns avatar nifarius avatar nixpulvis avatar radarek avatar sapslaj avatar sikachu avatar sshaw avatar tanner avatar tapajos avatar viseztrance avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.