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
旗標,Bundler 會自動建立一個目錄(預設為 app_root/bin
),其中包含套件中 gem 提供的所有可執行檔。
使用 --binstubs
之後,bin/rspec spec/my_spec.rb
等同於 bundle exec rspec spec/my_spec.rb
。
bundle exec
會對 shell 環境進行多項變更,然後完整執行你指定的指令。
bundle exec
呼叫的指令中,仍然可以透過 shell 將指令傳遞給 bundle
(使用 $BUNDLE_BIN_PATH
)rails
、rspec
、rackup
)的目錄放在 $PATH
中
Gemfile
(透過設定 BUNDLE_GEMFILE
)-rbundler/setup
新增到 $RUBYOPT
,這可以確保在子 shell 中呼叫的 Ruby 程式可以看到套件中的 gem它也會修改 Rubygems
gem
方法,如果套件中有符合需求的 gem,則使其成為空操作;如果沒有,則引發 Gem::LoadError
Gem.refresh
為 no-op,因為使用 bundler 時,來源索引始終凍結,且可防止系統中的 gem 洩漏到環境中Gem.bin_path
以使用 bundle 中的 gem,使系統可執行檔正常運作最後,如果鎖定檔和 Gemfile 不相符,bundle exec
也會隱式修改 Gemfile.lock
。Bundler 需要 Gemfile 來判斷 gem 的群組、autorequire
、平台等資訊,而這些資訊並未儲存在鎖定檔中。Gemfile 和鎖定檔必須同步才能順利執行 bundle exec
,因此 bundle exec
會事先更新鎖定檔。
預設情況下,當嘗試將 bundle exec
執行到具有 ruby shebang 的檔案時,Bundler 會 Kernel.load
該檔案,而不是使用 Kernel.exec
。在絕大多數情況下,這是一種效能提升。在極少數情況下,這可能會造成一些微妙的副作用(例如依賴 $0
或 __FILE__
的確切內容),且可以透過啟用 disable_exec_load
設定來停用最佳化。
任何開啟子外殼的 Ruby 程式碼(例如 system
、反引號或 %x{}
)都將自動使用目前的 Bundler 環境。如果您需要外殼執行到不屬於目前 bundle 的 Ruby 指令,請使用 with_unbundled_env
方法搭配區塊。在區塊內建立的任何子外殼都將獲得在 Bundler 啟動前存在的環境。例如,Homebrew 指令會執行 Ruby,但無法在 bundle 內執行
Bundler.with_unbundled_env do
`brew install wget`
end
如果您要外殼執行到不同的 bundle,也需要使用 with_unbundled_env
。在子外殼中執行的任何 Bundler 指令都將繼承目前的 Gemfile,因此需要在不同 bundle 的內容中執行的指令也需要使用 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 外掛程式系統需要在任何已安裝 gem 的載入路徑上放置所有命名為 rubygems_plugin.rb
的檔案,當任何 Ruby 程式碼需要 rubygems.rb
時。這包括安裝到系統中的可執行檔,例如 rails
、rackup
和 rspec
。
由於 Rubygems 外掛程式可以包含任意 Ruby 程式碼,因此它們通常會自行啟動或啟動其依賴項。
例如,gemcutter 0.5
寶石依賴 json_pure
。如果您已安裝該版本的 gemcutter(即使您也安裝了沒有這個問題的更新版本),Rubygems 會啟用 gemcutter 0.5
和 json_pure <latest>
。
如果您的 Gemfile(5) 也包含 json_pure
(或依賴於 json_pure
的寶石),系統上的最新版本可能會與 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.
在這種情況下,您幾乎一定會想要移除具有問題的寶石外掛程式的底層寶石。一般來說,這些外掛程式的作者(在本例中為 gemcutter
寶石)已發布了更新版本,在他們的外掛程式中會更加謹慎。
您可以透過執行以下命令來尋找包含寶石外掛程式的寶石清單
ruby -e "puts Gem.find_files('rubygems_plugin.rb')"
至少,您應該移除每個寶石外掛程式的最新版本以外的所有版本,並移除所有您未使用的寶石外掛程式(gem uninstall gem_name
)。