Rails 3 - 生产模式中的开发错误

发布于 2024-10-22 01:40:46 字数 2725 浏览 4 评论 0 原文

我在生产服务器上使用 Rails、Passenger(均为 3.0.5)和 Nginx。据我所知,Rails 应该显示 public/404.htmlpublic/500.html 而不是诸如 ActiveRecord::RecordNotFound 或 < code>未知操作但这并没有发生。我尝试删除 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;
        }
    }
}

看来这个问题重复 这个 但是没有工作建议。

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

# 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

Im using Rails, Passenger (both are 3.0.5) and Nginx on my production server. As I heard, Rails should show public/404.html or public/500.html instead of development errors like ActiveRecord::RecordNotFound or Unknown action but that doesn't happen. I've tried to delete config.ru file and set rack_env or rails_env in nginx.conf but nothing helped.

Here is my 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;
        }
    }
}

It seems that this question duplicates this one but there are no working suggestions.

UPD: I have both development and production apps on same PC. In production Rails ignores config.consider_all_requests_local = false (in /config/environments/production.rb) due to local_request? method. So one of possible solutions is listed below (taken from 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

Or for Rails 3:

class ActionDispatch::Request
 def local?
   false
 end
end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

晨光如昨 2024-10-29 01:40:46

要在 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>

To get this working in Rails 3 you'll have to do the following:

First, create your 404 and 500 error pages. I put mine in app/views/errors/404.html.erb and app/views/errors/500.html.erb.

Second, add the following to 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

Finally, make your production.rb not consider all requests local:

config.consider_all_requests_local = false

P.S: Keep in mind that when a complete routing error happens - i.e when there is absolutely no route match, not just an ActiveRecord NotFound error, the public/404.html will get displayed, so it's good to have that in place. I usually just re-direct it to my errors_controller, which ensures that any 404 errors not caught by the latter mentioned exceptions are still properly redirected to ErrorsController.

<script type="text/javascript">
<!--
window.location = "<%= request.host_with_port %>/errors/404"
//-->
</script>
岁月无声 2024-10-29 01:40:46

仅在某些控制器中出现错误

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

To get errors only in certain controllers

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
遮云壑 2024-10-29 01:40:46

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

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

如果您的应用程序没有提供页面,并且 nginx 对静态页面不可见,那么它就无法提供您想要的页面。

Move your root declaration up to the "server" block so the server can use the Rails app defined error handling pages when it receives a 5XX, 4XX error.

Or add error_page directives to the location block where passenger is being used so the error handlers can resolve the public/5xx.html in the Rails app public directory when needed.

If your app is not serving up the page and nginx has no visibility to the static page then it can't serve the page you want.

叹倦 2024-10-29 01:40:46

在 apache Passenger 上我使用了 apache 配置选项
PassengerFriendlyErrorPages 关闭。

On apache passenger I used the apache configuration option
PassengerFriendlyErrorPages off.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文