【问题标题】:Rails 3 - development errors in production modeRails 3 - 生产模式下的开发错误
【发布时间】:2011-07-16 20:41:27
【问题描述】:

我在生产服务器上使用 Rails、Passenger(都是 3.0.5)和 Nginx。正如我所听到的,Rails 应该显示public/404.htmlpublic/500.html 而不是像ActiveRecord::RecordNotFoundUnknown action 这样的开发错误,但这不会发生。我试图删除 config.ru 文件并在 nginx.conf 中设置 rack_env 或 rails_env 但没有任何帮助。

这是我的 nginx.conf:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    passenger_root /home/makk/.rvm/gems/ruby-1.9.2-p0/gems/passenger-3.0.5;
    passenger_ruby /home/makk/.rvm/bin/passenger_ruby;
    #passenger_ruby /home/makk/.rvm/wrappers/ruby-1.9.2-p0/ruby;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   /home/makk/projects/1server/deploy/current/public;
            index  index.html index.htm;
            passenger_enabled on;
            rack_env production;

            recursive_error_pages on;

            if (-f /home/makk/projects/1server/maintenance.html) {
              return 503;
            }

            error_page 404 /404.html;
            error_page 500 502 504 /500.html;
            error_page 503 @503;
        }

        location @503 {
            error_page 405 = /maintenance.html;

            # Serve static assets if found.
              if (-f $request_filename) {
              break;
            }
            rewrite ^(.*)$ /maintenance.html break;
        }

        location ~ ^(\/phpmyadmin\/)(.*)$ {
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_split_path_info         ^(\/phpmyadmin\/)(.*)$;
        fastcgi_param   SCRIPT_FILENAME /usr/share/phpmyadmin/$fastcgi_path_info;
        include         fastcgi_params;
        }
    }
}

这个问题似乎与this one 重复,但没有可行的建议。

UPD:我在同一台 PC 上同时拥有开发和生产应用程序。在生产中,由于 local_request? 方法,Rails 会忽略 config.consider_all_requests_local = false(在 /config/environments/production.rb 中)。所以下面列出了一种可能的解决方案(取自here):

# config/initializers/local_request_override.rb
module CustomRescue
  def local_request?
    return false if Rails.env.production? || Rails.env.staging?
    super
  end
end

ActionController::Base.class_eval do
  include CustomRescue
end

或者对于 Rails 3:

class ActionDispatch::Request
 def local?
   false
 end
end

【问题讨论】:

    标签: ruby-on-rails passenger production


    【解决方案1】:

    将您的 root 声明移至“服务器”块,以便服务器在收到 5XX、4XX 错误时可以使用 Rails 应用定义的错误处理页面。

    或者将error_page 指令添加到正在使用乘客的位置块,以便错误处理程序可以在需要时解析Rails 应用程序公共目录中的public/5xx.html

    如果您的应用未提供页面并且 nginx 无法查看静态页面,则它无法提供您想要的页面。

    【讨论】:

    • 看起来几乎是我的问题,但没有帮助。请查看更新的 nginx.conf。
    • 你的rails“public”目录中有500.html和404.html吗?
    【解决方案2】:

    在 apache 乘客上,我使用了 apache 配置选项 PassengerFriendlyErrorPages 关闭。

    【讨论】:

      【解决方案3】:

      仅在某些控制器中获取错误

      class AdminController < ApplicationController
        rescue_from Exception, :with => :render_simple_error if Rails.env.production?
        def render_simple_error(e)
          render :text => "#{e.message} -- #{e.class}<br/>#{e.backtrace.join("<br/>")}"
        end
      end
      

      【讨论】:

        【解决方案4】:

        要使其在 Rails 3 中工作,您必须执行以下操作:

        首先,创建 404 和 500 错误页面。我把我的放在app/views/errors/404.html.erbapp/views/errors/500.html.erb

        其次,在application_controller.rb中添加以下内容:

        unless Rails.application.config.consider_all_requests_local
          rescue_from Exception, :with => :render_error
          rescue_from ActiveRecord::RecordNotFound, :with => :render_not_found
          rescue_from AbstractController::ActionNotFound, :with => :render_not_found
          rescue_from ActionController::RoutingError, :with => :render_not_found
          rescue_from ActionController::UnknownController, :with => :render_not_found
          rescue_from ActionController::UnknownAction, :with => :render_not_found
        end
        
        def render_error exception
          Rails.logger.error(exception)
          render :template => "/errors/500.haml", :status => 500
        end
        
        def render_not_found exception
          Rails.logger.error(exception)
          render :template => "/errors/404.haml", :status => 404
        end
        

        最后,让您的 production.rb 不考虑所有本地请求:

        config.consider_all_requests_local = false
        

        PS:请记住,当发生完整的路由错误时 - 即当绝对没有路由匹配时,不仅仅是 ActiveRecord NotFound 错误,public/404.html 将被显示,所以最好有它.我通常只是将它重定向到我的errors_controller,这样可以确保没有被后面提到的异常捕获的任何404错误仍然正确地重定向到ErrorsController。

        <script type="text/javascript">
        <!--
        window.location = "<%= request.host_with_port %>/errors/404"
        //-->
        </script>
        

        【讨论】:

        • 如果您希望 Rails 应用程序处理它并提供页面,这是一种方法。如果您希望 nginx 处理它,请编辑您的块指令。两者都可以工作,只是取决于你想在哪里处理这些类型的错误。
        • 谢谢。我见过类似的here。但这不是很接近我的问题。我想避免任何显示开发错误的可能性。例如,另一种方法是覆盖 render_exception 方法。 Brandon 已经提出了更原生的解决方案。
        • 如果conside_all_requests_local 为false,则不会出现开发错误。用户只会得到 500 或 404 错误页面,但没有堆栈跟踪或内部错误消息。
        • 我在 production.rb 中有 config.consider_all_requests_local = false 但这也不起作用。需要说我检查了当前环境值(通过 runnig render :text =&gt; Rails.env.inspect),它被正确设置为“生产”。
        • 哪部分不起作用?在浏览器中显示堆栈跟踪或重定向到 500/404 错误页面?你得到了什么结果?
        猜你喜欢
        • 1970-01-01
        • 2012-07-21
        • 2019-11-26
        • 1970-01-01
        • 1970-01-01
        • 2014-01-11
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多