PHP exec(),shell_exec(),system(),passthru()在Windows 7 / IIS上不起作用
我在我的开发环境中使用了Windows 7 x64 Enterprise、IIS和PHP 5.6.32。我的应用程序的网站有以下设置:
- 匿名认证:禁用
- Windows身份验证:已启用(协商,协商:Kerboeros,NTLM)
- 应用程序池:域帐户。
- 除了默认的PHP扩展名之外,我还有在Windows身份验证模式下使用的Microsoft的PHP SQL Server驱动程序(3.2版).
我的生产服务器与Server 2008 R2上运行的安装程序相同。
我需要使用 exec()
, shell_exec()
等。 执行一个可执行文件(pdftk,如果它是重要的)。然而,当我使用这些函数时,我总是得出 "Unable to fork XXX"
在PHP错误日志中。我试着运行 whoami
, ping xxx
, 以及其他具有相同结果的简单命令。 典型的shell函数均无法正常工作-它们始终会出现相同的错误。 我检查了我的php.ini
文件 并验证这些功能没有被禁用。
但是,在生产环境中,我没有发现这个问题,也不知道为什么会出现这种情况。 它似乎只影响我的开发环境。 在研究期间,我确实偶然发现了这个问题(http://tech.trailmax.info/2012/12/php-warning-shell_exec-unable-to-execute-on-iis-7/),由于某种原因, 解决了我的问题; 但是,它完全破坏了我的SQL Server Windows身份验证(我所需要的)。
我也禁用了我的防病毒软件,希望这不是罪魁祸首。
在进行更多故障排除时,我确实发现了proc_open()
起作用。我们使用Prince来生成pdf,我注意到它是运行的,而我的exec()
却没有。 当我查看Prince类时,我发现它正在使用proc_open()
这就解释了为什么它似乎是有效的。
有人知道为什么吗?exec()
并且相关功能似乎在我的生产环境中而不在我的开发环境中正常工作? 为何可以工作,但其他Shell函数却不能工作? 谢谢! proc_open()
我在开发环境中使用的是Windows 7 x64 Enterprise,IIS和PHP 5.6.32。 我的应用程序的网站具有以下设置: p>
- 匿名身份验证:已禁用 li>
- Windows身份验证:已启用(协商,协商:Kerboeros,NTLM) li>
- 应用程序池:域帐户。 li>
- 除了默认的PHP扩展,我在Windows身份验证模式下使用了Microsoft的PHP SQL Server驱动程序(3.2版本)。 li>
ul>
我的生产服务器与Server 2008 R2上运行的设置相同。 p>
我需要使用
exec() code>,
shell_exec() code>等执行可执行文件(pdftk,如果重要的话)。 但是,每当我使用这些函数中的任何一个时,我总是在PHP错误日志中得到
“Unable to fork XXX” code>。 我已经尝试运行
whoami code>,
ping xxx code>,以及其他具有相同结果的简单命令。 没有典型的shell函数可以工作 - 它们总是会导致相同的错误。 我检查了我的
php.ini code>文件,并验证了这些功能尚未被禁用。 p>
但是,在我的生产环境中,我没有 这个问题 strong>,我不知道为什么。 它似乎只影响我的开发环境。 在我的研究过程中,我偶然发现了这一点( http://tech.trailmax.info/2012/12/php-warning-shell_exec-unable-to-execute-on-iis-7/ )由于某种原因,它确实修复了 我的问题; 但是,它完全打破了我的SQL Server Windows身份验证(我需要)。 p>
我也禁用了我的防病毒软件,希望它可能是罪魁祸首。 事实并非如此。 p>
在进行更多故障排除时,我确实发现
proc_open() code>确实有效。 我们正在使用Prince生成PDF,我注意到它正在工作,而我的
exec() code>却没有。 当我查看Prince类时,我发现它使用的是
proc_open() code>,它解释了为什么它似乎有效。 p>
有谁知道为什么
exec () code>和相关的功能似乎在我的生产环境而不是我的开发环境中没有问题? 为什么
proc_open() code>工作但其他shell函数不工作? 谢谢! p> div>
I wanted to post an update to this since I figured out the issue. The answer can be found here in the very last post by 1heer2351 at zonnet dot nl1
:
Located the problem and have been able to fix it.
I am using a special user for my Application Pool (say AppPoolUser), so PHP runs as this user. The new exec function uses CreateProcessAsUser() with impersonation. This means that the AppPoolUser must have the right to change the process level token.
You can assign this right to the user in the "Local Security Settings" -> User Rights Assignment.
I have granted my AppPoolUser the "Replace a process level token" setting -> fork error has gone.
Thought this might be useful information, so access is required to cmd.exe but in addition the "Replace a process level token" setting.
This is exactly what I did. I had created a new App Pool User using my domain account. By default, the Replace a process level token
setting includes DefaultAppPool
. Since I created a new App Pool User, it was not included in this policy setting. Adding the App Pool User I created resolved my issue.
Check the permissions on file 'C:\WINDOWS\system32\cmd.exe'. You need read/execute permission on this file.
I would recommend using the sysinternals Process Monitor 'procmon.exe' to confirm the user that is trying to run 'cmd.exe'. Filter on 'Process Name' is 'php-cgi.exe' and 'Path' ends with 'cmd.exe'. Look at the event properties for the task with the access denied error, and it will show you the 'Impersonating' user name. This is usually the 'Internet Guest Account', often 'NT AUTHORITY\IUSR'.