开发者

How to run "bundle exec" from a specific Ruby version using RVM when shell environment is not there

开发者 https://www.devze.com 2023-03-17 04:43 出处:网络
Ok I have a confession to make - I still run a massive FCGI setup (just alot of servers configured). I am trying to adapt it to rvm. In the fcgi settings I can specify the commandline command to execu

Ok I have a confession to make - I still run a massive FCGI setup (just alot of servers configured). I am trying to adapt it to rvm. In the fcgi settings I can specify the commandline command to execute for running my application (Sinatra, Rack, Bundler, the whole thing), and this is what I'd do without rvm

"bin-path" => "bundle exec rackup",
"bin-environment" => (
    "RACK_ENV" => "development"
),

assuming my rackup file is just confi开发者_JAVA技巧g.ru. Now, on my Mac this works:

"bin-path" => env.HOME + "/.rvm/gems/ruby-1.9.2-p180/bin/bundle exec rackup " + CWD  + "/config.ru",
"bin-environment" => (
    "BUNDLE_GEMFILE" => CWD + "/Gemfile",
    "RACK_ENV" => "development"
),

but not on the server. When the dispatchers are started they get a stripped-down env where RVM shell trickery no longer works. I guess I should use the wrapper option to make some sort of wrapper but I don't really understand how that would alleviate my problem and which arguments to use. Does anyone have experience with enforcing a specific ruby and gem binaries without having RVM shell env loaded?

P.S. To prevent off-topic answers, no thanks I don't need Ruby 1.8.7, Passenger or nginx.


You should be able to use rvm exec:

Like most of the rvm set operations, exec lets your perform commands against all installed rubies. Unlike the others, there is a key distinction - exec lets you run any command (versus just ruby / gem and the like) and if it is only run against a single ruby, it performs the equivalent of exec (e.g. no error message) after setting up the environment.

If the rvm executable is on the $PATH for your webserver's user, you can do:

"bin-path" => "rvm 1.9.2-p180 exec bundle exec rackup"


EDIT: Turns out Jacob was right, sorry for the downvote. I've decided to expand on this solution a bit.

I could as it turns out use the rvm binary now, but since it's user-installed it is not on the $PATH on my laptop

bigbuk:~ julik$ which rvm
bigbuk:~ julik$ 

but it is on the server.

[julik@serveur ~]$ which rvm
/usr/local/rvm/bin/rvm
[julik@serveur ~]$

This is what confused me. Only it needs to be called with an absolute path (since FCGI runs without proper PATH being set). Se then the binary path should be configured accordingly, AND rvm will of course properly set GEM_HOME and GEM_PATH for us as well. The only thing that really needs to be set is the BUNDLE_GEMFILE one since Bundler cannot autodetect it from the rackup file and the cwd of the FCGI process is garbage.

"bin-path" => "/usr/local/rvm/bin/rvm 1.9.2-p180 exec bundle exec rackup /home/user/websites/behandelaar-web/current/web-root/",
"bin-environment" => (
    "BUNDLE_GEMFILE" => "/home/user/websites/behandelaar-web/current/Gemfile",
    "RACK_ENV" => "production",
 ),

That said, having a specific wrapper script written in Ruby does have some merit since both rackup AND bundle are very bad at bubbling exceptions, and if say there are problems with the FCGI gem itself (which was what I had - it had 1.8-specific string-bytes handling) it's exceptions will not bubble up properly through this layered stack of wrappers and the most insightful thing you will see in terms of error reports will be a status-500 page from your webserver.


did you try to setup system variables as following:

/etc/environment
BUNDLE_GEMFILE=path_to_the_file
RACK_ENV=production
RUBY_VERSION='ruby-1.9.2-p180'
GEM_PATH='$HOME/rvm/...'

you can adjust any rubygems (gem environment) and rvm variables on the system level, not only user specific.


Ok rvm-shell seems to be the answer to the problem since it is an executable, not a shell function. Important thing it so tpecify GEM_HOME and GEM_PATH yourself though!

        "bin-path" => "/usr/local/rvm/gems/ruby-1.9.2-p180/bin/bundle2 /home/user/websites/behandelaar-web/current/web-root/config.ru",
        "bin-environment" => (
            "BUNDLE_GEMFILE" => "/home/user/websites/behandelaar-web/current/Gemfile",
            "RACK_ENV" => "production",
            "GEM_HOME" =>"/usr/local/rvm/gems/ruby-1.9.2-p180",
            "GEM_PATH" =>"/usr/local/rvm/gems/ruby-1.9.2-p180:/usr/local/rvm/gems/ruby-1.9.2-p180@global",
         ),          ),

The "bundle2" script is a mix between bundle exec and rackup, with added bonus of decent error reports (since fcgi has no STDERR and no STDOUT and alot of elements in the chain swallow all possible exceptions resulting in crashes).

#!/usr/local/rvm/rubies/ruby-1.9.2-p180/bin/ruby
#
# Generated Manually!
begin
  require 'rubygems'

  version = ">= 0"

  if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
    version = $1
    ARGV.shift
  end

  gem 'bundler', version

  load Gem.bin_path('bundler', 'bundle', version)
  load Gem.bin_path('rack', 'rackup', version)

rescue Exception => e
  File.open("/tmp/fcgrun-crash.log", "w") do | f |
    f.puts(ENV.inspect)
    f.puts(e.class.to_s)
    f.puts(e.message)
    f.puts(e.backtrace.join("\n"))
  end
  # and raise further
  raise e
end
0

精彩评论

暂无评论...
验证码 换一张
取 消