在 Windows 上通过 UNC 路径进行 PHP exec()

在 Windows 上通过 UNC 路径进行 PHP exec()

我的环境是 Windows Server 2012 R2、IIS 8、Active Directory 和文件共享。IIS、AD 和文件共享都是独立的虚拟机。

我在 IIS 中设置了一个网站 www.example.com。应用程序池身份设置为 AD 用户IUSR_example,该用户对包含网站文件的文件夹具有“完全控制”权限。网站文件位于文件共享上,IIS 通过 UNC 路径引用该文件共享。

总体而言,该网站的工作原理是它可以提供 PHP、ASP.Net 和 ASP Classic 页面,并且代码甚至可以创建新文件。

然而,我遇到了一个似乎特定于 PHP 的问题exec()。我尝试调用whoamidirffmpeg,但它们没有返回任何内容。使用 Sysinternals Procmon,我已确认可执行文件从未启动。

奇怪的是,我能够使用 ASP Classic(使用)进行完全相同的调用,并且运行完美。当脚本未通过 UNC 路径运行时, WScript.Shell我也能够让 PHP运行。exec()

这是我尝试过/发现的:

  • 使用 ASP 时,procmon 报告 w3wp.exe 生成 cmd.exe 进程,该进程又生成 conhost.exe 和(例如)ffmpeg.exe。ffmpeg 的输出文件成功显示。
  • 使用 PHP 时,procmon 报告 w3wp.exe 生成 php-cgi.exe 进程,该进程又创建 cmd.exe 和 conhost.exe。ffmpeg.exe 的线程从未出现。
  • cmd.exe 使用如下命令行调用: cmd.exe /c ""--the command to be executed--""
  • cmd.exe 进程的命令行对于 ASP Classic 和 PHP 完全相同。
  • 在 Procmon 中,用户总是被报告为IUSR_example
  • 我尝试2>&1在命令末尾添加
  • 我尝试将 IUSR 赋予“替换进程级令牌”权限
  • 我尝试关闭 FastCGI 模拟并在“进程模型”>“高级设置”下在“NamedPipe”和“TCP”之间切换
  • PHP 错误日志中没有错误
  • Windows 事件日志中没有任何错误

请注意,这并非特定于 ffmpeg。任何其他使用exec()也会失败。此外,我宁愿不在WScript.ShellPHP 中使用,因为最终我们将使用依赖于 的 WordPress 插件exec()

我该如何进一步解决这个问题?

答案1

作为建议由用户“pajoye”在 bugs.php.net 上发布,使用proc_open()允许我成功执行命令。这反过来又允许我使用 procmon 来发现方式exec()proc_open()工作之间的差异。长话短说,当 PHP 脚本位于网络共享上时,我会将其称为在 Windows 上运行的 PHP 中的一个核心错误。以下是关键细节:

  • exec()将当前工作目录默认为 PHP 脚本的路径,在我的情况下是 UNC 路径。
  • cmd.exe不允许您将 UNC 路径作为当前工作目录,并cmd.exe声称它将恢复到 Windows 文件夹。
  • 尽管cmd.exe继续执行并conhost.exe生成,但原始工作目录仍然会导致某种问题,并且所需的可执行文件永远不会启动。

因此,一个简单的解决方法是chdir()在调用之前转到本地目录exec()。但是,有很多 WordPress 插件依赖于exec(),所以在我看来,exec()应该与 PHP 脚本是否在共享上运行无关。我会询问是否可以在未来版本中包含对此的修复。

相关内容