Ошибки конфигурирования nginx (или как правильно писать рерайты)

    Привет, хабралюди!

    По долгу службы приходится работать с веб-разработчиками, которые иногда пишут свои скрипты с рерайтами, которые им приходится адаптировать для nginx. Мне же приходится разгребать то, что там написано.

    Все желающие получить помощь по рерайтам могут задавать вопросы в комментариях, потом, наверно, из этого будет оформлен еще один пост.


    Ошибка номер 1, самая фатальная.


    Огромное количество раз упоминалась в рассылке. А именно — использование if на уровне location.
    Проблема в том, что if в location устроены не так, как мы представляем. Мы думаем, что приходит запрос, проверяется условие, если оно истинно — делаются поправки к конфигурации. А на деле все совсем иначе. При запуске nginx генерирует отдельные конфигурации location'ов для истинных и ложных условий в if. Несколько жутких примеров:
    location /
    {
        set $true1 1; set $true2 1;
        if($true1) { proxy_pass http://127.0.0.1:8080; }
        if($true2) { set $expr 123; }
    }

    Segmentation fault в рабочем процессе при попытке найти upstream для proxy_pass'a из первого if'a. А все дело в том, что он не унаследовался в location, где оба условия правильные.

    location /
    {
        set $true 1;
        try_files /maintenance.html $uri @fallback;
        if($true) { set $expr 123; }
    }
    location @fallback
    {
        proxy_pass 127.0.0.1:8080;
    }

    Полное игнорирование try_files. Просто его нет в location, который получился при истинности выражения.

    Под «set $expr 123;» можно понимать почти любое выражение в if, не задающее обработчика для запроса — все set, limit_rate и прочее.

    Однако, в одном случае использовать if в location все-таки можно — если сразу же после if'a мы уйдем из этого location. Сделать это можно двумя способами:
    1) Через rewrite… last;
    location /
    {
        try_files /maintenance.html $uri @fallback;
        if($cookie_uid = '1') { rewrite ^ /user/panel last; }
    }
    location /user
    {
        proxy_pass 127.0.0.1:8080;
    }

    2) Через return ...;
    location /
    <c
        try_files /maintenance.html $uri @fallback;
        if($cookie_bot = '1') { return 403; }
    }
    

    При этом мы можем через return как окончить обработку запроса, так и перейти в другой location, через error_page.
    Кстати, if на уровне server действует именно так, как мы ожидаем. При его использовании глобальных проблем возникать не должно.

    Ошибки номер 2, менее фатальные.


    После apache и его htaccess с RewriteRule и RewriteCond очень хочется запихнуть все в один location с if'ами, которые будут уводить обработку в другое место. Но это некрасиво, неправильно и неэффективно.
    Ошибка номер 2.1, об if (-e ...)

    Специально для того, чтобы красиво записывать такие рерайты придумана специальная директива — try_files. В самом простом варианте ее обычно записывают так:
    try_files $uri $uri/ @fallback
    что обозначает:
    1. Проверить, существует ли запрошенный файл. Если да — отдать его, если нет — идти далее.
    2. Проверить, существует ли директория с запрошенным именем. Если да — отдать ее, если нет — идти далее.
    3. Передать запрос на обработку в именованный location @fallback.

    Внимание! В @fallback при использовании fastcgi не стоит делать rewrite. Достаточно лишь написать fastcgi_parm с требуемым скриптом. Таким образом, конструкция вроде
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php

    Превращается в
    root /path/to/root;
    location / { try_files $uri $uri/ @fallback; }
    location @fallback
    {
        fastcgi_pass backend;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php; # тут, кстати, злобный хабрапарсер съел слово S_C_R_I_P_T, будьте аккуратнее - регистр важен!
    }
    

    В случае использования как бекенда не FastCGI, а HTTP, можно написать это так:
    root /path/to/root;
    location / { try_files $uri $uri/ /index.php; }
    

    Нужно понимать, что все аргументы try_files, кроме последнего, будут восприниматься как простые файлы для отдачи, а последний аргумент — уже как новая цель (то есть, туда можно написать обрабатывающий uri или именованый location). Поэтому, попытка написать try_files $uri $uri/ /index_new.php /index_old.php не приведет ни к чему хорошему — вместо выполнения index_new.php будет отдано его содержимое.

    С помощью try_files можно делать еще одну удивительную вещь — не редактируя конфигов, закрыть весь сайт на техобслуживание. Это делается прописыванием try_files /maintenance.html $uri $uri/ @fallback; и затем простым созданием/перемещением файла /maintenance.html с сообщением о технических работах. Это не даст ожидаемого спада производительности в связи с использованием open_file_cache, который так же кеширует и неудачные попытки открытия файла.

    Ошибка номер 2.2, об if ($uri ~ )

    Итак, есть достаточно простое правило — если в Вашей конфигурации есть строка, начинающаяся на «if ($uri ~», то nginx сконфигурирован неправильно. Вся логика проверки uri на что-то должна быть реализована через location, которые теперь поддерживают и выделения.
    RewriteCond %{REQUEST_URI} ^/rss[0-9]{1-6}
    RewriteRule ^(.*)$ rss.php

    переходит в
    location ~ /rss[0-9]{1-6}
    {
        fastcgi_pass backend;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/rss.php; # тут, кстати, злобный хабрапарсер съел слово S_C_R_I_P_T, будьте аккуратнее - регистр важен!
    }


    Ошибка номер 2.3, об if ($host ~ )

    Все, сказанное для if ($uri ~ ) так же верно для if ($host ~ ). Для использования этих правил просто создайте server с server_name в виде регэкспа!

    Не ошибка, но грабли с выделениями

    Если Вы отважились переписать конфиг с использованием выделений в server/location то непременно наткнетесь на небольшую проблему. Она заключается в том, что при входе в location с регекспом затираются серверные выделения, при входе в if или при использовании rewrite затираются выделения location.Увы, я не слишком сильно знаком с рерайтами apache чтобы предоставить код, поэтому опишу требуемое словами.
    Требуется все запросы вида abc.mysite.com/xyz.php перенаправлять на mysite.com/abc/index.php?p=xyz
    Для того, чтобы это работало, приходится писать вот так:
    server
    {
        server_name ~ ^(.*)\.mysite\.com$;
        set $subdom $1;
        location ~ \/(.*)\.php 
        {
            set $script $1;
            rewrite ^ http://mysite.com/$subdom/index.php?p=$script;
        }
    }

    В следующих версиях nginx планируется для выделений на каждом уровне сделать отдельные префиксы (например, вышеописанный рерайт можно будет описать как
    rewrite ^ http://mysite.com/$sc_1/index.php?p=$lc_1;
    ), но пока этого нет, так что приходится писать так.

    Еще неплохой практикой является давание переменным осмысленных имен :-).

    Заключение


    Спасибо всем, кто дочитал пост до конца. Он получился достаточно длинным, но я хотел описать все максимально чисто и понятно.
    Разумеется, существуют и другие ошибки при конфигурировании — буферы, пути, но это — забота системного администратора, а не вебмастера.

    Использованные материалы:
    Русский список рассылки nginx
    Документация nginx
    Поделиться публикацией
    Похожие публикации
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 56
    • +1
      Елки-палки, бывает же такое, пару часов назад для форума возникла необходимость переписать апачевский htaccess на nginx, сидел в раздумьях.
      А тут статья попадается.

      Огромное спасибо.

      • 0
        Спасибо большое за труд, инфа очень вовремя. Как раз в ближайшем будущем мне предстоит переезд с виртуального хостинга на VDS, где и хочу испытать на собственной шкуре связку nginx+apache.
        • 0
          В общем случае в связке nginx+apache нет особой необходимости заморачиваться с переписыванием .htaccess в конфиг nginx, поскольку обработка .htaccess по-прежнему остается на совести apache. Вот если выкидывать apache совсем, то да — тут возникает множество проблем.
          • 0
            В принципе, согласен. Однако, отключение у apache .htaccess может его немного ускорить, а большинстве VDS как раз нужно иметь возможность выжимать максимум из имеющегося :-)
            • 0
              В таком случае лучше еще немножко поднапрячься и выкинуть apache совсем, т.к. зачастую его оставляют лишь по причине невозможности (неумения, нежелания) переписать .htaccess. Разумеется, я говорю про общие случаи, т.к. в них обычно не используются специфические модули, настройки и прочее.
              • 0
                если бы nginx так же можно было настраивать «на лету», как Apache при помощи .htaccess (без админских прав), то цены бы ему не было :)
                • +1
                  Увы, это невозможно по некоторым идеалогическим и техническим причинам :-)

                  1. В nginx нет понятия, подобного апачевскому Directory, только Location, а содержимое .htaccess приписывается как раз в Directory. Это было сделано намеренно, чтобы убрать эту ужасную двойственность конфигурации, где на один запрос влияет куча мест в конфиге. Это уже делает очень затруднительным выбор пути для того, чтобы искать в нем .htaccess.

                  2. Поддержка динамической конфигурации потребует весьма ресурсоемких операций, которые неприменимы на высоких нагрузках.
                  Во-первых, надо сделать stat() для всех возможных .htaccess файлов.
                  Во-вторых, надо прочитать их содержимое.
                  В третьих, надо скомпилировать их с с'merge'ить с текущей конфигурацией.

                  3. Что пораждает следующую проблему — конфигурация конфигурируется при запуске и ее изменение на лету достаточно проблематично.
                  • 0
                    проблема в другом. Мы говорим о разных сегментах пользователей: вы о высокой производительности и сис. админах, я — про «обычных» пользователей, которые не могут «записать в конфиг». Для них единственный вариант — иметь под рукой .htaccess (пусть с небольшой потерей производительности, но все лучше, чем делать то же самое через PHP), который можно как-то менять.

                    Процентное соотношение этих сегментов примерно 1 к 99.
                    • +1
                      Возможно. Но nginx как раз придумывался для этого 1%, а для 99% — придуман apache.
        • +3
          упс…

          *ушёл переписывать конфиги
          • 0
            а если в location появляется

            if ($request_filename ~*

            это нормально?
            • 0
              Честно говоря, не вижу смысла — ведь $request_filename зависит от $uri и root или alias, то есть его возможные значение при написании конфига можно предсказать и вынести в location.

              Можете показать пример конфига, где приходится писать такое?
              • 0
                ну например есть сайт, на нем есть форум по урлу /forum.

                мы не ходим чтобы клиенты не из RU и UA имели к нему доступ, поэтому надо что-то делать с /forum/*.php, иначе они уйдут на локейшен с регуляркой location ~* \.php$ и, соответственно, ограничение по стране не сработает.

                то же самое и с картинками; чтобы никто из USA не видел милой картинки /forum/img/icon/post.png например.

                вот пример:

                location ~* /forum/ {
                if ($country = 'en') {
                rewrite ^ /404.html last;
                }

                if ($request_filename ~* "\.php$" ) {
                break;
                proxy_pass backend;
                }

                if ($request_filename ~* "\.(jpg|jpeg|gif|png|bmp|ico|swf|flv|css|txt|xml|rss|js)$" ) {
                #if ($invalid_referer) {
                # return 403;
                #}
                expires max;
                }
                }

                • 0
                  Какой ужас :-)

                  location ~* /forum/(.*)\.php$
                  {
                      proxy_pass ;
                      if ($country = 'en') { return 404; }
                  }
                  
                  location ~* /forum/
                  {
                      if ($country = 'en') { return 404; }
                  }
                  
                  location ~* "/forum/(.*)\.(jpg|jpeg|gif|png|bmp|ico|swf|flv|css|txt|xml|rss|js)$"
                  {
                      expires max;
                      if ($country = 'en') { return 404; }
                  }
                  .

                  Еще можно сделать вложенными location, намного красивее:
                  <code>location /forum
                  {
                      if ($country = 'en') { return 404; }
                      location ~ \.php$
                      {
                          proxy_pass ...;
                      }
                      location ~* "\.(jpg|jpeg|gif|png|bmp|ico|swf|flv|css|txt|xml|rss|js)$
                      {
                          expires max;
                      }
                  }</code>
                  • 0
                    я просто читал рассылку, и что-то там не жаловали вложенные локейшены (правда, давно это было), а много локайшенов я не делал, чтобы избежать повторения if ($country = 'en') { return 404; }

                    всё-таки при конфигурировании nginx надо гасить в себе «программисткие» порывы :)
                    • 0
                      а как насчёт этого? :)

                      location ~* \.(avi|mp4|mkv|wma|flv|wmv|mpg|mpeg|mp3|rar|zip|7z)$ {
                      if ($invalid_referer) {
                      return 403;
                      }

                      limit_conn download_zone 5;
                      limit_rate 1m;
                      set $limit_rate 1m;

                      output_buffers 1 256k;

                      directio 10m;
                      expires max;

                      types {}
                      default_type application/octet-stream;

                      #internal;
                      #root $_application_storage;

                      if ($uri ~ /([^/]*)$) {
                      set $_f $1;
                      add_header Content-disposition «attachment;filename=$_f»;
                      }

                      #add_header Content-type application/octet-stream;
                      #add_header Content-Type application/force-download;

                      }

                      • 0
                        location ~* ^/([^/]*)\.(avi|mp4|mkv|wma|flv|wmv|mpg|mpeg|mp3|rar|zip|7z)$ {
                            if ($invalid_referer) {
                                return 403;
                            }
                            прочее
                            add_header Content-disposition "attachment;filename=$1.$2";
                        }

                        Насколько я понимаю, как-то так.
                        • 0
                          и правда, тысячу чертей!!! :)
              • +6
                Хочется перефразировать известное:
                «Despite the tons of examples and docs, nginx is voodoo. Damned cool voodoo, but still voodoo.» © ;-)

                • 0
                  А что, если мне нужно здесь: location / { try_files $uri $uri/ @fallback; } только проверку существования файла, и если его нет, то отдавать управление на index.php? Просто убрать $uri/?
                  • 0
                    Да.
                    • 0
                      Спасибо. Но у меня вопросов ещё так много… :)
                      • 0
                        А как сделать, чтобы в @fallback падали не только не найденные файлы, но и .php$? Можно, конечно, прописать ещё один локейшон с содержанием повторяющем @fallback, но это как-то не тру…
                        • 0
                          На данный момент — никак, только дублированием location'a (прямо или через include).

                          Давно упоминалось несколько идей, как это можно сделать:
                          1) сделать хендлер redirect, который сможет перенаправлять обработку запроса в именованный location или по другому uri.
                          2) выносить конфигурацию в отдельные блоки, например
                          use php-conf
                          {
                              fastcgi_pass ...;
                          }
                          location ~ \.php$
                          {
                              use php-conf;
                          }
                          location @fallback
                          {
                              use php-conf;
                          }

                          Увы, сейчас ничего из этого не реализовано :-(
                          • 0
                            Мда, очень жаль :(
                    • 0
                      Может быть Вам создать тему ликбеза, с человеческими объяснениями и примерами? Хотя, может это никому не нужно, но мне было бы весьма полезно.
                      • 0
                        Увы, типичные вопросы, чтобы вынести их в тему, мне неизвестны.

                        А вопросы — можно задавать в комментариях, все они будут отвечены :) По их материалам потом тоже можно будет сделать отдельный пост.
                        • 0
                          Ну, например. Есть структура каталогов:

                          data/
                          cache/
                          index.php

                          Нужно при запросе:
                          host.name/hello.html

                          Проверить, есть ли такой файл в кэше.
                          1. Если есть, отдать его (это получается без проблем)
                          2. Если его нет, то передать управление index.php
                          3. Если пришли переменные методом POST, то не проверяя наличие файла, передать управление в index.php

                          Вот, что я пытался сделать:

                          location ~ \.html$ {
                          root cache;
                          try_files $uri @fallback;
                          } // файл отдаётся

                          location @fallback {
                          index index.php;
                          } // тут, похоже, я всё сделал неправильно

                          Про POST я вообще молчу :) Ещё не нашёл как сделать.
                          • +2
                            Я бы сделал так:
                            location ~ \.html$
                            {
                                root cache;
                                error_page 406 =@indexphp;
                                if ( $request_method = 'POST' ) { return 406; }
                                try_fiiles $uri @indexphp;
                            }
                            location @indexphp
                            {
                                fastcgi_pass ...;
                                fastcgi_param script_FILENAME $document_root/index.php;
                                include fastcgi_params;
                            }</code>


                            Тут мы по error_page .. if .. return или try_files уходим в другой location, когда кеширование неприменимо.

                            Если бекенд - apache, то можно написать что-то такое:
                            location ~ \.html$
                            {
                                root cache;
                                error_page 406 =/index.php;
                                if ( $request_method = 'POST' ) { return 406; }
                                try_fiiles $uri /index.php;
                            }
                            location =/index.php
                            {
                                proxy_pass ...;
                            }</code>


                            Вообще, для подобного есть встроенное кеширование nginx, которое работает для proxy_pass и fastcgi_pass, учитывает и отсутствие файла, и POST, и истечение. Есть замечательная статья по этому поводу: dklab.ru/chicken/nablas/56.html
                            • 0
                              Спасибо! Почитаю обязательно.
                      • +3
                        Захожу на habr.ru а там: Welcome to nginx!
                        • +2
                          Наверное, ошибки исправляют :)
                        • 0
                          По поводу ошибки 2.3. Есть такая конструкция: server {
                          listen 80;
                          server_name blabla.ru *.blabla.ru "";

                          if ($host != blabla.ru ) {
                          rewrite ^(.*)$ httр://blabla.ru$1 permanent;
                          }

                          Как тут можно убрать if $host?
                          • +1
                            server
                            {
                                listen 80;
                                server_name *.bla.ru "";
                                rewrite ^ httр://blabla.ru$request_uri? permanent;
                            }
                            server
                            {
                                listen 80;
                                server_name bla.ru;
                                ... обычный конфиг ...
                            }
                          • 0
                            Хотелось бы задать такой вопрос…

                            Возможно ли (и если да — то как) через реврайт nginx'a запретить доступ к некоторым ссылкам сайта. Ну например:

                            host.su/admin/... — nginx, ссылка не работает.
                            host.su:8080/admin/… — apache, ссылка работает.
                            • +1
                              location ~ /admin(.*)
                              {
                                  return 403;
                              }
                              location /
                              {
                                   proxy_pass ...;
                              }
                            • +1
                              Упс… Сижу переписываю конфиги :-)
                              • 0
                                с этими не поможешь?
                                forum.nginx.org/read.php?11,4025,10177
                                forum.nginx.org/read.php?21,16373
                                • 0
                                  Насколько я помню,
                                  1) для работы переменной надо, чтобы все тело запроса не писалось во временный файл (то есть, размер тела был меньше, чем размер одного буфера), client_body_in_single_buffer должен быть on, в location, где хочется получить значение переменной, должна быть директива proxy_pass или fastcgi_pass. Хотя, матчить POST по регекспу — не очень хорошая затея, пожалейте процессор и память :) Заюзайте iptables и его модуль string.

                                  2) Проблема в том, что % не считается членом именем переменной. Сейчас попробую сделать патч.
                                  • 0
                                    client_body_in_single_buffer не помогал, iptables теоретически должен быть тяжелее — строка же больше :)
                                    • 0
                                      Регексп тяжелее поиска подстроки :)

                                      Надо смотреть, что происходит внутри. Сейчас уже не смогу, скорее всего — завтра днем.
                                      • 0
                                        ну там все равно нужен регексп был и плюс ко всему в зависимости от условия надо было менять апстрим на конкретный, т.е. тока на уровне приложения можно принять решение.
                                    • 0
                                      2) насколько я понял он вообще uri не unescape-ит
                                  • +1
                                    Патч для второй проблемы (на 0.8.21, должен сработать для большого числа версий) — dolgov.name/nginx/vars_names.patch
                                    Сработало написание переменной как $arg_user%5fid.

                                    Рекомендую после наложение проверить, не сломалось ли еще что-то.
                                  • 0
                                    client_body_in_single_buffer не помогал, iptables теоретически должен быть тяжелее — строка же больше :)
                                  • 0
                                    у меня тоже есть вопрос. не знаю возможно ли такое реализовать средствами nginx

                                    стандартная ситуация:

                                    location ~ \.(jpg|gif|png)$ {
                                        root images;
                                    }
                                    location / {
                                        proxy_pass ...;
                                    }

                                    можно ли кешировать ответы апача, но отдавать всегда свежий контент (ну как если бы мы кешировали с таймаутом в 0 секунд). а в случае если апач возвращает 50х ошибку — выдавать страницу из кеша.

                                    немного сумбурно объясняю, я просто сам еще толком не уяснил для себя как это должно работать.

                                    пример: все работает в штатном режиме — всегда отдается свежий контент без всякого кеширования. но вдруг на бекэнде что-то ломается (допустим отваливается база данных) и бекенд завершает работу с ошибкой 503 допустим. может ли nginx получив такой ответ посмотреть есть ли у него в кеше такая страничка (ее последняя нормальная версия) и если есть — отдать?
                                    • 0
                                      Можно попробовать
                                      proxy_cache_use_stale http_502 http_503 http_504;
                                      proxy_cache_valid 0;
                                      • 0
                                        при proxy_cache_valid 0; он ничего в кеш не записывает.
                                        ls -la /var/cache/nginx/ — всегда пусто (чтобы было понятно о чем я говорю)

                                        притом если поставить например proxy_cache_valid 5m; — то кешируются все запросы на 5 минут

                                        видимо ему нужно как то дать понять чтобы он в кеш писал каждый нормальный ответ апача в независимости от времени жизни кеша

                                        вот так более-менее работает:

                                        proxy_cache_use_stale http_503;
                                        proxy_cache_valid 200 301 302 304 1ms;
                                        

                                        но есть непонятные баги:
                                        во-первых если быстро рефрешить страницу в нормальном режиме (когда бекэнд отдает 200) nginx через раз показывает закешированную копию. так, будто время жизни кеша 1-2 секунды, а не 1 милисекунда.
                                        во-вторых в «аварийном» режиме (когда апач отдает 503) nginx отдает последнюю имеющуюся у него версию из кеша, но через раз вместо нее предлагает скачать какой-то файл. т.е. просто вываливается диалог сохранения/открытия файла с непонятным именем zEDex4TV.dms.part. причем происходит это бессистемно. мне так и не удалось понять в каком случае он отдает правильную страницу, а когда предлагает вдруг что-то сохранить/скачать. раз 5 показывает последнюю версию из кеша как и надо, а потом вдруг бац.

                                    • 0
                                      Сорри за некропостинг, но написано «все желающие» :)

                                      Только начал осваивать nginx, перенес из апача что-то вроде

                                      server {
                                      listen example.com:80;
                                      server_name example.com www.example.com;

                                      location / {
                                      root /var/www/example.com/www;
                                      index index.php;
                                      }

                                      location /subdir/ {
                                      root /var/www/example.com/www;
                                      index index.php;
                                      if (!-e $request_filename) {
                                      rewrite ^/subdir/(.*)$ /subdir/index.php?/$1 last;
                                      }

                                      }
                                      location ~ .php$ {
                                      root /var/www/example.com/www;
                                      fastcgi_pass 127.0.0.1:9000;
                                      fastcgi_index index.php;
                                      fastcgi_param script_FILENAME $document_root$fastcgi_script_name;
                                      fastcgi_param QUERY_STRING $query_string;
                                      fastcgi_param REQUEST_METHOD $request_method;
                                      fastcgi_param CONTENT_TYPE $content_type;
                                      fastcgi_param CONTENT_LENGHT $content_length;
                                      include fastcgi_params;
                                      }
                                      }

                                      Смысл в том, что все существующие файлы из example.com/subdir отдаются напрямую (хотя в идеале надо исключить оттуда все .php, кроме example.com/subdir/index.php и тот не напрямую, а только через реврайт)

                                      В принципе работает (после пары часов курения доков, гугления и использование метода научного тыка), но прочитал топик и понял, что допустил ошибку 2.1. Но, увы, как не мудрил не получилось сделать через вариант с @fallback, чтобы передать как QUERY_STRING на $document_root/subdir/index.php всё, что после example.com/subdir.

                                      Это реально? (версия nginx 0.7.64)
                                      • 0
                                        0.7.64 — старая. Попробуйте так, но не уверен. Если не будет работать, как надо — сообщите, посмотрим еще :)
                                        <code>
                                        location = /subdir/index.php
                                        {
                                            root /var/www/example.com/www;
                                            fastcgi_pass 127.0.0.1:9000;
                                            fastcgi_index index.php;
                                            fastcgi_param script_FILENAME $document_root$fastcgi_script_name;
                                            fastcgi_param QUERY_STRING $query_string;
                                            fastcgi_param REQUEST_METHOD $request_method;
                                            fastcgi_param CONTENT_TYPE $content_type;
                                            fastcgi_param CONTENT_LENGHT $content_length;
                                            include fastcgi_params;
                                        }
                                        location ~ /subdir/(.*)$
                                        {
                                            root /var/www/example.com/www;
                                            try_files $uri /subdir/iindex.php?/$1;
                                        }


                                        Есть вариант переделать скрипт, чтобы он принимал не то, что после subdir, а весь путь, и написать тогда вот так:
                                        <code>
                                        location = /subdir/index.php
                                        {
                                            root /var/www/example.com/www;
                                            fastcgi_pass 127.0.0.1:9000;
                                            fastcgi_index index.php;
                                            fastcgi_param script_FILENAME $document_root/subdir/index.php;
                                            fastcgi_param QUERY_STRING $request_uri;
                                            fastcgi_param REQUEST_METHOD $request_method;
                                            fastcgi_param CONTENT_TYPE $content_type;
                                            fastcgi_param CONTENT_LENGHT $content_length;
                                            include fastcgi_params;
                                        }
                                        location ~ /subdir/(.*)$
                                        {
                                            root /var/www/example.com/www;
                                            try_files $uri @fallback;
                                        }


                                        • 0
                                          Спасибо большое, первый вариант заработал. Вроде смотрю на него, каждая строчка ясна и почему сам не додумался не понятно, просто надо думать по другому, наверное :) Второй вариант — возможности исправить скрипт нет, точнее каждый апдейт скрипта придётся править ручками.

                                          0.7.64 — старая? вроде это последний стабильный билд от 16.11.2009 — чуть больше месяца. Или 0.8.xx ближе к сквиз, чем к сид (если говорить в терминах дебиан) и на некритичных серверах его вполне можно использовать?

                                          P.S. Пока разбирался, понял что строчки
                                          fastcgi_param QUERY_STRING $request_uri;
                                          и т. д. не нужны, т. к. они (и еще несколько) уже есть в подключаемом дефолтном fastcgi_params
                                          • 0
                                            Увы, в терминах debian я не умепю оперировать :) 0.8 — текущая версия, 0.7 — старая версия. 0.7 не развивается, в нее только раз в N времени бекпортятся исправления багов, найденных во время разработки 0.8. Если Вы найдете в 0.7 баг, то его исправят в 0.8 :)
                                            Я использую последнюю ветку все время, таких уж страшных проблем, как при использовании бета-ПО, никогда не имел.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое