子目录运行子站点必须用alias且末尾带/,location /subdir/须置于正则规则之前,显式设置fastcgi_param SCRIPT_FILENAME $request_filename,多子目录时按路径长度降序或用^~前缀避免匹配冲突。

子目录运行子站点必须用 alias,且末尾带 /;漏掉斜杠、写错位置、没重写 SCRIPT_FILENAME,三者任一都会导致 404 或 “No input file specified”。
location /subdir/ 必须放在正则匹配之前
宝塔默认配置里,类似 location ~ .*\.(js|css|png|jpg)$ 这类静态资源正则规则通常写在最前面。一旦它先匹配上 /subdir/app.css,Nginx 就不会继续找你写的 location /subdir/,结果按主站 root 去找文件——路径错、权限错、MIME 错,全挂。
解决方法只有手动调序:
- 打开站点配置文件(路径如
/www/server/panel/vhost/nginx/your-site.conf) - 把你的
location /subdir/ { ... }块,剪切并粘贴到所有location ~正则块的上方 - 确保它在
location / { ... }之后、其他正则之前
alias 路径末尾必须加 /,且不能和 root 混用
alias 和 root 对 URI 的处理逻辑完全不同:
-
alias /www/wwwroot/subsite/;→ 请求/subdir/index.php映射为/www/wwwroot/subsite/index.php -
alias /www/wwwroot/subsite;(缺/)→ 实际去找/www/wwwroot/subsiteindex.php,直接 404 -
root /www/wwwroot/subsite/;→ 请求/subdir/index.php会拼成/www/wwwroot/subsite/subdir/index.php,多了一层/subdir
所以:只用 alias,末尾必须有 /,且整个映射必须严格限定在 location 块内,绝不能动顶层 root。
PHP 子目录必须显式设置 SCRIPT_FILENAME
即使 alias 路径对了,PHP-FPM 仍可能报 No input file specified。原因是宝塔默认的 fastcgi_param SCRIPT_FILENAME 是靠 $document_root$fastcgi_script_name 拼出来的,而 $document_root 还是主站的,不是子目录的。
必须在子目录的 PHP 处理块中覆盖该参数:
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/tmp/php-cgi-80.sock;
}
注意:$request_filename 是 Nginx 解析出的真实磁盘路径,它已包含 alias 映射后的结果,这才是 PHP 需要的。
如果子站点用 ThinkPHP、Laravel 等需要 PATH_INFO 的框架,还得补一句:fastcgi_param PATH_INFO $fastcgi_path_info;
多个子目录共存时,路径长度决定顺序
比如你要同时配 /admin/ 和 /admin/api/,location /admin/api/ 必须写在 location /admin/ 前面。否则所有 /admin/api/xxx 请求都会被短规则 /admin/ 截走,导致 API 路由失效。
更安全的做法是统一用 ^~ 前缀:
location ^~ /admin/api/ { alias /www/wwwroot/api/; ... }location ^~ /admin/ { alias /www/wwwroot/admin/; ... }
^~ 表示前缀匹配且优先于正则,还能避免隐式继承问题。这点很容易被忽略,但线上出问题时最难排查。


















