Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 config.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.

like image 536
Julik Avatar asked Jul 05 '11 13:07

Julik


2 Answers

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"
like image 169
Jacob Avatar answered Sep 25 '22 19:09

Jacob


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.

like image 35
Julik Avatar answered Sep 21 '22 19:09

Julik