探讨 "bundle exec"

11 Sep 2017

Bundler的带头人是Andre Arko,他还是The Ruby Way的作者

在Bundler的文档里有解释bundle exec为何物

Execute a command in the context of the bundle

在当前的bundle环境中运行一个指令

这个命令只会运行那些来源于 在Gemfile里被指出的gem所包含的指令。

What does “bundle exec” mean? | The Art and Science of Ruby这篇博文通过rails的历史发展来讲述的。 在rails 3以前,并没有Gemfile这个东西。如果,你拿到别人的项目,如果作者不告诉你,你根本不知道该项目依赖了哪些第三方的gems.而从rails 3 开始就引入了Bundler,而正是bundler使用了Gemfile这个文件,来管理所有依赖的第三方gem。但也有一些场景就是,我们因为某些原因,没有在Gemfile里继续引入某个gem,但我的输入的命令依然会使用该命令,那么就可以使用bundle exec,因为bundle exec会根据Gemfile.lock里的记录来运行命令。

但其实,我们这种场景,我几乎想不到什么时候会使用。 然后我又看到了下面两篇资料 Bundle Exec已解决 what’s ‘bundle exec’ used for ? · Ruby China 他们都提到了一种场景,你本机电脑安装了最新版的rake,然后你的新项目中也使用的新的rake,但是你的旧项目里依然使用的旧版本rake,如果你在旧的项目里直接执行rake rails rspec打头的命令,可能就会报错

# Error
rake aborted!
Gem::LoadError: You have already activated rake 10.4.2, but your Gemfile requires rake 10.4.0. Prepending `bundle exec` to your command may solve this.

这种情况下就说明,新版本的rake的改动影响到旧版本的命令的运行。于是,我们就要在前面加上bundle exec来让旧项目继续使用旧版本的rake。

但同时,第一篇从历史角度讲的博文里有提到,rails 4以后rake rails rspec实际上就是在帮你调用bundle,所以不用再手动输入bundle exec。但是并没有指出什么样的特殊情况需要再手动输入。 而且,我还看到下面这个2016年写的文章,甚至有人为了节省输入,就通过在bash里设置一个别名来简化输入bundle exec的痛苦过程。(Shell alias to stop writing bundle exec (Example)) 这也就间接的说明,还是有使用场景的。

不过4篇文章总结下的结论是:

不用特别的去考虑它,当出现上面的报错的时候,再在前面加入budnel exec