Bundler serves two primary purposes:

  1. it helps you to install the correct gem versions
  2. it constrains the load path to the correct gem versions at runtime

Assuming you’re using Bundler to constrain your runtime environment (which you are if you’re using Rails 3 defaults), then you are likely prefixing most shell commands with bundle exec.

We interrupt this post for an important update:

Two important pieces of information in the comments:

  1. Prepending ./bin to your path exposes a serious security risk. Proceed with caution.
  2. rvm >= 1.6.18 + bundler >= 1.0.5 removes the need for this altogether.

We now return you to our regularly scheduled post:

Here’s a little tip to help save you the prefix, without adding any aliases or functions to your environment.

bundle install --binstubs
export PATH=./bin:$PATH

bundle install --binstubs creates a bin directory at the root of your project, and fills it with Bundler-enabled wrappers for all of the executables installed by the gems listed in your Gemfile. This enables you to type bin/rake instead of bundle exec rake, for example, ensuring that the correct version of rake is loaded.

Now prepend ./bin to your path and you can just type rake.

22 Responses to “Stop typing “bundle exec””

  1. Gravis Says:

    What a terrible security hole :) I hope you’ll never encounter a repo with “bin/ls” being an alias to “rm -rf ~/” ;)

  2. Chris Flipse Says:

    Be careful with the path modification …

    One of the nice things about rake is that you can run it from any directory, and it will walk up the tree until it finds a Rakefile. If, for some reason, you’re not in the root of your project, running the command alone will fall back to the system version of the gem and bypass bundler altogether. Might not be what you’re expecting.

    For that reason, I tend to prefer to just do ./bin/rake … it fails when I’m not where expected, instead of silently doing the unexpected thing.

    @Gravis: At that point, you’re already trusting running code from a third party. Nobody needs to get into shell scripts in the bin directory to twist the knife, they could just bury it in the project code.

    In the general case though, I agree. I believe there’s an old bit of UNIX wisdom that holds that you never put relative directories in your PATH, largely for that reason.

  3. Rhett Sutphin Says:

    An alternative that does not leave you open to exploitation by malicious bin directories:

    alias b='bundle exec'
    b rake
    

    It’s just two keystrokes more.

  4. Winfield Says:

    I expected the security snark, but this is a very useful feature.

    Don’t get hung up on the relative path in the example, there’s no reason you can’t swap in and out an absolute path when you’re configuring the environment for a project.

    Thanks for posting this, Dan.

  5. han Says:

    i just link ‘/usr/bin/be’ to bundle exec

    for the exact reasons in the article i think we should use bundle exec even more! granted bundle exec is dead-slow

    but we’d be really constraining ourselves to the same gem runtime environment as our final app which is a good thing!

    something RoR-ers always fail to do when they plaster their machines with lots of native libs, dangerous system calls and multi versions of the same gems

  6. David Chelimsky Says:

    @Gravis - this is something I do in the development environment in my own projects. I guess some upstream gem could install its own ls command and screw people up, but that would be a problem in many more environments than the one I’m describing.

    @Rhett and @han - I used to use a ‘be’ alias as well, but I like this better.

    @Chris - I pretty much run everything from the project root. Even though rake will look for the Rakefile, not all tools will do the same.

  7. Bob Nadler Says:

    If your using the latest version of rvm with bundler, rvm should take care of this for you.

    http://beginrescueend.com/integration/bundler/

  8. probonogeek Says:

    The point about not adding relative directories to your path isn’t just limited to upstream gems, it has to do with general system security against all forms of malicious code. The command suggested puts ./bin at the front of all other binary paths, so it becomes very easy for malicious code to be executed in place of system binaries like ls, git, you name it… at which point it’s not just gems… it’s anything that has any sort of write permissions to your system, whether that be other package managers, OS X app installers, or even your browser.

    The risk may very well be worth it to some developers, but as it goes against decades of learned UNIX experience, anyone contemplating this approach should at least understand the full nature of the risk and weigh that against the benefits.

  9. Ken Says:

    Good tip; however, I wish it worked on Windows.

  10. David Chelimsky Says:

    Thanks all for the pointer to rvm and clarity on the security risk. I’ve updated the post accordingly.

  11. Fletcher Nichol Says:

    Unless I’m mistaken, the rvm/bundler support was taken out for now (https://github.com/wayneeseguin/rvm/commit/e8c1b87e1da57ed9d58d15ba3763f2d19e5f8170) which would make the site docs inaccurate.

  12. Michal Papis Says:

    the rvm support was rejected and removed from rvm by bundler team (without updating docs), after long discussions with rubygems/bundler team I have created separate gem to solve the problem https://github.com/mpapis/rubygems-bundler

  13. Gregório Kusowski Says:

    I just found this(seems to be a soft option ;) ): http://twistedmind.com/bundle-exec-bash-shortcut

  14. Ted Milker Says:

    So that explains why rvm has been crapping bin/ folders all over my filesystem. :(

  15. Arturo Says:

    What you want is the ‘alias’ command…

  16. Marc Bowes Says:

    I also implemented a solution using alias, then saw it’s very similar to the one on twistedmind. http://marc-bowes.com/2011/09/21/dry-your-bundle-exec-tears.html

  17. Uri Sharf Says:

    BTW, rbenv prepends itself to the path, so it’s shims will be found first if same gems are installed globally.

  18. Darren Says:

    If you are using RVM, and .rvmrc, you can add the following line to your .rvmrc file…

    export PATH=”pwd/bin:$PATH”

    This will change your path while you are in your project. The change will not persist in your environment when you leave your project.

    I find this useful in cases where I want the binstubs in a different folder. I.e., when working on a project that has a legitimate ‘bin’ directory, I “bundle install –binstubs=bbin” and add that directory to .rvmrc.

  19. Judson Lester Says:

    I put this together a little while ago: use –binstubs for each project once, have your path set properly regardless of what directory you’re in. It’s in bash, or I’d write a gem.

    https://gist.github.com/1290098

  20. Peter van Hardenberg Says:

    I just pretend bundler works like rubygems. If there’s a Gemfile, this works. It also means any ruby-language tools you use need to be in your Gemfile while you’re working in a given directory but:

    export RUBYOPT=”rubygems I$( dirname gem which bundler ) rbundler/setup”

  21. Masterchief Says:

    How about the security hole caused by the fact that rvm requires shell login to run? Everywhere I read about *nix security, the suggestion is to turn this off. In my case, I’m trying to run a Jenkins CI Server, and I don’t want to give the Jenkins user account the ability to run shell login. Yet, apparently, if I want to use rvm, I have to.

  22. cars Says:

    All large purchases are always intimidating, especially if you are uninformed about the industry. One of the scariest purchases is buying cars. Many people fear they are getting ripped off and you surely don’t want that. Avoid buying a lemon by looking through these great tips and tricks regarding car purchases.

Leave a Reply