游客发表
服务器突然报错,错误HTTP 错误 500.21,错误Internal Server Error。错误事件查看器里躺着一条刺眼的错误记录:IIS Web Core,模块ManagedPipelineHandler,错误错误代码0x80070021。错误别慌,错误这八成是错误PHP和IIS的集成管道权限没对上。
很多人以为装好PHP、错误配好处理程序映射就完事了。错误真不是错误。IIS从7.0开始引入了集成模式,错误所有请求都走同一个管道。错误PHP作为FastCGI模块挂进去,错误如果应用程序池的错误“启用32位应用程序”设置不对,或者托管管道模式设成了“经典”,立马给你脸色看。我上次帮朋友排查,他网站后台能开,前台静态页正常,一到PHP动态页面就500.21。查了半天,发现他在IIS管理器里把应用程序池的托管管道模式改成了“经典”。改成“集成”后,问题瞬间消失。就这么简单,但不知道的人能折腾一整天。
还有个常见坑:applicationHost.config 里的globalModules节点顺序。如果你手动添加过FastCGI模块,或者服务器上同时装了多个PHP版本,模块加载顺序错乱也会触发这个错误。具体表现是,错误日志里除了0x80070021,还会伴随模块列表里出现两个CgiModule条目。这时候别急着改代码,先打开%windir%\system32\inetsrv\config\applicationHost.config,搜索FastCgiModule,确保它只出现一次,且位于RewriteModule之前。
权限问题也常被忽略。PHP需要读取站点目录,但IIS进程账户(默认是IUSR或应用程序池身份)如果没有“读取和执行”权限,一样报这个错。我之前遇到过一个案例,站点文件放在D盘,但D盘的NTFS权限只给了管理员组。IIS进程跑起来后根本没权限访问PHP文件。给IUSR加上读取权限,问题解决。这类错误很隐蔽,因为静态文件可能因为IIS的匿名认证缓存而正常显示,但PHP每次都要重新读取文件,权限不足直接暴露。
再往深处说,web.config 里的system.webServer节点配置错误也会触发。比如你复制了别人网站的web.config,里面包含节点,但没包含节点的完整定义。IIS加载时发现处理程序映射和模块列表不匹配,直接拒绝启动管道。检查方法很简单:用记事本打开web.config,看看下是否有。没有的话加一行,很多兼容性问题能直接跳过。
最后说个冷门的:如果你用的是PHP 7.4以上版本,并且开启了opcache,偶尔会因为opcache的validate_timestamps设置导致文件更新后管道缓存错乱。表现为修改PHP文件后刷新页面,偶尔出现500.21,过几分钟又自己好了。把opcache.validate_timestamps=1和opcache.revalidate_freq=0设上,基本能杜绝。我见过有人因为这个把服务器重启了十几次,最后发现是opcache的锅。
排查顺序建议:先看应用程序池的管道模式和32位设置,再看applicationHost.config的模块顺序,然后查NTFS权限,最后翻web.config。八成问题出在前两步。别一上来就重装PHP或IIS,那是最笨的办法。用%windir%\system32\inetsrv\appcmd.exe list config命令快速导出当前配置,对比正常服务器的差异,往往一眼就能看出毛病。
友情链接