西西软件园多重安全检测下载网站、值得信赖的软件下载站!
软件
软件
文章
搜索

首页 → 业内动态 → 业内资讯 → IIS 上部署 PHP 的 7 个坑:应用池没设对就 502

IIS 上部署 PHP 的 7 个坑:应用池没设对就 502

相关软件相关文章发表评论 来源:本站整理时间:2026/11/5 6:50:54字体大小:A-A+

作者:xiix点击:0次评论:0次标签: IIS PHP部署 应用池 Windows服务器 502错误排查

PHP Win32v7.4.22 官方最新版
  • 类型:网页设计大小:24.8M语言:英文 评分:5.8
  • 标签:
立即下载

接了一个小活:客户有一台 Windows Server 2019,IIS 早就装好了,站点目录也拷过去了,结果访问就是 502。前同事的排查记录停在「php-cgi.exe 路径不对」,换了个路径还是 502,就没人再管了。

先说结论:在 Windows Server 上把 IIS 跑通一个 PHP 站点,难点不在点界面,而在于 IIS 的应用池、PHP 的 FastCGI 和 Windows 自己的NTFS 权限是三套互不打招呼的体系,任何一处对不上,前端就是干干净净的 502。如果你还在纠结买 Linux 还是 Windows 服务器,或者正打算先把环境搭起来试试,可以先看看这几家的配置和技术说明:bacloud(Linux / Windows VPS 与独立服务器,托管与建站一站式)

另外补一句:这篇讲的是 Windows 侧的坑,但同一个网站换到 Linux + Nginx + PHP-FPM 之后,很多问题会自动消失因为那套组合里没有应用池,也没有 NTFS 继承权限这种历史包袱。所以先想清楚自己到底需不需要 IIS,再动手改配置,能省下大把时间。对比配置的时候可以再多看一家:hosteons(服务器与主机,KVM VPS 支持 Linux / Windows,另有共享主机托管)

我花了大半天把这事从头捋了一遍,最后发现不是路径问题,也不是 PHP 没装, 而是 IIS 应用池的托管模式设成了 Integrated,PHP 却只装了 CGI 版本, 外加几个看起来像玄学、其实全是配置对不上的小问题。这篇就把这 7 个坑按我实际踩过的顺序写出来, 每一条都附上我最后是怎么定位的,方便你对着抄。

Windows Server 上的 IIS 服务器机房,PHP 站点部署 502 排查场景

坑一:应用池托管模式,和你装的 PHP 版本对不上

这是最坑的一个,也是最容易被甩锅给 PHP 的一个。IIS 的应用池有两个托管模式: Integrated(集成模式)和 Classic(经典模式)。 集成模式下,PHP 必须以 ISAPI 扩展或者 FastCGI 进程的形式接进来,由 IIS 统一调度; 经典模式则直接走老的 ISAPI 过滤器。

我这台机器上,php.ini 里写的 cgi.fix_pathinfo=1 配得好好的, php-cgi.exe 也确实存在,但应用池是集成模式,而 PHP 是按「经典模式 + CGI」装的。 结果就是:IIS 收到请求,转给 PHP,PHP 不认这个握手方式,直接把连接掐了, 浏览器看到的就是一个没有任何错误细节的 502。

定位方法很直接,看错误日志。打开 IIS 管理器 → 站点 → 右侧「日志」, 或者直接去 C:\inetpub\logs\LogFiles 找当天的日志, 搜 status code 为 502 的那几行。重点看后面的 sub-status 和 Win32-status 两个字段, 不同组合指向的原因完全不一样,不要一律当成 PHP 挂了。

我的解决办法是把托管模式改成 No Managed Code(无托管代码), 这个选项对纯 PHP 站点基本永远是对的;如果你确实要用 .NET 写应用, 那就老老实实装 ISAPI 版 PHP,或者干脆分成两个应用池,各干各的。

