2013年7月9日星期二

Nginx alias try_files php-fpm 共存

Nginx 1.2.1 服务器有这么一个配置:
server {
 listen 80 default_server;
 listen [::]:80 default_server ipv6only=on;
 root /var/www;
 index index.php index.html;
 autoindex on;
 autoindex_localtime on;
 try_files $uri $uri/ =404;
 location ~ ^/~([^/]+)(/.*)?\.php(/.*)?$ {
  alias /home/$1/public_html$2.php;
  fastcgi_pass unix:/var/run/php5-fpm.sock;
  fastcgi_index index.php;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME /home/$1/public_html$2.php;
  fastcgi_param PATH_INFO $3;
 }
 location ~ ^/~([^/]+)(/.*)?$ {
  alias /home/$1/public_html$2;
 }
}
目的是把所有的 /~username/ 映射到 /home/username/public_html/,让服务器的用户能够存放自己的文件。
但这样带来了一个问题,如果访问一个不存在的 .php 文件,比如 /~username/asdfasdf.php,php-fpm 就会报错,显示“Invalid Argument”而不是 Nginx 的“404 Not Found”页面。
查看了 Nginx 的 Wiki,有这么一句话:
Note that there is a longstanding bug that alias and try_files don't work together.
但是我不会就此罢休的!
于是我观察了 Nginx 传递给 PHP 的环境变量,发现 $_SERVER["DOCUMENT_ROOT"] 变成了和 $_SERVER["SCRIPT_FILENAME"] 一样的值,而不是 /var/www 了。
try_files 指令是从 $document_root 算起的,比如 try_files $uri =404; 就是检测 $document_root$uri 是否存在。
弄明白了这个,就豁然开朗了。在 alias 那一行后面加上 try_files "" =404; 即可。