bundle-exec
- 在捆绑器上下文中执行命令
bundle exec
[--keep-file-descriptors] command
此命令执行命令,使 Gemfile(5)
中指定的 gem 在 Ruby 程序中可供 require
使用。
本质上,如果您通常会运行类似 rspec spec/my_spec.rb
的命令,并且您想使用 Gemfile(5)
中指定的 gem 并通过 bundle install(1) 安装,您应该运行 bundle exec rspec spec/my_spec.rb
。
请注意,bundle exec
不需要在 shell 的 $PATH
上提供可执行文件。
--keep-file-descriptors
如果您在 bundle install(1) 中使用 --binstubs
标志,捆绑器将自动创建一个目录(默认情况下为 app_root/bin
),其中包含捆绑包中 gem 提供的所有可执行文件。
使用 --binstubs
后,bin/rspec spec/my_spec.rb
等同于 bundle exec rspec spec/my_spec.rb
。
bundle exec
对 shell 环境进行了一些更改,然后完全执行您指定的命令。
bundle exec
调用的命令内部(使用 $BUNDLE_BIN_PATH
)调用 shell 到 bundle
rails
、rspec
、rackup
)的目录放在 $PATH
上
Gemfile
(通过设置 BUNDLE_GEMFILE
)-rbundler/setup
添加到 $RUBYOPT
,这将确保在子 shell 中调用的 Ruby 程序可以看到捆绑包中的 gem它还修改了 Rubygems
gem
方法,如果捆绑包中存在与要求匹配的 gem,则为无操作,如果不存在,则引发 Gem::LoadError
Gem.refresh
为无操作,因为在使用捆绑器时源索引始终被冻结,并且为了防止系统中的 gem 泄漏到环境中Gem.bin_path
以使用捆绑包中的 gem,使系统可执行文件正常工作最后,bundle exec
还会在锁定文件和 Gemfile 不匹配时隐式修改Gemfile.lock
。Bundler 需要 Gemfile 来确定 gem 的组、autorequire
和平台等信息,这些信息不会存储在锁定文件中。为了使bundle exec
成功,Gemfile 和锁定文件必须同步,因此bundle exec
会事先更新锁定文件。
默认情况下,当尝试使用带有 Ruby shebang 的文件执行bundle exec
时,Bundler 会Kernel.load
该文件,而不是使用Kernel.exec
。在绝大多数情况下,这是一种性能提升。在极少数情况下,这可能会导致一些细微的副作用(例如依赖于$0
或__FILE__
的确切内容),并且可以通过启用disable_exec_load
设置来禁用此优化。
任何打开子 shell 的 Ruby 代码(如system
、反引号或%x{}
)都会自动使用当前的 Bundler 环境。如果需要对当前捆绑包中不包含的 Ruby 命令执行外壳命令,请使用with_unbundled_env
方法并带一个代码块。在代码块内创建的任何子 shell 都将获得 Bundler 激活之前的环境。例如,Homebrew 命令运行 Ruby,但不能在捆绑包内运行
Bundler.with_unbundled_env do
`brew install wget`
end
如果要对不同的捆绑包执行外壳命令,也需要使用with_unbundled_env
。在子 shell 中运行的任何 Bundler 命令都会继承当前的 Gemfile,因此需要在不同捆绑包的上下文中运行的命令也需要使用with_unbundled_env
。
Bundler.with_unbundled_env do
Dir.chdir "/other/bundler/project" do
`bundle exec ./script`
end
end
Bundler 提供了包装system
和exec
的便捷帮助程序,可以使用以下方式使用它们
Bundler.clean_system('brew install wget')
Bundler.clean_exec('brew install wget')
目前,Rubygems 插件系统要求在任何 Ruby 代码需要rubygems.rb
时,在任何已安装 gem 的加载路径上包含名为rubygems_plugin.rb
的所有文件。这包括安装到系统中的可执行文件,如rails
、rackup
和rspec
。
由于 Rubygems 插件可以包含任意 Ruby 代码,它们通常会自行激活或激活其依赖项。
例如,gemcutter 0.5
gem 依赖于 json_pure
。如果你安装了该版本的 gemcutter(即使你也安装了没有此问题的更新版本),Rubygems 将激活 gemcutter 0.5
和 json_pure <latest>
。
如果你的 Gemfile(5) 也包含 json_pure
(或依赖于 json_pure
的 gem),系统上的最新版本可能与你 Gemfile(5) 中的版本冲突,或者与你 Gemfile.lock
中的快照版本冲突。
如果发生这种情况,bundler 会说
You have already activated json_pure 1.4.6 but your Gemfile
requires json_pure 1.4.3. Consider using bundle exec.
在这种情况下,你几乎肯定想要删除包含有问题的 gem 插件的底层 gem。通常,这些插件的作者(在本例中为 gemcutter
gem)已经发布了更新版本,这些版本在插件方面更加谨慎。
你可以通过运行以下命令找到包含 gem 插件的所有 gem 的列表:
ruby -e "puts Gem.find_files('rubygems_plugin.rb')"
至少,你应该删除除每个 gem 插件的最新版本之外的所有版本,并删除所有未使用的 gem 插件(gem uninstall gem_name
)。