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

kakaxi2 · 2015年08月09日 · 最后由 kakaxi2 回复于 2015年08月10日 · 4227 次阅读

是这样的,我按照配置,给出了如下的 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 下访问权限的问题一定要谨记。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号