limitinternalrecursion不能防止死循环,仅在重写链超默认深度10时强制中止并报错,属事后熔断机制;需通过规则设计(如排除终点路径、避免正则重叠、补全[l]标志)主动预防。
limitinternalrecursion 不能防止死循环,它只在重写链超出设定深度时强制中止并报错。把它理解成“安全气囊”更准确——撞上了才弹出,不是方向盘上的防撞系统。真正防死循环,靠的是规则设计;这个指令的作用,是给失控的重写链设一道熔断阀,避免服务器卡死或耗尽资源。
它在虚拟主机中怎么配置
该指令支持 server config、virtual host 和 directory 作用域,但不能写在 .htaccess 中。在虚拟主机配置块内直接添加即可:
- 写一个数字(如
LimitInternalRecursion 15),表示内部重定向和子请求嵌套深度都设为 15 - 写两个数字(如
LimitInternalRecursion 15 5),第一个是重定向链上限,第二个是子请求(如 DirectoryIndex 查找)嵌套深度 - 默认值是
10 10,多数场景无需修改;调高仅用于临时排查,不可作为“修复”手段
为什么不能靠它“防止”循环
Apache 不分析 RewriteRule 的逻辑关系,也不预判某条规则是否会再次触发自身。它只计数:每次 mod_rewrite 发起内部重定向(internal redirect),计数器就 +1。一旦达到上限,就抛出 [alert] mod_rewrite: maximum number of internal redirects reached 并返回 500 错误——此时循环早已发生多次。
典型触发路径:
→ 请求 /old/page
→ 规则 A 重写为 /new/page
→ 规则 B 又匹配 /new/page,重写回 /old/page
→ 如此往复,第 11 次时被 LimitInternalRecursion 截断
配合虚拟主机定位真实问题
看到报错后,应立刻检查该虚拟主机下的重写规则结构,重点关注:
-
终点路径未排除自身:比如重写到
/index.php,但没加RewriteCond %{REQUEST_URI} !^/index\.php$ -
正则范围重叠:如同时存在
^api/(.*)$和^(.*)$,后者会反复捕获前者输出的结果 - 缺少 [L] 标志:尤其在多条规则共存时,某条漏掉 [L],后续规则仍会执行,容易形成闭环
-
RewriteBase 设置错误:WordPress 等程序放在子目录时,
RewriteBase /bbs写成/或反过来,都会导致重写目标路径错位、反复跳转
增强可观测性的实用建议
在虚拟主机配置中启用详细重写日志,能更快锁定哪两条规则在互刷:
- Apache 2.4 推荐:
LogLevel warn rewrite:trace3(写在<virtualhost></virtualhost>块内) - 确保 ErrorLog 级别不低于
warn,避免 alert 被过滤 - 临时将
LimitInternalRecursion提到 20,方便观察完整循环链(查完务必改回默认)










