当直接调用.rb文件时,Bundler起作用;通过其他Ruby脚本中的exec调用时,Bundler失败

时间:2019-06-26 09:56:18

标签: ruby rubygems bundler

我需要使用Bundler + Gemfile从另一个ruby script1.rb使用Bundler + Gemfile调用ruby script2.rb。

我注意到script2.rb可用的Gems只有script1.rb可用。当script1.rb调用script2.rb时,script2.rb特有的gem不可用。 直接从bash shell调用script2.rb时,一切都可用。

我确保这不是一个ENV问题,我在两个文件中都使用了diff和帮助程序代码来比较它们,并进行了一些修改以使它们匹配。

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

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

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

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

我对问题的理解是,当从script1.rb调用script2.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>'

4 个答案:

答案 0 :(得分:4)

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"

答案 1 :(得分:4)

总结并完成Marat Amerov的答案:

捆绑商非常well documented

  

任何打开子外壳的Ruby代码(例如系统,反引号或%x {})都将自动使用当前的Bundler环境。如果您需要使用不属于当前捆绑软件的Ruby命令,请使用with_clean_env方法和一个块

第二种解决方案如Jay Dorsey所述:使用bundler/inline method

我已经测试了这两种方法,它们都可以正常工作。

答案 2 :(得分:4)

根据我对原始问题的评论:

Bundler支持inline Gemfiles,可让您直接在红宝石脚本中指定所需的宝石(和来源!)。只要在计算机上安装了捆绑程序,它就可以正常工作,从而使脚本依赖项保持隔离状态。

Bundler将处理安装并需要必需的gem,从而使您可以运行脚本

答案 3 :(得分:2)

似乎您需要在致电Dir.chdir "/Users/charbon/wip/script2/"之前制作script2.rb。 您正在从没有Gemfile的目录中调用script2.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"
Dir.chdir "/Users/charbon/wip/script2/"
exec("script2.rb")