PHP exec()、shell_exec()、system()、passthru() 在 Windows 7/IIS 上不起作用

PHP exec(), shell_exec(), system(), passthru() do not work on Windows 7/IIS

我在我的开发环境中使用 Windows 7 x64 Enterprise、IIS 和 PHP 5.6.32。我的应用程序的网站具有以下设置:

我的生产服务器与 Server 2008 R2 上的 运行 设置相同。

我需要使用 exec()shell_exec() 等来执行可执行文件(pdftk,如果重要的话)。但是,每当我使用这些函数中的任何一个时,我总是在 PHP 错误日志中得到 "Unable to fork XXX"。我已经尝试运行 whoamiping xxx 和其他具有相同结果的简单命令。 None 的典型 shell 函数将起作用——它们总是导致相同的错误。我检查了我的 php.ini 文件并确认这些功能没有被禁用。

然而,在我的生产环境中,我没有这个问题,我也不知道为什么。它似乎只影响我的开发环境。在我的研究过程中,我确实偶然发现了这个 (http://tech.trailmax.info/2012/12/php-warning-shell_exec-unable-to-execute-on-iis-7/),出于某种原因,它确实解决了我的问题;但是,它完全破坏了我的 SQL 服务器 Windows 身份验证(我需要)。

我也禁用了我的防病毒软件,希望它是罪魁祸首。不是。

在进行更多故障排除时,我确实发现 proc_open() 确实有效。我们正在使用 Prince 生成 PDF,我注意到它可以正常工作,而我的 exec() 却没有。当我查看 Prince class 时,我发现它正在使用 proc_open(),这解释了为什么它似乎有效。

有谁知道为什么 exec() 和相关功能在我的生产环境而不是我的开发环境中似乎没有问题?为什么 proc_open() 起作用而其他 shell 函数不起作用?谢谢!

检查文件 'C:\WINDOWS\system32\cmd.exe' 的权限。 您需要对此文件的 read/execute 权限。

我建议使用 sysinternals Process Monitor 'procmon.exe' 来确认正在尝试 运行 'cmd.exe' 的用户。 'Process Name' 上的过滤器是 'php-cgi.exe','Path' 以 'cmd.exe' 结尾。查看具有拒绝访问错误的任务的事件属性,它会显示 'Impersonating' 用户名。这通常是'Internet Guest Account',通常是'NT AUTHORITY\IUSR'。

我想 post 对此进行更新,因为我发现了这个问题。答案可以在最后 post 中找到 here 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.

这正是我所做的。我使用我的域帐户创建了一个新的应用程序池用户。默认情况下,Replace a process level token 设置包括 DefaultAppPool。由于我创建了一个新的应用程序池用户,因此它未包含在此策略设置中。添加我创建的应用程序池用户解决了我的问题。