15

IfIsEvil以来、私はディレクティブのみを使用して構成をセットアップしようとしてきました。これによりtry_files、メンテナンス ファイルが存在する場合、例外なく任意の URI (つまり、php ページを含む) に対してメンテナンス ページが応答コード 503 と共に表示されます。

私の構成には 2 つの問題があります。

  1. PHP URI の場合、メンテナンス ページは表示されません。
  2. maintenance.html ファイルが存在する場合、応答コード 503 は返されません。

同様の質問[1][2]try_filesを見たことがありますが、(ディレクティブを使用するのではなく) のみを使用ifし、対応するファイルが存在する場合は無条件に応答コード 503 のメンテナンス ページを提供するソリューションはありません。そのような解決策は可能ですか?

以下は、現在動作していない conf ファイルです。上記のように動作するためにどこに行くべきか理解できないため、503 応答コードの設定は含まれていません。

worker_processes            1;

error_log                   /var/log/nginx/error.log debug;

events {
    worker_connections      1024;
}

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

    index                   index.php index.html index.htm;

    server {
        listen                  80;
        server_name             rpi;
        root                    /www;

        location / {
            try_files           /maintenance.html $uri $uri/ /index.php?$args;

            # pass the PHP scripts to FastCGI server
            location ~ \.php$ {
                try_files           $uri =404;
                fastcgi_pass        unix:/run/php-fpm/php-fpm.sock;
                fastcgi_index       index.php;
                include             fastcgi.conf;
            }
        }
    }
}

私の質問は、代わりに次のように表現することもできると思います:制御構造try_filesとして機能させることはできますか? if単独ではない場合、上記の目標を持って、他のディレクティブと組み合わせて、ifディレクティブを除いて、そのように機能することはできますか?

編集:以下はif、サーバーセクションに含めることで現在使用しているものを使用したソリューションです。

error_page              503 @maintenance;

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

location @maintenance {
        try_files       /maintenance.html =404;
}
4

1 に答える 1

10

とても良い質問です!しかし、正しい応答コードを設定する何らかのスクリプトを呼び出さない限り、それはまったく不可能です。

nginxのみを使用し、ifを使用しない実用的なソリューション

try_filesディレクティブは、最後のステートメントの内部リダイレクトのみを実行しています。indexしかし、それをディレクティブと組み合わせて、内部リダイレクトを強制することができます。

# This will be the HTML file to display for the 503 error.
error_page 503 /maintenance/maintenance.html;

# Let nginx know that this particular file is only for internal redirects.
location = /maintenance/maintenance.html {
  internal;
}

# Any request that starts with the maintenance folder is 503!
location ^~ /maintenance/ {
  return 503;
}

# Instead of checking if a file exists and directly delivering it we check
# if a certain directory exists and trigger our index directive which will
# perform an internal redirect for us.
location / {
  expires epoch;
  try_files /maintenance/ $uri $uri/ /index.php?$args;
}

この方法の欠点はありますか?

  • 同じ URL (検索エンジン) にとどまるのではなく、ディレクトリへの実際の 301 リダイレクト。
  • 301 リダイレクトのブラウザー キャッシュが問題になる可能性があるexpires epochため、ロケーション ブロックに を追加しました。

他の解決策?

nginx 設定ファイル経由

HTML ファイルを作成する代わりに、nginx 構成ファイルを作成し、プロセスを再ロードするだけではどうですか?

  • はるかに優れたパフォーマンス!
  • より分かりやすく!
  • 副作用なし!

nginx の構成は次のようになります (これifはまったく悪いことではないことに注意してください)。

error_page 503 /maintenance.html;

location / {
  include maintenance.conf;
  if ($maintenance = 1) {
    return 503;
  }
  try_files $uri $uri/ /index.php?$args;
}

maintenance.confファイルの内容:

set $maintenance 0;

そして、(シェルで) メンテナンス モードを有効にしたい場合:

echo set $maintenance 1;> maintenance.conf && service nginx reload

シェル フレンド向けのより高度なファイルの末尾にある次のブロックを置き換えることにより 、たとえば私の LSB 準拠の init スクリプトをこれで拡張することもできます。

*)
  echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop}" >&2
  exit 1
;;

次のブロックを使用します。

maintenance)
  echo "set $maintenance 1;" > /etc/nginx/maintenance.conf && service nginx reload;
;;

production)
  echo "set $maintenance 0;" > /etc/nginx/maintenance.conf && service nginx reload;
;;

*)
  echo "Usage: ${NAME} {force-reload|reload|restart|start|status|stop|maintenance|production}" >&2
  exit 1
;;

そして、次のコマンド (オートコンプリートを含む) を実行するだけで、メンテナンス モードに入ることができます。

service nginx maintenance

または、次のようにして本番環境に戻ります。

service nginx production

スクリプト/PHPファイルで

魔法のように機能するもう 1 つの非常に簡単な方法は、それを処理する PHP ファイルを使用することです。

location / {
    try_files /maintenance.php $uri $uri/ /index.php?$args;
}

PHP ファイルは HTML ファイルとまったく同じように見えますが、最初に以下を追加するだけです (PHP 5.4+ を想定):

<?php http_response_code(503) ?><!doctype html>
<html>
<head>
<!-- ... more html ... -->
于 2014-02-11T16:35:56.860 に答える