Назад | Перейти на главную страницу

PHP в псевдониме каталога NGINX не работает

У меня свежая установка сервера Ubuntu 14.04. Я установил nginx, php и т.д.

server {
  listen 80;
  listen [::]:80;

  server_name testone.local;

  root /var/www/htmlone;
  index index.html;

  # pass the PHP scripts to FastCGI server listening on the php-fpm socket
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }

  location /alias {
    alias  /var/www/htmlalias;
    location ~ \.php$ {
      try_files $uri =404;
      fastcgi_pass unix:/var/run/php5-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }
  }
}

Если я использую простой скрипт php в /var/www/htmlone php выполняется должным образом. Если я использую тот же сценарий в /var/www/htmlalias он выполняется не так, как ожидалось. Если я вставлю HTML-скрипт в /var/www/htmlalias однако он отображается так, как ожидалось, поэтому псевдоним действует как псевдоним, но не выполняет файлы php, но php работает в основном корневом каталоге.

По многим вопросам о сбоях сервера я обнаружил, что эта общая настройка должна работать, но это не так. Кто-нибудь видит что-нибудь, что я делаю неправильно? Я не вижу сообщений в журнале ошибок.

Я должен добавить, что это для версии nginx: nginx / 1.8.0

Проблема, с которой вы столкнулись, на самом деле давний баг, зарегистрированный 3 года назад что приводит к alias и try_files не работать вместе.

На странице с ошибкой есть обходной путь Люком Хауэллом, который выглядит следующим образом:

location /api { ## URL string to use for api ##
    alias /home/api/site_files/; ## Site root for api code ##

    ## Check for file existing and if there, stop ##
    if (-f $request_filename) {
        break;
    }

    ## Check for file existing and if there, stop ##
    if (-d $request_filename) {
        break;
    }

    ## If we get here then there is no file or directory matching request_filename ##
    rewrite (.*) /api/index.php?$query_string;

    ## Normal php block for processing ##
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

Обратите внимание, что что касается nginx, ЕСЛИ это зло и по возможности следует избегать.

Судя по моему тестированию вышеупомянутой конфигурации, это наличие

try_files $uri =404;

внутри вложенного псевдонима php, который вызывает проблему. С его помощью nginx проверяет наличие "/var/www/htmlalias/alias/index.php" (обратите внимание на добавление псевдонима и uri), обнаруживает, что его не существует, а затем возвращает 404. Удаление этого файла try_files сначала останавливает поиск этого файла на диске и передает запрос непосредственно в fastcgi, который затем находит правильный файл в SCRIPT_FILENAME.

Если вы хотите, чтобы несуществующие файлы PHP выдавали ошибку 404, а не ошибку PHP, то работает следующее:

  location /alias {
    alias  /var/www/htmlalias;
    location ~ /([^/]+\.php)$ {
      try_files /$1 =404;
      fastcgi_pass unix:/var/run/php5-fpm.sock;
      fastcgi_index index.php;
      include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
  }

Сначала регулярное выражение фиксирует имя файла заполнения php-файла (например, foo.php) как $ 1. Затем try_files проверяет относительно текущего псевдонима, существует ли этот файл, и возвращает 404, если нет.

Затем нам нужно переопределить SCRIPT_FILENAME по умолчанию, как определено в fastcgi_params, переопределив его после включения, потому что $ request_filename по какой-то причине, которую я не понимаю, будет совершенно неправильным (буквально /index.php).

Я решил это так:

конфигурация сервера по умолчанию (без псевдонима), в вашем примере:

server {
  listen 80;
  listen [::]:80;

  server_name testone.local;

  root /var/www/htmlone;
  index index.html;

  # pass the PHP scripts to FastCGI server listening on the php-fpm socket
  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }
}

и из командной строки создайте символическую ссылку под /var/www/htmlone:

ln -s /var/www/htmlalias /var/www/htmlone/alias