apache伪静态重写死循环需开启loglevel warn rewrite:trace3查error_log,重点观察uri与rewrite uri反复变化;规则须加[l]终止、前置rewritecond守门,并区分内部重写与外部重定向。

伪静态重写规则陷入死循环,Apache 通常不会直接报错,而是触发内部重定向超限(AH00124)或浏览器显示 ERR_TOO_MANY_REDIRECTS。这类问题不能靠猜,必须让 Apache “说出它做了什么”——核心手段就是开启重写追踪日志。
打开 rewrite trace 日志并定位循环点
Apache 的重写过程默认静默,需主动启用详细跟踪:
- 在对应虚拟主机配置或主配置中添加:
LogLevel warn rewrite:trace3
(注意:不要设为trace8,开到trace3已足够看清路径变化,且避免日志爆炸) - 保存后执行重载:
sudo systemctl reload apache2(宝塔点「重载配置」) - 复现一次出问题的请求(比如刷新某个页面或点击一个链接)
- 立即查看错误日志:
tail -f /www/wwwlogs/your-domain.error.log(宝塔在网站日志页可直接打开) - 搜索该请求的 IP 或时间戳,找到以
[rewrite:trace3]开头的连续多行日志
重点看每行末尾的 URI 和 REWRITE URI 变化。如果出现类似下面的反复模式,就确认是循环:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
/admin/ → /index.php?r=admin/ → /admin//api/user → /index.php?r=api/user → /api/user/old/page → /new/page → /old/page
检查 RewriteRule 是否缺少守门条件和终止标志
日志里看到反复改写,大概率是规则没设“闸门”,也没加“刹车”:
- 每条
RewriteRule后面都应带[L],否则后续规则还会继续匹配 - 入口类规则(如强制 HTTPS、统一 www)必须前置
RewriteCond守门,例如:RewriteCond %{HTTPS} off<br>RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L] - 若规则目标可能再次命中自身(如把所有请求转给
index.php),必须先排除该文件:RewriteCond %{REQUEST_URI} !^/index\.php - 避免用
RewriteRule ^(.*)$ /index.php [L]这种无差别转发,它会让/index.php自己也再进一遍规则
区分内部重写与外部重定向
混淆两者是循环的常见根源:
- 内部重写(URL 地址栏不变):不带
[R]标志,只走一次 Apache 内部流程,不计入重定向计数 - 外部重定向(地址栏跳变):带
[R=301]或[R=302],每次都会发起新 HTTP 请求,浏览器和服务器都算一次跳转 - 典型错误:先
R=301跳 HTTPS,再R=301跳 www,又R=301跳新路径——三跳起步,极易触发浏览器拦截 - 正确做法:合并守门条件,单条规则完成多重判断:
RewriteCond %{HTTPS} off [OR]<br>RewriteCond %{HTTP_HOST} !^www\.<br>RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
验证模块与权限是否真正就位
日志空或 trace 不输出,往往说明请求根本没进重写流程:
- 执行
apachectl -M | grep rewrite,确认输出含rewrite_module (shared) - 检查站点根目录对应的
<directory></directory>块中是否有:AllowOverride All<br>Require all granted
- 确认
.htaccess确实在该目录下,且第一行为RewriteEngine On - 删掉所有临时测试规则,用最简规则验证是否生效:
RewriteEngine On<br>RewriteRule ^test$ /index.php [L]
访问/test看是否真跳转










