Nginx 다중 위치 문제


14

현재 하나의 저장소에서 3 개의 응용 프로그램을 3 개의 저장소로 분리하려고하지만 URL 구조를 유지하므로 기본적으로 동일한 도메인 아래의 다른 위치를 다른 응용 프로그램에서 제공해야합니다.

내가 고투하고있는 것은 앱 중 하나가 존재하지 않는 URL에 대한 폴백이어야한다는 것입니다. 따라서 첫 번째 URL이 일치하지 않고 두 번째 URL이 일치하지 않으면 세 번째가 요청을 처리해야합니다

내가 가진 구조는 다음과 같습니다.

/ etc / nginx / sites-enabled / main_site (여기서는 server_name 및 logs 제외)에서 include /etc/nginx/subsites-enabled/*각 앱마다 하나씩 3 개의 구성 파일이 있습니다.

3 개의 구성 파일 각각에는 위치 블록이 있습니다.

정규식에서 부정적인 미리보기를 시도했지만 (기본적으로 다른 앱이 처리하는 URL을 하드 코딩하려고 시도했지만) 실패했습니다.

요약하자면 다음과 같습니다.

/ 및 / community는 /etc/nginx/subsites-enabled/example.org/home (몇 가지 펄 스크립트)을 통해 제공되어야합니다.

/ news는 /etc/nginx/subsites-enabled/example.org/news(wordpress)에서 제공해야합니다.

그 밖의 모든 것은 /etc/nginx/subsites-enabled/example.org/app (케이크 앱)에서 제공해야합니다.

펄 비트는 잘 작동합니다. 내가 겪고있는 문제는 앱이 뉴스를 인수한다는 것입니다 (아마도. *와 일치하기 때문에). 다양한 옵션을 시도했지만 (2 일 동안이 일을했습니다) 모든 문제를 해결하지 못했습니다 (때로는 정적 자산은 작동하지 않습니다).

내 구성은 다음과 같습니다

/etc/nginx/sites-enabled/example.org :

server {
    listen   80;
    server_name example.org;
    error_log /var/log/nginx/example.org.log;

    include /etc/nginx/subsites-enabled/example.org/*;
}

/etc/nginx/subsites-enabled/example.org/home :

location = / {
  rewrite ^.*$ /index.pl last;
}

location ~* /community(.*) {
  rewrite ^.*$ /index.pl last;
}

location ~ \.pl {
  root   /var/www/vhosts/home;
  access_log /var/log/nginx/home/access.log;
  error_log /var/log/nginx/home/error.log;

  include /etc/nginx/fastcgi_params;
  fastcgi_index index.pl;
  fastcgi_param SCRIPT_FILENAME /var/www/vhosts/home$fastcgi_script_name;
  fastcgi_pass  unix:/var/run/fcgiwrap.socket;
}

/ etc / ngins / subsites-enabled / news

location /news {
  access_log /var/log/nginx/news/access.log;
  error_log /var/log/nginx/news/error.log debug;

  error_page 404 = /news/index.php;

  root /var/www/vhosts/news;

  index index.php;

  if (!-e $request_filename) {
      rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news$fastcgi_script_name;
  }
}

/ etc / nginx / subsites-enabled / app :

location ~ .* {
  access_log /var/log/nginx/app/access.log;
  error_log /var/log/nginx/app/error.log;

  rewrite_log on;

  index index.php;
  root /var/www/vhosts/app/app/webroot;

  if (-f $request_filename) {
    expires 30d;
    break;
  }

  if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot$fastcgi_script_name;
  }
}

a) 존재하지 않는 URL에 대한 경로를 포함하여 다양한 경로 재 지정의 예와 함께 구성을 게시하십시오. b) 기본 앱에 매핑 되는 명명 된 위치 블록 ( 접두사 사용)과 함께 try_files 를 사용하십시오 @. 404를 명명 된 위치에 매핑하는 error_page를 설정할 수도 있습니다.
cyberx86

@ cyberx86 나는 자세한 내용과 내 설정 추가
안드레이 Serdeliuc을

a) 정규식 일치는 기존 문자열보다 우선하므로 뉴스 블록 대신 앱 블록이 일치합니다 location ^~ /news. b) 앱 블록의 경우 location /(와 동일하지 location = /않지만 일치하지 않는 모든 항목과 일치해야 함) c) 경우에 따라 (특히 정규식) 순서가 중요합니다-3을 결합 할 수 있습니다 블록을 올바른 순서로 하나의 파일로 묶습니다. 또한 대신 try_files를 사용하십시오 !-e. 마지막으로 wiki.nginx.org/HttpCoreModule#location을 참조하십시오 .
cyberx86

나는 그것들을 단일 파일로 결합하는 것을 포함하여 그것들의 거의 모든 변형을 시도했지만 (별도로 배포 될 때 분리해야하지만) 작동하지 않습니다. 뉴스가 앱에서 처리됩니다.
Andrei Serdeliuc

글쎄, 나는 처음에 예상했던 것보다 조금 까다로워서 그것을 풀었다. 퍼즐 주셔서 감사합니다.
cyberx86

답변:


45

설정에 몇 가지 문제가 있습니다. 두 가지 관련 요소는 다음과 같습니다.

  1. 위치 블록 내의 경로에는 여전히 일치하는 경로가 포함됩니다.
  2. '마지막'으로 다시 쓰면 사용 가능한 모든 위치를 검색하여 일치합니다 (현재 위치 블록에서 벗어남).

예를 들어 URL example.org/news/test.htm을 사용하십시오.

  • location /news블록을 일치합니다
  • 사용 된 경로 /news/test.htm는 위치 블록에 있기 때문에 변경되지 않습니다.
  • document_root에 경로를 추가하면 다음과 같은 이점이 있습니다. /var/www/vhosts/news/news/test.htm
  • 귀하의 if (!-e $request_filename)진술서는 존재하지 않는 파일을 캡처해야합니다
  • 당신은 경로를 다시 작성 /index.php
  • last프로세스를 사용 하고 있기 때문에 시작합니다 (위치 블록에서 벗어나기)
  • /index.php에 의해 캡처됩니다 location /app block.

루트 지시문과 함께 위에서 언급 한 문제는 앱 위치 블록으로 이동하면 더욱 복잡해집니다. 경로에서 '뉴스'를 제거 할 수있는 '뉴스'블록과 달리 (다시 추가되므로) '웹 루트'로 끝나는 앱 경로에 대해서는이 작업을 수행 할 수 없습니다.

해결책은 alias지침에 있습니다. document_root는 변경하지 않지만 요청을 처리하는 데 사용되는 파일 경로는 변경합니다. 불행히도 rewritetry_files의외로 조금 행동하는 경향이 alias있습니다.

PHP가 아닌 HTML과 Perl 블록 만있는 간단한 예제부터 시작하지만 자신과 일치하는 폴더 구조 (Nginx 1.0.12, CentOS 6에서 테스트)로 시작하겠습니다.

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;

        [fastcgi_stuff...]
    }


    location ^~ /news {
        alias /var/www/vhosts/news;
        index index.htm;

        try_files $uri $uri/ /news/index.htm;
    }

    location ^~ /app {
        alias /var/www/vhosts/app/app/webroot;
        index index.htm;

        try_files $uri $uri/ /app/index.htm;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}
  • location = / -루트 경로와 만 일치합니다
  • location ^~ /community -/ community로 시작하는 모든 경로와 일치합니다
  • location ~ \.pl -.pl이 포함 된 모든 파일과 일치
  • location ^~ /news -/ news로 시작하는 모든 경로와 일치합니다
  • location ^~ /app -/ app로 시작하는 모든 경로와 일치합니다
  • location / -위에 일치하지 않는 모든 경로와 일치합니다

^~- 를 제거 할 수 있어야 하지만 일치하는 것이 발견되면 검색을 중지하므로 약간의 성능 향상을 제공 할 수 있습니다.

PHP 블록을 다시 추가하는 것은 간단한 일이지만 불행히도 약간의 어려움이 있습니다- try_files(그리고 다시 쓰면) 원하는 경로를 중첩 된 위치 블록으로 전달하지 않으며 alias확장 기능 만있을 때 사용 합니다 위치 블록에 지정된 작동하지 않습니다.

하나의 해결책은 별명 지시문과 함께 캡처를 수행하는 별도의 위치 블록을 사용하는 것입니다. 매우 우아하지는 않지만 알 수있는 한 작동합니다 (다시 Nginx 1.0.12, CentOS 6에서 테스트 됨) 물론 CakePHP, Wordpress 및 Perl을 설정하지 않았습니다. 각 폴더에 몇 개의 PHP 및 HTML 파일을 사용했습니다)

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;
        access_log /var/log/nginx/home.access.log;
        error_log /var/log/nginx/home.error.log;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.pl;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
    }

    location /news {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/news;
        index index.php;
        try_files $uri $uri/ /news/index.php;
    }

    location ~* ^/news/(.*\.php)$ {
        access_log /var/log/nginx/news.php.access.log;
        error_log /var/log/nginx/news.php.error.log notice;
        alias /var/www/vhosts/news/$1;
        try_files "" /news/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location /app {
        alias /var/www/vhosts/app/app/webroot;
        access_log /var/log/nginx/app.access.log;
        error_log /var/log/nginx/app.error.log notice;
        index index.php;
        try_files $uri $uri/ /app/index.php;
    }

    location ~* ^/app/(.*\.php)$ {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/app/app/webroot/$1;
        try_files "" /app/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}

위의 구성은 위의 간단한 구성을 사용하여 두 가지 변경을 수행합니다.

  • 두 개의 위치 블록을 추가하십시오.
    • location ~* ^/news/(.*\.php)$ -/ news /로 시작하는 경로를 사용하여 .php로 끝나는 모든 파일과 일치합니다.
    • location ~* ^/app/(.*\.php)$ -.php로 끝나는 모든 파일을 / app /로 시작하는 경로와 일치시킵니다.
  • ^~일치하는 제거 -추가 된 두 개의 위치 블록이 경로와 일치 할 수 있어야합니다 (그렇지 않으면 / news 또는 / app 블록에서 일치가 중지됨).

위치 일치 순서는 여기에서 매우 중요합니다.

  • 정확히 일치하는 첫 번째 (을 사용하여 =)
  • ^~두 번째 와 일치
  • 일치하는 정규식 블록
  • 기존 문자열-일치하는 정규식을 찾을 수없는 경우에만

일치하는 정규 표현식은 직선 문자열을 대체합니다!

중요한 점은 캡처가 별칭과 함께 사용될 때 주요 폴더뿐만 아니라 전체 URL이 대체된다는 것입니다. 불행히도, 이것은 $fastcgi_script_name비어 있음을 의미 하므로 $1대신 위에 사용했습니다.

몇 가지 사항을 변경해야하지만 기본 전제는 작동해야합니다. 필요에 따라 블록을 여러 파일로 분리 할 수 ​​있어야합니다. 순서는 구성에 영향을 미치지 않아야합니다.


2
야, 내가 너에게 100 번 투표 할 수 있으면 좋겠다. 넌 정말 대단해 감사!
Andrei Serdeliuc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.