坑二:php-cgi.exe 路径写了绝对路径,挪个机就废

FastCGI 的配置项里要填 php-cgi.exe 的路径。最省事的写法是填绝对路径, 比如 C:\php\php-cgi.exe。然后事情就来了:换服务器、换盘符、 装到 D 盘、或者用容器镜像跑,IIS 就找不到这个文件,直接 502.5。

我现在的做法是留空,只填 php-cgi.exe 这一个文件名, 然后确保 C:\Windows\System32\inetsrv\ 之外,PHP 的 bin 目录 在系统的 PATH 环境变量里。顺带说一句,这里必须改的是系统变量, 不是用户变量IIS 的工作进程跑在 SYSTEM 账户下,用户变量对它完全不生效。 这个点我卡了将近一个小时,改完用户变量发现没效果才反应过来。

另外别忘了 IIS 自带的 FastCGI 组件要先装:控制面板 → 程序 → 打开或关闭 Windows 功能 → 勾选「Web 服务 (IIS) → Web 服务器扩展 → CGI 扩展」和「FastCGI Extension」, 装完必须重启 IIS 服务(iisreset)才生效。

IIS 应用池与 FastCGI 模块配置界面,PHP 站点部署排查示意图

坑三:站点目录的 NTFS 权限,不是 Everyone 就完事

IIS 站点跑起来之后,实际干活的应用池身份默认是 IIS AppPool\站点名, 这套账号在 Windows Server 2012 之后是虚拟账号,名字带一个随机后缀, 你在用户列表里可能根本搜不到。这也是为什么「我明明给了 Everyone 完全控制, 还是报 500.3 / 500.19」权限给错了对象。

正确的做法是:在站点根目录上右键 → 属性 → 安全 → 编辑 → 添加, 输入 IIS_IUSRS 这个组,注意是组不是某个具体账号, 给「读取和执行」「写入」「修改」三项即可;如果是纯展示型站点,连写入都可以不给。 再往下的 data、upload 这种子目录单独设,不要整棵树继承一到底。

顺带说个排查小技巧:IIS 管理器里选中站点 → 授权规则 → 打开「匿名身份验证」, 如果连应用池身份都选不到、或者提示配置错误,多半是应用程序池的加载项(.NET CLR 版本) 出了问题,回看坑一。

Windows 服务器磁盘权限与 IIS 站点目录 NTFS 权限设置图解

坑四:500.19 不是 PHP 的错,是 web.config 被锁了

配置 web.config 里的 rewrite 规则时,我遇到过满屏 500.19, 错误信息里写的是「无法读取配置节」,还有一个「此节已被锁定」的提示。 这是因为站点用的不是根目录的 web.config,而是子应用目录里的另一份, 两份配置里的 configSections 冲突了。

解决办法是让 web.config 和站点根目录用同一份配置, 不要在一个已经部署好的站点里再塞一份新的 web.config 进去。 要写 rewrite 规则,也应该用 IIS 管理器里的「URL 重写」模块, 它会把规则写进根目录那份 web.config,不会另起一份。

PHP-FPM 与 IIS 应用池 worker 进程堆积导致的站点卡顿示意图

坑五:上传 2MB 就失败,是两道限制在打架

客户后台要传图片,结果超过 2MB 直接报错。这个坑在于 IIS 和 PHP 各有一道独立的限制,你要把两道门都推开。

IIS 这一侧是 maxAllowedContentLength,单位是字节, 在 web.config 的 system.webServer 里配; PHP 这一侧是 upload_max_filesize 和 post_max_size, 在 php.ini 里配。两边不一致,就会出现「IIS 说请求体太大直接 413, 或者 PHP 说 post 超过 post_max_size 收不到 $_POST」的怪现象。 我的习惯是统一写成 20M,post_max_size 略大于 upload_max_filesize, 再留一点余量给表单其它字段。

