PHP exec(psexec.exe)无限期挂起

时间:2013-02-03 01:11:39

标签: php exec psexec

我在Windows机器上有一个开发/测试设置,需要测试调用后台进程。我使用http://www.somacon.com/p395.php作为运行后台服务的选项列表。

以下是我尝试运行的示例代码:

$string = "PsExec.exe -d cmd /c \"mspaint\"";
echo $string;
exec($string, $data);

当我在命令行中键入它时,这是有效的。

我还没有尝试在Windows上做过很多操作,但是在移动到Linux机器之前能够在本地测试它会很不错。

现在,我认为它与psexec打开一个新窗口的事实有关?但是,我不知道如何解决这个问题。

没有生成apache或PHP错误日志,页面永远不会停止。这似乎也超越了PHP的最大执行时间。

6 个答案:

答案 0 :(得分:1)

编辑:

这不是完全正确的答案。命令psexec \\machine cmd.exe /C 1 & dir不会挂起,因为psexec首先返回说远程计算机中不存在命令1,然后在本地计算机中评估dir。我被cmd操作员命令欺骗了。正在本地&进程中调用cmd.exe运算符,而不是远程运算符。但是,如果引用命令psexec \\machine cmd.exe /C "1 & dir"

,逻辑仍然适用

原始答案:

在Windows中调用PHP中的psexec时会发生一些奇怪的事情。无论您使用的是shell_exec()exec()popen()还是proc_open()。无论如何它都会挂起。

老实说,我不知道发生了什么,你也可以下载PsExplorer来跟踪你的进程命令行,参数等。你会发现这个工具非常有用。

我在Windows上使用XAMPP,经过一定的测试后我发现了这个:

首先创建一个测试文件(即test.php)并将其放在您的网络服务器中,以便您可以使用此内容访问它:

   <?php
      echo "<pre>".shell_exec("psexec \\\\machine <options> cmd.exe /C dir")."</pre>";
   ?>

请注意,您可以使用GET参数来创建更灵活的示例。要在测试网页之前确认这确实有效,请发出命令php <path-to-the-file>\test.php。这将完美地运作。但是,它不适用于网络浏览器。

如果您终止了该过程,您将获得第一行:El volumen de la unidad C no tiene etiqueta.。下一行,在我的语言中有一个重音包括所以我认为它可能是编码(或代码页)问题。因此我测试cmd.exe /C dir而不是cmd.exe /C chcp 850 && dir。令我惊讶的是,这是有效的。

然后,我意识到无论你在它之前设置什么命令也会工作,例如,cmd.exe /C 123 & dir(注意单&,因为我没有评估命令输出)。

老实说,我不知道psexec和PHP通过网络浏览器发生了什么。更令人惊讶的是,像cmd.exe /C copy cmd.exe cmd.exe.deletemecmd.exe /C mkdir deletethis这样的命令会起作用!

所以,你可以试试cmd.exe /C 1 & \"mspaint\"作为你的问题,而我似乎是同样的。对于单个命令可能是一种解决方法,但我正在开发一个无人值守的框架来安装软件,我的所有文件都是.cmd.exe.bat个文件。

让我知道如果你发现了一些有趣的东西:)

答案 1 :(得分:0)

我目前的解决方案是使用WScript.Shell:

$string = "cmd /c \"cd {$full_base}{$newSource} && ant release > compile.txt\"";
$Shell = new COM("WScript.Shell"); 
$exec = $Shell->Run($string, 0, false);

答案 2 :(得分:0)

不确定这是否得到了明确的回答,但我遇到了与PSEXEC悬挂相同的问题,不过在我的情况下,它在某些机器上做了,而其他机器没有。原来是接受了EULA。在我从命令行运行它的机器上,使用与我的PHP脚本相同的用户名/密码,它在没有挂起的情况下运行。

进一步的研究表明,我可以通过将其包含在从PHP执行的命令中来指定EULA接受度:

此DID挂起:psexec \\MACHINENAME ...

这不是: psexec /accepteula \\MACHINENAME ...

答案 3 :(得分:0)

好的,这就是事情。我也像你一样跳进了类似的状态,希望因为我这么晚才发表评论你一定也想出了办法。但是对于那些仍然存在这个问题的人,我建议他们提供一些技巧。
1)已发布的代码非常精细,没有问题。如果你的页面无限挂起,那么尝试在源exe之前添加-i -d params。 (参见文档HERE )。您还可以在命令中添加-accepteula(EULA)标志以使页面加载而不是等待该命令完成(解决无限等待问题)。
2)对我来说,这些东西都没用。它并不意味着你们不尝试这些东西。如果你的代码开始工作,那么这是第一步,那对你来说很好。删除,另一个帐户作为管理员,输入 services.msc 开始菜单,你会看到那里的页面。搜索wampapache或xammp服务,不包括mysqld one。然后只需点击该服务.GO到登录标签,选择此帐户。选择以前制作的管理员帐户,如果设置了其他文件,请输入密码。在名称字段中将该帐户的名称键入\\ accname。如果您不知道帐户名称,请单击浏览 - > 高级 - &gt; 立即支付,您将看到该名称帐户。选择,应用设置并重新启动wamp应用程序,你就可以了:)

答案 4 :(得分:0)

另外,请务必仔细检查您输入exec命令的字符串。看起来微不足道,但让我难过了一会儿。在许多情况下,PHP会逃避机器地址中的双反斜杠,从而导致所有内容丢失。要解决此问题,请创建如下字符串:

$string = 'PSExec /accepteula \\\\MACHINENAME ...'

答案 5 :(得分:0)

我有一个解决方案!

此主题已陈旧但仍然相关。我想使用PsExec 2.2和PHP 7.2.0 RC3远程执行脚本。我需要脚本的输出,因此我使用PsExec.exe -accepteula \\HOST -u xxx -p xxx>> LOGFILE 2>&1

因为我不想等待脚本完成,所以我使用exec()这样:exec('start /p cmd /c PsExec.exe -accepteula \\HOST -u xxx -p xxx >> LOGFILE 2>&1')。 我的php脚本继续工作,PsExec也完成了他的工作。

一切正常但我的LOGFILE始终只包含STDOUT输出的第一行

我尝试了很多这里提到的解决方案,但没有一个能为我工作。直接在CMD中执行命令,PsExec返回STDOUT的所有行,但在PHP内部则不返回。

exec()的php文档中,我发现了一些注释,其中有些人使用PsExec运行程序而无需等待(http://php.net/manual/de/function.exec.php#86438)。作为最后一次机会,我尝试了以下方法:exec('PsExec.exe -accepteula -i -d cmd /c PsExec.exe -accepteula \\HOST -u xxx -p xxx >> LOGFILE 2>&1') ......它有效!

PsExec现在返回到我的LOGFILE。我希望我可以帮助你并节省你一些时间。