包含内容问题的nginx维护页面

时间:2011-05-12 20:46:16

标签: nginx maintenance

要在部署期间显示维护页面,我总是在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

6 个答案:

答案 0 :(得分:11)

对不起,Frank Farmer,但这不起作用。

什么有效但不那么整洁:

请求如何工作 - >

  1. 我使用规则#1

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

    此规则支持指定位置location @maintenance,并且/maintenance.htmlroot /home/shared/errors的公共重定向一切正常。

  2. 此页面包含图片some.jpg - 要接收此图片,浏览器会启动新请求,此新请求会再次触及规则#1

    所有这些都在初始问题中描述但

    如果我在Frank Farmer的回答中使用了一些if魔法,我可以将服务器指向请求的文件但是HTTP回答将是503并且浏览器(所有,除了Safari,在我的测试中)在调试控制台中抛出错误并且做显示图像但不处理相同情况下的CSS文件。

    这很关键。

  3. 我尝试使用location magic来解决这个问题 - 这意味着我必须:

    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;
      }
      
  5. 此解决方案在所有浏览器和shared/errors文件夹中的大量页面中都没有任何错误,例如。 maintenance.html,error.html,overload.html等

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

答案 1 :(得分:10)

我花了两个小时寻找这个问题的答案,最后找到了这篇文章。似乎它应该更常见。我的解决方案介于Frank's和Wile之间。正如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;
}

像魅力一样工作。 :)

答案 2 :(得分:4)

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;
    }
}

答案 3 :(得分: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;
        }
}

答案 4 :(得分: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目录中。

答案 5 :(得分:1)

我尝试了上述所有建议,遗憾的是他们没有按预期工作。对我有用的唯一解决方案如下:

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;
}

我知道,它会在正常情况下创建不必要/维护位置,但您可以想象另一个位置路径,您的用户永远不会猜到:)。