2011-05-12 78 views
16

部署过程中表现出的维护页面我一直使用下一个配置在nginx的:nginx的维护页面

if (-f /home/shared/system/maintenance.html) { 
    return 503; 
} 

error_page 503 @maintenance; 

location @maintenance { 
    root /home/shared/errors; 
    rewrite ^(.*)$ /maintenance.html break; 
} 

而且一切正常,直到我需要添加静态内容维护页面(图片,样式表等)

没有在error.log中有这样的记录静态内容的工作:

2011/05/05 02:47:20 [notice] 13760#0: *6 "^(.*)$" matches "/some.jpg", client: x.x.x.x, server: server.com, request: "GET /some.jpg HTTP/1.1", host: "server.com" 
2011/05/05 02:47:20 [notice] 13760#0: *6 rewritten data: "/maintenance.html", args: "", client: x.x.x.x, server: server.com, request: "GET /some.jpg 2 HTTP/1.1", host: "server.com" 

这是合乎逻辑 - 如果我做重写一切maintenance.html这意味着静态续恩不排除。

但我不能找到任何合适的解决方案,使重定向到每一个文件,除了其在root /home/shared/errors文件夹物理存在的。

PS。 /home/shared/errors不常见的项目文件夹共享任何资源 - 这是完全不同的文件夹中(即使没有任何符号链接/current为项目

回答

10

。对不起,弗兰克农民,但这不起作用

什么工作,但不是那么整齐。

个如何请求工作 - >

  1. 我使用规则#1

    if (-f /home/shared/system/maintenance.html) { 
        return 503; 
    } 
    

    这个规则有一个支持命名的位置location @maintenance的和共同的重定向到/maintenance.htmlroot /home/shared/errors一切正常。

  2. 此页面包含与图像some.jpg - 获得这个图像浏览器启动新的要求和新的要求再次命中规则#1

    这一切在最初的问题进行描述,但

    ,如果我使用了一些if魔像弗兰克农民答案我可以指向服务器请求文件,但HTTP答案将是503和浏览器(所有的,除了Safari浏览器,在我的测试)抛出的错误在调试控制台和不显示图像,但并不处理CSS-文件中同样的情况。

    这是至关重要的。

  3. 我试图解决这个使用魔法的位置为我的新内容的请求 - 这意味着我必须:

    1. 做内容的请求不return 503并跳过所有命名的位置。

    2. 做改变root /home/shared/errors因为保养内容仍然存在。

  4. 最后,我有一个解决方案:

    1. 创建maintenance-static文件夹中的所有静态内容,并更改我的maintenance.html文件和维护静态样式表的路径

    2. 下次使用这些规则(我相信它们是自描述性的)在最初的问题中取代单个if (-f /home/shared/system/maintenance.html)

      set $can503 0; 
      if (-f /home/shared/system/maintenance.html) { 
          set $can503 1; 
      } 
      if ($uri ~* /maintenance-static/) { 
          set $can503 0; 
      } 
      location /maintenance-static/ { 
          root /home/shared/errors; 
      } 
      if ($can503 = 1) { 
          return 503; 
      } 
      

此解决方案,而不在所有浏览器的任何错误,并为众多的shared/errors文件夹页,为前。 maintenance.html,error.html,overload.html等

这个解决方案不是很清楚 - 可能你可以告诉我如何使它更整洁,但记住我们正在处理单独的请求(和单独的nginx进程对于高负载情况下的每个文件/请求等),对于初始html及其内容,我们不能使用503重定向所有文件的相同规则。

3
location @maintenance { 
    root /home/shared/errors; 
    rewrite (some\.jpg|some2\.gif)$ /$1 break; 
    rewrite ^(.*)$ /maintenance.html break; 
} 

这可能不枚举白名单文件的工作:

location @maintenance { 
    root /home/shared/errors; 
    if (!-f $request_filename) { 
     rewrite ^(.*)$ /maintenance.html break; 
    } 
} 
+0

太棒了!谢谢,但有没有解决方案不列出每个文件?这不是问题 - 我有很少的文件,但这将是更好的解决方案... – 2011-05-14 05:42:45

+0

@wile看到我的编辑。 – 2011-05-14 19:49:46

+0

@FrankFarmer有趣的是,你的回答会让我大饱口福,因为我最终想出了完全相同的代码(参见我的[博客文章])(http://www.relativkreativ.at/articles/graceful-error -pages-with-nginx)如果你感兴趣的话)。 – 2014-06-22 16:04:22

9

我花了两个小时寻找这个问题的答案,并最终找到了这篇文章。似乎它应该更常见。我的解决方案落在弗兰克和威尔之间的某处。正如Wile所述,某些浏览器(例如Chrome)会选择不呈现任何返回503的文件的CSS/JS,即使它完全正确地提取它们。

但有一个修复程序比Wile做得少。只需返回200!

我的完整的解决方案如下:

error_page 503 @maintenance; 

location @maintenance { 
    root /path_to_static_root; 
    if (!-f $request_filename) { 
     rewrite ^(.*)$ /rest_of_path/maintenance.html break; 
    } 
    return 200; 
} 

工作就像一个魅力。 :)

+0

谢谢!我也会试试这个,看起来还不错 – 2012-01-10 11:47:11

+0

你知道如果nginx处理错误的方式有任何改变吗?而不是返回200它现在返回502.它只有502如果文件实际存在(这不包括“maintenance.html”请求) – crockpotveggies 2012-02-18 02:51:45

+0

作出更新,当充当反向代理时确实存在一个全新的问题。这里的问题http://stackoverflow.com/questions/9338130/nginx-502-when-issuing-error-page-content – crockpotveggies 2012-02-18 06:06:07

1
server { 
    listen 80; 
    server_name myserv.trunk; 
    autoindex off; 
    access_log /var/log/nginx/sitename-access.log; 

    location ^~ /static/ { 
     root /home/dev/myserv-site/; 
    } 

    location ~ /(?P<language>en)?/? { 
     uwsgi_pass unix:///tmp/uwsgi.sock; 
     include uwsgi_params; 
     error_page 502 @fallback; 
     error_page 503 @maintenance; 
     if (-f /home/dev/myserv-site/maintenance.active) { 
      return 503; 
     } 
    } 

    location @fallback { 
     root /home/dev/myserv-site/; 
     if ($language) { 
      rewrite ^(?!\/static\/)(.*)$ /static/html/502.$language.html break; 
     } 
     rewrite ^(?!\/static\/)(.*)$ /static/html/502.zh.html break; 
    } 

    location @maintenance { 
     root /home/dev/myserv-site/; 
     if ($language) { 
      rewrite ^(?!\/static\/)(.*)$ /static/html/503.$language.html; 
     } 
     rewrite ^(?!\/static\/)(.*)$ /static/html/503.zh.html break; 
    } 
} 

以下是可翻译的维护(503)或502错误页面屏幕的示例。 如果用户转到http://site.com/en/英文页面将会显示(当存在maintenance.active文件时)。 static dir位于myserv-site目录内。

2

使用这种解决方案只有一个单一的if语句,并且也更易于阅读和理解:

upstream unicorn { 
     server unix:/path/to/unicorn.sock; 
} 

server { 
     listen 3000 default deferred; 

     proxy_read_timeout 3600; 
     client_max_body_size 4G; 
     set_real_ip_from 0.0.0.0/0; 

     root /path/to/current/public; 
     try_files $uri/index.html $uri.html $uri @unicorn; 

     error_page 404 /404.html; 
     error_page 500 502 504 /500.html; 
     error_page 503 /system/maintenance.html; 

     location /404.html { 
       internal; 
     } 

     location /500.html { 
       internal; 
     } 

     location @unicorn { 
       if (-f $document_root/system/maintenance.html) { 
         return 503; 
       } 

       proxy_set_header Host $http_host; 
       proxy_set_header X-Real-IP $remote_addr; 
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
       proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; 
       proxy_redirect off; 
       proxy_pass http://unicorn; 
     } 
} 
+0

什么是'内部'?以及这如何处理维护页面上的静态内容?在这里看不到解决方案 – 2012-05-11 12:40:07

+0

'internal'防止直接访问位置。有关详细信息,请参阅http://wiki.nginx.org/HttpCoreModule#internal – unhollow 2012-05-12 19:57:57

+0

静态资产已正确传递,因为它们甚至不会输入“@ unicorn”位置。它们由'try_files'处理。 – unhollow 2012-05-12 20:01:00

0

我试过上述建议和不幸预期他们不工作。这只是对我的作品的唯一的解决办法是:

location/{ 
    if (-f /path/to/file/indicating/maintenance/mode) { 
     rewrite ^(.+)$ /maintenance/$1; 
    } 

    #... the rest of the "normal" logic 
} 

location /maintenance { 
    root /path/where/your/maintenance/root/is; 
    rewrite ^/maintenance/(.*)$ /$1 break; 
    try_files /$uri /index.html =404; 
    return 200; 
} 

我知道,它会在正常条件下,不需要/维护位置,但你能想象另一个位置路径,你的用户永远猜不到:)。