还有第三道门:requestFiltering 里的 maxAllowedContentLength 默认也是 30MB,但如果你在 web.config 里写了重复的节点,它会以先声明的为准,报一个特别难懂的配置错误。 我一般直接搜一遍整个 web.config,把重复的节点删干净。

坑六:Session 锁文件放在网络盘上,整个站点卡成幻灯片

这个坑更隐蔽。站点看起来能访问,但每个请求都要等好几秒, 任务管理器里 php-cgi.exe 进程一堆,每个都占着 CPU。 原因是我把站点目录放在了 NAS 共享盘上,而 PHP 默认把 session 存成文件, 每个 session 一个文件,跨网络读写一遍,光延迟就够受的。

解决办法是给 PHP 配一个真正的 session handler,比如 Redis 或 Memcached, 在 php.ini 里设置 session.save_handler = redis 加上对应的扩展配置; 没有 Redis 的话,至少把 session 目录指到本机 SSD 上,别放在网盘。 顺便把 opcache 也打开,Windows 下 opcache 不像 Linux 那样默认给你配好, 得在 php.ini 里手动写 zend_extension=opcache 并确认 extension_dir 指向正确。

Windows Server 远程桌面与 IIS 站点服务化部署对比示意

坑七:远程桌面一关,站点就跟着停了

最后一个坑其实不算 IIS 的问题,但 Windows 上特别容易踩。 客户的运维习惯是登上远程桌面,跑一个批处理,然后直接关窗口, 结果跑在用户会话里的站点进程也跟着被回收了,第二天早上来一看网站全没了。

在 Linux 上用 nohup 或者 systemd 可以绕开这个问题, Windows 上对应的做法是把站点注册成 Windows 服务, 或者干脆用「任务计划程序」配置成「不管用户是否登录都要运行」, 触发器设成系统启动时。我更推荐前者,用 NSSM 这类工具把 php-cgi 挂成服务, 再让 IIS 通过 FastCGI 连过去,这样服务生命周期就和远程桌面彻底解耦了。

顺便提一句,如果你只打算跑一个纯 PHP 站点、也没有 .NET 代码, 认真考虑一下用 Windows + IIS 这条路值不值:应用池、NTFS 权限、 FastCGI 这三层的配置复杂度,比 Linux + Nginx + PHP-FPM 高出不少, 而且可选的运维工具链也少。如果业务确实依赖 ASP.NET, 或者团队里只有 Windows 开发环境,那再往下看。

最后说说我的排查顺序

这次折腾下来,我把这套流程固定下来了,下次再遇到 502 就按这个顺序走一遍, 基本不会超过半小时:

第一,看 IIS 日志里的 sub-status 和 Win32-status,先确定是 IIS 层还是 PHP 层的问题; 第二,确认应用池托管模式是 No Managed Code; 第三,确认 FastCGI 路径和 PATH 系统变量; 第四,确认站点目录的 NTFS 权限给到了 IIS_IUSRS; 第五,把 session 和 opcache 从网络盘挪到本地。

五步里最容易被跳过的其实是第一步大部分人一上来就去改 PHP 配置, 在 IIS 层的问题上耗掉半天。日志里那行小字,其实已经把答案写出来了。

    php开发工具
    (26)php开发工具
    php开发工具可谓一份php资源宝库,应有尽有,非常齐全,大家可以用来开发动态网站程序,或者一些相关服务器软件编写。php开发工具:集成开发环境是一种集成了软件开发过程中所需主要工具的集成开发环境,其功能包括但不仅限于代码高亮、代码补全、调试、构建、版本控制等。一些常见的PHPIDEs如下:ZendStudio:商业版,Zend官方出品,基于eclipseEclipsewithPDT:免费Coda:商业版,针对Mac用户NetBeans:免费,功能强大PHPStorm:...更多>>

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶顶
    • 1 难过难过
    • 5 囧囧
    • 3 围观围观
    • 2 无聊无聊

    发表评论

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