在Linux的Apache中为多级目录配置独立重写规则,核心是按目录层级分别控制、避免规则继承与冲突;需启用mod_rewrite模块、设置AllowOverride All或显式Directory块、开启FollowSymLinks,并通过.htaccess或VirtualHost内嵌套Directory分层定义规则,注意路径不带开头斜杠、每文件单独启用RewriteEngine、合理使用RewriteCond排除真实文件目录。

在 Linux 的 Apache 中为多级目录配置独立重写规则,核心是**按目录层级分别控制、避免规则继承与冲突**。每个子目录若需不同逻辑(比如 /blog 用伪静态,/api 做代理转发),就不能只靠根目录一条规则覆盖,而要分层隔离配置。
确保基础模块和权限已就绪
所有重写功能的前提一致:
- 确认
mod_rewrite已启用:Debian/Ubuntu 执行sudo a2enmod rewrite && sudo systemctl restart apache2;CentOS/RHEL 检查/etc/httpd/conf.modules.d/00-base.conf中LoadModule rewrite_module modules/mod_rewrite.so未被注释 - 主配置或虚拟主机中,对目标目录路径必须设置
AllowOverride All(若用.htaccess)或显式配置<Directory>块(若直写规则) -
Options +FollowSymLinks必须开启,否则多数规则会触发 500 错误
方式一:用 .htaccess 在各子目录独立部署
适合开发灵活、站点结构常变的场景。每个子目录放自己的 .htaccess,互不干扰:
-
/var/www/html/blog/.htaccess:RewriteEngine On<br>RewriteRule ^post/([0-9]+)$ /blog/post.php?id=$1 [L]
-
/var/www/html/api/.htaccess:RewriteEngine On<br>RewriteRule ^v1/(.*)$ /api/v1/router.php?path=$1 [QSA,L]
- 注意:上级目录(如根目录)的
.htaccess不会自动向下传递规则;Apache 默认逐级向上查找并合并,但只要子目录有自己的RewriteEngine On,就会以该文件为准,覆盖上级逻辑
方式二:在 VirtualHost 内用嵌套 <Directory> 显式定义
更稳定、性能略优,适合生产环境。直接在站点配置文件(如 /etc/apache2/sites-available/example.com.conf)中分块声明:
-
<Directory "/var/www/html/blog">:Options +FollowSymLinks<br>AllowOverride None<br>RewriteEngine On<br>RewriteRule ^article/([0-9]+)/?$ /blog/article.php?id=$1 [L]
-
<Directory "/var/www/html/admin">:Options +FollowSymLinks<br>AllowOverride None<br>RewriteEngine On<br>RewriteCond %{REQUEST_FILENAME} !-f<br>RewriteCond %{REQUEST_FILENAME} !-d<br>RewriteRule ^(.*)$ /admin/index.php [L] - 关键点:
AllowOverride None表示禁用该目录下.htaccess,所有规则由配置文件统一管理,避免混用导致重复执行
避坑要点:路径匹配与作用域边界
多级目录下最容易出错的是路径写法和规则范围:
- 正则中的路径**不带开头斜杠**:写
^post/,不是^/post/(后者在<Directory>或.htaccess中会匹配失败) - 每条
RewriteRule前必须有RewriteEngine On,且仅对该<Directory>或该.htaccess文件生效 - 需要排除真实文件/目录时(常见于 SPA 路由),在对应目录的规则前加两行条件:
RewriteCond %{REQUEST_FILENAME} !-f<br>RewriteCond %{REQUEST_FILENAME} !-d - 若某子目录需跳转到外部地址(如
/old全部 301 到新域名),加[R=301,L];若只是内部重写(URL 不变),不加R标志


















