5

好的,我要坦白——我仍然运行大量的 FCGI 设置(只是配置了很多服务器)。我正在尝试使其适应 rvm。在 fcgi 设置中,我可以指定要执行的命令行命令以运行我的应用程序(Sinatra、Rack、Bundler 等),这就是我在没有 rvm 的情况下会做的事情

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

假设我的机架文件只是 config.ru。现在,在我的 Mac 上这可以工作:

"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"
),

但不在服务器上。当调度程序启动时,它们会得到一个精简的环境,其中 RVM shell 诡计不再起作用。我想我应该使用 wrapper 选项来制作某种包装器,但我真的不明白这将如何缓解我的问题以及使用哪些参数。有没有人在没有加载 RVM shell 环境的情况下执行特定的 ruby​​ 和 gem 二进制文件的经验?

PS 为了防止偏离主题的答案,不,谢谢,我不需要 Ruby 1.8.7、Passenger 或 nginx。

4

4 回答 4

3

您应该能够使用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"
于 2011-07-20T21:25:27.523 回答
2

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.

于 2011-07-30T13:54:13.240 回答
0

您是否尝试如下设置系统变量:

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

您可以在系统级别调整任何 ruby​​gems(gem 环境)和 rvm 变量,而不仅仅是用户特定的。

于 2011-07-18T17:24:12.930 回答
0

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
于 2011-07-24T21:23:19.760 回答