我想要执行一个大型的数据库密集型脚本,但不需要等待该过程完成。我只想调用脚本,让它在后台运行,然后重定向到另一个页面。
编辑: 我正在使用Windows 7上的本地Zend社区服务器。 我可以访问项目所在的远程linux服务器,所以我可以在linux或windows上执行此操作。
我有这个
public function createInstanceAction()
{
//calls a seperate php process which creates the instance
exec('php -f /path/to/file/createInstance.php');
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Instance creation process started. This may take up to a few minutes.'));
$this->_redirect('instances/adminhtml_instances/');
return;
}
这完美无缺,但是magento应用程序会挂起以完成整个过程。它做我所期望的一切,不时记录到文件,并对它的运行方式感到满意。现在我想做的就是让这个脚本启动,控制器动作不会挂起,而是重定向,那就是那个。根据我对exec()的了解,你可以通过改变我上面调用exec()的方式来实现:
exec('php -f /path/to/file/createInstance.php > /dev/null 2>&1 &');
我从here
获取的如果我添加“> / dev / null 2>& 1&”对于exec调用,它不会按预期等待,但它不再执行脚本。有人可以告诉我为什么,如果是的话,请告诉我如何让这个工作起来好吗?
这可能是与许可相关的问题吗?
感谢
编辑:我假设如果我用(/ dev / null 2>& 1&)调用exec函数将任何输出记录到文件将是一个问题,因为这会取消它。那是对的吗?
答案 0 :(得分:2)
在花时间充分了解我自己的问题及其解决方法之后,我已经准备好了我的解决方案。
感谢所有人提出的建议,并在提出问题时放弃了我的随意和毫无准备。
上述问题的答案取决于许多因素,例如您所指的操作系统,您正在运行的php模块,甚至是您正在运行的Web服务器。所以,如果我不得不再次提出这个问题,那么我要做的第一件事就是陈述我的设置。
我想在两种环境中实现这一目标:
1。)运行Zend服务器社区版的Windows 7。 2.)Linux(我的操作系统是Linux odysseus 2.6.32-5-xen-amd64#1 SMP Fri Sep 9 22:23:19 UTC 2011 x86_64)
要做到这一点,我希望它在部署到Windows或Linux时以任何方式工作,所以我使用php来确定操作系统是什么。
public function createInstanceAction()
{
//determines what operating system is Being used
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
{
//This is a windows server
//call a seperate php process to run independently from the broswer action
pclose(popen("start php /path/to/script/script.php","r"));
}
else
{
//assuming its linux, but in fact it simply means its not windows
// to check for linux specifically use (strtoupper(substr(PHP_OS, 0, 3)) === 'LIN')
exec('php -f /path/to/file/script.php >/dev/null 2>&1 &');
}
//the browser will not hang around for this process to complete, and you can contimue with whatever actions you want.
//myscript log any out put so i can capture info as it runs
}
简而言之,一旦你理解了问题就提出问题。有很多方法可以实现上述目标,这只是一个适用于我的开发和生产环境的解决方案。
感谢所有人的帮助。
答案 1 :(得分:1)
从文档中(这应该可以帮助你做其他事情,而这个过程正在运行;不确定关闭当前的PHP进程是否会终止打开的进程):
/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
解决方案2: 欺骗浏览器关闭连接(假设涉及浏览器):
ob_start();
?><html><!--example html body--></html><?php
$strContents=ob_get_clean();
header("Connection: Close");
header("Content-encoding: none");//doesn't work without this, I don't know why:(
ignore_user_abort(true);
header("Content-type: text/html");
header("Content-Length: ".strlen($strContents));
echo $strContents;
flush();
//at this point a real browser would close the connection and finish rendering;
//crappy http clients like some curl implementations (and not only) would wait for the server to close the connection, then finish rendering/serving results...:(
//TODO: add long running operations here, exec, or whatever you have.
答案 2 :(得分:1)
您可以编写一个包装脚本,比如说createInstance.sh
#! /bin/bash
trap "" SIGHUP
php -f "$1" > logfile.txt 2>&1 &
然后从PHP中调用脚本:
exec('bash "/path/to/file/createInstance.sh"');
应该从脚本中立即分离新的php进程。如果这没有帮助,你可能会尝试使用SIGABRT,SIGTERM或SIGINT而不是SIGHUP,我不知道确切地发送了哪个信号。
答案 3 :(得分:1)
我已经能够使用:
shell_exec("nohup $command > /dev/null & echo $!")
$command
例如:
php script.php --parameter 1
我注意到了一些奇怪的行为。例如,运行mysql
命令行不起作用,只有php脚本似乎可以工作。
此外,运行cd /path/to/dir && php nohup $command ...
也不起作用,我必须在PHP脚本中chdir()
,然后运行命令使其工作。
答案 4 :(得分:0)
Zend Server附带的PHP可执行文件似乎是导致尝试在后台运行脚本(使用exec中的&符号和运算符)失败的原因。
我们使用我们的标准PHP可执行文件测试了它,它工作正常。这与Zend Server附带的版本有关,虽然我们有限的尝试弄清楚发生了什么并没有改变任何东西。