Nginx location块内root指令失效问题排查
咱先拆解下你遇到的问题:明明给/sub路径配了单独的root,结果访问mydomain.com/sub/xxx还是走了主应用的目录,核心问题要么是location匹配没生效,要么是try_files的fallback逻辑串了,或者你对root/alias的用法理解有偏差。
先搞懂root在location里的工作逻辑
当你在location /sub里用root /home/myname/other_app/public时,Nginx会把「root指定的目录」+「location的路径」+「请求的URI后缀」拼起来找文件。也就是说,访问/sub/xxx时,它会去找/home/myname/other_app/public/sub/xxx——这其实和你期望的路径完全一致,但为什么实际走了主应用?大概率是下面几个原因:
原因1:location匹配优先级没抢过主应用
虽然location /sub比location /更具体,但如果你的配置里还有其他正则匹配的location(比如.php的规则),普通前缀匹配的优先级会比正则低。要强制让/sub的location优先匹配,给它加个^~修饰符就行:
location ^~ /sub { root /home/myname/other_app/public; try_files $uri @other_named_location; }
^~会告诉Nginx:只要请求路径匹配/sub前缀,就直接用这个location,不用再看后面的正则规则。
原因2:@other_named_location指向了主应用
你配置里的try_files $uri @other_named_location意思是:先找$uri对应的文件,找不到就跳转到@other_named_location处理。如果这个@other_named_location的配置是给主应用写的(比如指向主应用的PHP-FPM或者反向代理地址),那当/sub/xxx文件不存在时,就会直接 fallback到主应用,自然就走了主应用的目录。
你得检查@other_named_location的配置,确保它是给other_app服务的。比如other_app是PHP应用的话,应该写成这样:
location @other_named_location { fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # 改成你的PHP-FPM地址 fastcgi_param SCRIPT_FILENAME /home/myname/other_app/public/index.php; include fastcgi_params; }
原因3:目标文件本身不存在或权限不足
如果/home/myname/other_app/public/sub/xxx这个文件根本不存在,或者Nginx进程没有读取权限,try_files也会触发fallback到@other_named_location。你可以先手动检查文件路径和权限:
ls -l /home/myname/other_app/public/sub/xxx
关于你尝试过的alias用法
如果你想用alias实现同样的效果,得注意路径写法:
- 如果你期望
/sub/xxx对应/home/myname/other_app/public/sub/xxx,alias应该写成:
location /sub { alias /home/myname/other_app/public/sub; try_files $uri @other_named_location; }
因为alias会把请求URI里的/sub前缀替换成alias的值,所以/sub/xxx会直接映射到/home/myname/other_app/public/sub/xxx。要是你写成alias /home/myname/other_app/public,那/sub/xxx会变成/home/myname/other_app/public/xxx,这就不符合你的需求了。
最后记得修改配置后重载Nginx让配置生效:
sudo nginx -s reload
内容的提问来源于stack exchange,提问作者goodbyeera

