【发布时间】:2014-02-01 17:30:15
【问题描述】:
我正在尝试使用 PHP(当前为 5.3.24,但很快将是最新版本)在 Windows 上创建一个浏览器启动的自调用/重复 PHP 脚本。它将作为一个守护进程来监视数据库中的更改(每隔几秒钟,因此 cron/schedule 已失效),然后在发现更改时调用其他 PHP 脚本来执行工作。出于这个问题的目的,请忽略这样一个事实,即我最好用 C# 或其他语言来做这件事:)
为了简单起见,我开始尝试使用 popen 在后台运行第二个 PHP 脚本...
// BatchMonitor.php
SaveToMonitorTable(1); // save 1st test entry to see if the script reached this point
$Command = '"" "C:\Program Files (x86)\PHP\v5.3\php.exe" C:\inetpub\wwwroot\Test.php --Instance=' . $Data->Instance;
pclose(popen("start /B $Command", "r"));
SaveToMonitorTable(2); // save 2nd test entry to see if the script reached this point
exit();
// Test.php
SaveToTestTable(1);
Sleep(10);
SaveToTestTable(2);
exit();
如果我在浏览器中运行 BatchMonitor.php,它可以正常工作。不出所料,它会将1保存到监视器表中,调用Test.php将1保存到测试表中,原来的BatchMonitor.php将继续运行而不等待响应并在退出之前将2保存到监视器表中,然后10秒后测试页在退出前将 2 保存到测试表中。第二个脚本启动正常,第一个脚本不等待回复,所有参数在脚本之间正确传递。随着一切按预期工作,然后我通过调用自身(有延迟)而不是另一个脚本来更改系统以作为重复循环工作......
// BatchMonitor.php
SaveToMonitorTable(1); // save 1st test entry to see if the script reached this point
$Command = '"" "C:\Program Files (x86)\PHP\v5.3\php.exe" C:\inetpub\wwwroot\BatchMonitor.php --Instance=' . $Data->Instance;
pclose(popen("start /B $Command", "r"));
SaveToMonitorTable(2); // save 2nd test entry to see if the script reached this point
exit();
如果我在浏览器中运行 BatchMonitor.php,它会运行一次,仅此而已。它将 1 保存到数据库,等待 10 秒,然后在退出之前将 2 保存到数据库。页面成功返回,没有脚本或 PHP 错误,但没有按应有的方式重复。
BatchMonitor.php 和 Test.php 都使用逐行相同的函数来获取参数,并且两个文件在第一次迭代时运行正确且相同。如果我使用 exec 而不是 popen ,那么页面会正确循环,所有逻辑都按预期工作(一个明显的缺陷是创建一个永无止境的脚本链,等待永远不会出现的响应值)。
我是否遗漏了一些明显的东西? popen 是否有某种秘密规则可以防止页面/进程打开自身的副本?有没有使用 popen 或 exec 的替代方法?我阅读了有关 WScript.Shell 的信息,但可能需要一段时间才能安排启用它,所以现在它不是一个选项,我希望有更标准的东西可以使用。
【问题讨论】:
-
您是否尝试过记录 popen 返回的内容?还是关闭?我还建议您检查更改的命令上的文件路径是否正确。 BackMonitor 和 Test.php 的权限完全相同
-
popen 返回“Resource id #1”,pclose 返回 0。当我调用 Test.php 时也是如此,它工作正常。 PHP和脚本的文件路径都经过验证,权限相同。