Warm tip: This article is reproduced from stackoverflow.com, please click
ruby rubygems bundler

Bundler works when .rb file called directly, fails when called via exec from other ruby script

发布于 2020-03-27 10:24:36

I need to call a ruby script2.rb using Bundler + Gemfile from another ruby script1.rb using Bundler + Gemfile.

I noticed that the Gems available to script2.rb are only those of script1.rb. The gems unique to script2.rb are not available when script2.rb is called by script1.rb. When script2.rb is called directly from the bash shell, everything is available.

I made sure it's not an ENV problem, I compared them using diff with helper code like so in both files and made a couple modifications to make them match.

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

To make sure it was not a $LOAD_PATH problem, I also made sure they match.

In script2.rb, which is called by script1.rb, I added the following line to match the $LOAD_PATH of script1 :

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

My understanding of the problem is that somehow Bundler is not initialized properly when script2.rb is called from script1.rb, maybe because there is no

eval "$(rbenv init -)"

as there is in my 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'

The result is

 /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>'
Questioner
MichaelC
Viewed
69
Marat Amerov 2019-07-02 02:34

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"