当.rb文件直接调用时,bundler起作用,从其他Ruby脚本通过EXEC调用时会失败



我需要使用bundler gemfile从另一个ruby script1.rb使用bundler gemfile来调用ruby script2.rb。

我注意到Script2.RB的宝石只是script1.rb的宝石。script2.rb script1.rb调用script2.rb时,script2.rb独有的gems。当Script2.rb直接从Bash Shell调用时,所有内容都可用。

我确保这不是一个env问题,我在两个文件中使用diff与助手代码进行了比较,并进行了几个修改以使其匹配。

File.open("script2_env.txt", 'wb') {|f| f.write(JSON.pretty_generate(ENV.to_h))}

确保这不是$ load_path问题,我还确保它们匹配。

在script2.rb中,由script1.rb调用,我添加了以下行以匹配script1的$ load_path1:

$:.unshift "/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash"

我对问题的理解是,当script2.rb从script1.rb调用时,bundler以某种方式无法正确初始化,也许是因为没有

eval "$(rbenv init -)"

就像我的bash_profile中的那样

script1/script1.rb:

#!/usr/bin/env ruby
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ;  Bundler.setup
require "awesome_print"
ap "in script1, we have awesome_print in our GemFile"
exec("/Users/charbon/wip/script2/script2.rb")

script1/gemfile

source 'https://rubygems.org'
gem 'awesome_print'

script2.rb:

#!/usr/bin/env ruby
puts "we are now in script2.rb"
$:.unshift "/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash"
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
#make ENV match to script1 ENV
ENV.delete('BUNDLER_ORIG_GEM_PATH') 
ENV['BUNDLE_GEMFILE']=ourDir+"/Gemfile"
ENV['RBENV_DIR']=ourDir
require 'bundler' ;
Bundler.setup
require 'awesome_print'
ap "in script2, we also have awesome_print in our GemFile"
puts "but we also have colored, which is not available, this throws an erro"
require "colored"

script2/gemfile

source 'https://rubygems.org'
gem 'awesome_print'
gem 'colored'

结果是

 /Users/charbon/wip/script1/script1.rb 
"in script1, we have awesome_print in our GemFile"
we are now in script2.rb
ourDir is /Users/charbon/wip/script2
"in script2, we also have awesome_print in our GemFile"
but we also have colored, which is not available, this throws an error
/Users/charbon/wip/script2/script2.rb:19:in `require': cannot load such file -- colored (LoadError)
    from /Users/charbon/wip/script2/script2.rb:19:in `<main>'

script1.rb

#!/usr/bin/env ruby
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ;  Bundler.setup
require "awesome_print"
ap "in script1, we have awesome_print in our GemFile"
Bundler.with_clean_env do
  Dir.chdir('/Users/charbon/wip/script2/script2.rb') do
    exec("./script2.rb")
  end 
end

script2.rb

#!/usr/bin/env ruby
puts "we are now in script2.rb"
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)

require 'bundler' ;
Bundler.setup
require 'awesome_print'
ap "in script2, we also have awesome_print in our GemFile"
puts "but we also have colored, which is not available, this throws an erro"
require "colored"

从我对原始问题的评论中:

Bundler支持内联Gemfiles,使您可以直接在Ruby脚本中指定所需的宝石(和来源!(。只要您在计算机上安装了Bundler,就可以使您保持脚本依赖关系。

Bundler将处理安装&amp;需要所需的宝石,允许您运行脚本

总结并完成Marat Amerov的答案:

Bundler有很好的记录:

任何打开子壳的Ruby代码(例如系统,Backticks或%X {}(都会自动使用当前的Bundler环境。如果您需要将不是当前捆绑包的Ruby命令,请使用with_clean_env方法与block

第二个解决方案如杰伊·多尔西(Jay Dorsey(所评论:使用Bundler/inline方法

我已经测试了这两种方法,并且它们工作正常。

似乎您需要在调用script2.rb之前制作Dir.chdir "/Users/charbon/wip/script2/"。您是从目录中调用script2.rb的,那里没有gemfile。脚本看起来像这样:

#!/usr/bin/env ruby
cwd=Dir.pwd ; ourDir=File.dirname(__FILE__) ; Dir.chdir(ourDir)
require 'bundler' ;  Bundler.setup
require "awesome_print"
ap "in script1, we have awesome_print in our GemFile"
Dir.chdir "/Users/charbon/wip/script2/"
exec("script2.rb")

最新更新