try_files在这个nginx配置中的作用是什么?

我在设置基本的 Nginx / PHP-FPM web服务器时复制了这个配置。
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name server_domain_name_or_IP;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        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文件提供服务时,location ~ \.php$ { .... }块中的try_files是如何工作的,例如domain.com/test.php
我以为这行代码
try_files $uri =404; 
告诉Nginx继续尝试提供静态文件 - 即将$uri附加到root目录,如果文件存在 - Nginx将简单地发送静态文件,请求将结束,不是吗? 因此,fastcgi_pass不会发生?但是php-fpm会接收并执行脚本。 为什么try_files不能阻止fastcgi_pass呢?
2个回答

try_files并不是告诉nginx来提供静态文件的。在没有其他操作的情况下,到达闭括号会导致它提供静态文件。try_files会检查本地文件系统中文件的存在性,并可能重写URL。

因此,try_files $uri =404;是一种常见的技巧之一,用于克服特定的脚本注入漏洞,确保PHP文件是一个“真实”的文件,然后再将URL发送给上游解释器。


哦,好的,所以 try_files 检查 $root$uri 是否存在,如果存在,它只是记住它,然后继续处理 location 块的其余部分。如果没有其他指定如何处理请求/文件的内容,那么nginx会作为最后的选择提供静态文件服务。 - the_velour_fog
1@user4668401 是的。但是在nginx中,一个位置块并不必须包含try_files指令才能从该位置提供静态文件服务。 - Richard Smith
我明白,如果在一个location block中有一个try_files指令,并且它没有匹配到任何文件,那么它会停止当前location block的处理,并使用try_files的最终值生成一个新的内部重定向。 - the_velour_fog
1是的。有几个指令可以做到这一点。 - Richard Smith
哥们...我花了好几个小时试图弄清楚为什么try_files不起作用,明明文件存在,尝试了有无root,尝试了硬编码路径等等...始终都是404错误!你的第一段话对我来说至关重要,终于让我明白了为什么try_files不起作用。我需要先手动进行rewrite,去掉URL的前缀,try_files才能工作。在了解到try_files并不会提供文件服务之后,一切都变得清晰了!非常感谢!+1 - Nuno

为什么你认为应该这样做?Nginx文档并没有提到这样的情况。 检查指定顺序中文件的存在,并使用找到的第一个文件进行请求处理;处理在当前上下文中进行。如果没有找到任何文件,则会内部重定向到最后一个参数中指定的URI。 只要找到文件,请求就会正常处理,即传递给fastcgi。否则将发送404错误。

哦,所以,尝试文件有点像一个守卫,它说:“如果我找不到底层文件,那么这个位置块将不会进行进一步处理?”回退将被使用,并且内部重定向将重新发送处理开始? - the_velour_fog