简单来讲,就是我编写了一段代码 exec('dir'),php会报错,提示 Unable to fork [dir] ,而且exec函数第三个参数返回值为-1。为了解决这个问题,我作了大量搜索,花了几乎一整的时间,尝试了网上提到的各类办法,最终问题得以解决,不过仍是有不少不太清楚的地方,本文只是记录一下心得。php
个人环境
Windows Server 2012 R2, IIS-8.5, PHP-5.6.28windows
问题查找顺序
1. 肯定:检查php.ini的disable_functions是否包含了exec
2. 肯定:C:\Windows\System32\ 路径被加入到环境变量中
2. IIS默认会创建一个IIS_IUSRS组,还有一个默认用户叫IUSR
3. php官网提到,exec函数会先打开cmd.exe,所以网上有帖子说须要让用户"IUSR"有执行cmd.exe的权限,我不肯定是否是必定要这样作
4. C:\Windows\System32 以及 C:\Windows\SysWOW64 都有cmd.exe,还不太明白这2个的区别。
5. 貌似环境变量里有一个变量叫 ComSpec,指向了 C:\Windows\System32
6. 微软官方提供了一个工具Procmon.exe,大概能够监视一些东西。
https://docs.microsoft.com/en-us/sysinternals/
https://live.sysinternals.com/
最终监视出来的结果,貌似是php-cgi.exe建立了一个进程cmd.exe,而后执行dir命令,不过cmd.exe的完整路径为何是 C:\Windows\SysWOW64\cmd.exe
7. IIS好像有多处地方能够修改user
1. 应用程序池(Application Pools)-> 高级设置(Advacned Settings) -> 标识(Identity)
2. 网站(Sites) -> 身份认证(Authentication) -> 匿名身份认证(Anonymous Authentication) -> 编辑(Edit)
3. 网站(Sites) -> 高级设置(Advacned Settings) -> 物理路径凭据(Physical Path Credentials)
8. 使用 get_current_user 函数能够获取到当前php究竟是以哪一个用户在运行
9. Windows任意文件或者目录下,查看指定用户的权限
右键 -> 属性 -> 安全 -> 高级 -> 有效访问 -> 选择用户 -> "输入用户名,点检查名称,肯定" -> 查看有效访问
以上是不少人提到的有多是权限不足形成的问题,各类测试下来,我发现并非权限形成的,继续又查了好多资料!
10. 打开IIS首页 -> FastCGI Settings -> Edit -> Advacned Settings.Protocol由NamedPipe改成TCP,问题解决!
11. 继续查资料,为何NamedPipe不行,其实我也不懂这玩意。大概就是fascgi和其余应用程序通讯的方式,由于我在第7点处都指定了网络用户,致使了在建立pipe时(可能就是第6点提到的),权限不足引发的。
12. 最终解决方案:FastCGI Protocol继续保持NamedPipe(由于网上说windows下这种协议更快),第7点提到的3处分别为
1. 指定网络用户,不过在IIS_IUSRS组里
2. 使用应用程序池标识(Application pool identity)
3. 留空白,应用程序用户(经过身份认证)(Application user(pass-through authentication))
13. 关于NamedPipe的资料
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365600(v=vs.85).aspx
https://stackoverflow.com/questions/4098549/minimum-os-permissions-required-to-create-named-pipe-wcf
https://serverfault.com/questions/247064/permission-needed-for-named-pipes-on-windows-2008
https://stackoverflow.com/questions/21115821/what-is-fcgi-x-pipe-in-the-php-superglobal-array-and-what-is-it-used-for安全