部署 Nginx + Passenger 部署 Rails, 希望能够直接访问 Rails 的 public 目录的静态文件,但是 Nginx 总是返回 404

kakaxi2 · August 09, 2015 · Last by kakaxi2 replied at August 10, 2015 · 4231 hits

是这样的,我按照配置,给出了如下的 nginx 的配置文件,

events {
    worker_connections  1024;
}

http {
    passenger_root /home/sdy/.rvm/gems/ruby-2.0.0-p643@rails4/gems/passenger-5.0.15;
    passenger_ruby /home/sdy/.rvm/gems/ruby-2.0.0-p643@rails4/wrappers/ruby;

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

    #access_log  logs/access.log  main;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 8800;
        server_name 127.0.0.1;
        root /home/sdy/rails_project/saler/public;
        passenger_intercept_errors on;
        passenger_friendly_error_pages off;
        passenger_enabled on;
        error_page 404  /404.html;
     }
}

目的是:

  1. 希望能够直接访问 rails 的静态资源,包括 html,css,js 等。到目前为止,我的理解是如果在 rails 项目的 public 目录能够访问到的,nginx 应该能够直接返回,但是 nginx 启动后提示 404 找不到页面
  2. 希望能够使用 public 目录当中定制的 404 页面,访问http://127.0.0.1/abc.html

查看 nginx 的日志显示为:

2015/08/09 18:15:02 [error] 12945#0: *3 open() "/home/sdy/rails_project/saler/public/abc.html" failed (2: No such file or directory), client: 127.0.0.1, server: 127.0.0.1, request: "GET /abc.html HTTP/1.1", host: "127.0.0.1:8800" 

2015/08/09 18:15:02 [error] 12945#0: *3 open() "/home/sdy/rails_project/saler/public/404.html" failed (2: No such file or directory), client: 127.0.0.1, server: 127.0.0.1, request: "GET /abc.html HTTP/1.1", host: "127.0.0.1:8800"

我的 public 目录当中是存在 abc.html 以及 404.html 的,可以判断 nginx 访问 public 目录没有找到 abc.html,随后按照设置在该目录寻找 404.html 但是都没有找到

疑问是:

  1. passenger 在 nginx 当中是怎么配置使得访问静态资源直接有 nginx 来返回,动态资源有 rails 来返回的。
  2. 上述的访问http://127.0.0.1/abc.htmldevelopment环境当中是可以,但是production环境当中就不行,为何在?
  3. public 目录不是说是 rails 路由一开始就能直接看到的么,然后如果在 public 目录找不到文件才去走 routes.rb,但是 production 和 nginx 都访问不到 abc.html.

附注:rails 使用的是 4.2,我猜是不是和 asset 之类的有关,但是 asset 这不是我不是很懂。

可以试试用 rails server -e production , 在本地运行 Production, 直接在 log 里面有没有什么报错。

  1. 不用单独配置,nginx 会 serve 资源(root 下,如果有访问权限的话)。
  2. passenger 也需要 rails_env 或 rack_env。

ref. https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#PassengerAppEnv

请教“default_type application/octet-stream;“的作用?

#1 楼 @springwq 请求 localhost/abc.html application.log 返回

INFO -- : Started GET "/abc.html" for 127.0.0.1 at 2015-08-09 21:31:25 +0800
ActionController::RoutingError (No route matches [GET] "/abc.html"):
  actionpack (4.2.3) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  actionpack (4.2.3) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.2.3) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.2.3) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.3) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.3) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.3) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.3) lib/rails/rack/logger.rb:20:in `call'
  actionpack (4.2.3) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.4) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.4) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.3) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  rack (1.6.4) lib/rack/sendfile.rb:113:in `call'
  railties (4.2.3) lib/rails/engine.rb:518:in `call'
  railties (4.2.3) lib/rails/application.rb:165:in `call'
  rack (1.6.4) lib/rack/lock.rb:17:in `call'
  rack (1.6.4) lib/rack/content_length.rb:15:in `call'
  rack (1.6.4) lib/rack/handler/webrick.rb:88:in `service'
  /home/sdy/.rvm/rubies/ruby-2.0.0-p643/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service'
  /home/sdy/.rvm/rubies/ruby-2.0.0-p643/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run'
  /home/sdy/.rvm/rubies/ruby-2.0.0-p643/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread'

看这行错误,路由错误。

ActionController::RoutingError (No route matches [GET] "/abc.html"):

routes.rb 里面加一行

get '/abc',  :to => redirect('/abc.html')

#4 楼 @springwq public 目录访问需要加/public 么

#2 楼 @appell 作用我也不是很了解,另 public 的目录确实访问不到

ps aux| grep nginx #查看你的nginx是以什么用户启动的
sudo su - nginxuser #把nginxuser换成你的nginx运行用户看看
file /home/sdy/rails_project/saler/public/abc.html #看看此用户有没有权限访问此文件

另外,最好在 server 里面再包含一个 location 指令。

server {
    listen 8800;
    server_name 127.0.0.1;
    root /home/sdy/rails_project/saler/public;
    passenger_intercept_errors on;
    passenger_friendly_error_pages off;
    passenger_enabled on;
    error_page 404  /404.html;

    location / {
        root /home/sdy/rails_project/saler/public;
 }

一般来说,会有多个 location,配置成静态资源存在则直接返回文件,不存在则反向代理 rails 程序处理

#8 楼 @cxh116 谢谢你的回帖,确认是你说的额用户问题,修改 nginxuser,问题得到修正。 总结,由于在测试访问 abc.html 的过程中,对 nginx 的相应 403 forbidden 没有理解清楚,也咩有仔细查看 nginx error 日志,里面记载了 denied 相关消息。linux 下访问权限的问题一定要谨记。

You need to Sign in before reply, if you don't have an account, please Sign up first.