如何在 Symfony2 应用程序的控制器中执行命令并在 Twig 模板中实时打印输出
How to execute a command within a controller of a Symfony2 application and print in real-time the output in a Twig template
我需要在我的 Symfony2 应用程序的控制器中执行一个持久的命令,并 return 向用户实时输出终端。
我读过这个:
http://symfony.com/doc/current/components/process.html#getting-real-time-process-output
我不知道如何在 Twig 模板中实时打印终端输出。
编辑:
感谢 Matteo 的代码和用户的评论,最终实现是:
/**
* @Route("/genera-xxx-r", name="commission_generate_r_xxx")
* @Method({"GET"})
*/
public function generateRXXXsAction()
{
//remove time constraints if your script last very long
set_time_limit(0);
$rFolderPath = $this->container->getParameter('xxx_settings')['r_setting_folder_path'];
$script = 'R --slave -f ' . $rFolderPath . 'main.R';
$response = new StreamedResponse();
$process = new Process($script);
$response->setCallback(function() use ($process) {
$process->run(function ($type, $buffer) {
//if you don't want to render a template, please refer to the @Matteo's reply
echo $this->renderView('AppBundle:Commission:_process.html.twig',
array(
'type' => $type,
'buffer' => $buffer
));
//according to @Ilmari Karonen a flush call could fix some buffering issues
flush();
});
});
$response->setStatusCode(200);
return $response;
}
如果您需要启动一个简单的 shell 脚本并捕获输出,您可以将 StreamedResponse 与您发布的 Process
回调结合使用。
例如,假设您有一个非常简单的 bash 脚本,如下所示:
loop.sh
for i in {1..500}
do
echo "Welcome $i times"
done
您可以像这样实施您的操作:
/**
* @Route("/process", name="_processaction")
*/
public function processAction()
{
// If your script take a very long time:
// set_time_limit(0);
$script='/path-script/.../loop.sh';
$process = new Process($script);
$response->setCallback(function() use ($process) {
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
echo '<br>';
}
});
});
$response->setStatusCode(200);
return $response;
}
并且取决于缓冲区长度,您可以得到如下输出:
.....
OUT > Welcome 40 times Welcome 41 times
OUT > Welcome 42 times Welcome 43 times
OUT > Welcome 44 times Welcome 45 times
OUT > Welcome 46 times Welcome 47 times
OUT > Welcome 48 times
OUT > Welcome 49 times Welcome 50 times
OUT > Welcome 51 times Welcome 52 times
OUT > Welcome 53 times
.....
您可以使用呈现控制器将其包装在页面的一部分中,例如:
<div id="process">
{{ render(controller(
'AcmeDemoBundle:Test:processAction'
)) }}
</div>
更多信息here
希望对您有所帮助
我需要在我的 Symfony2 应用程序的控制器中执行一个持久的命令,并 return 向用户实时输出终端。
我读过这个:
http://symfony.com/doc/current/components/process.html#getting-real-time-process-output
我不知道如何在 Twig 模板中实时打印终端输出。
编辑: 感谢 Matteo 的代码和用户的评论,最终实现是:
/**
* @Route("/genera-xxx-r", name="commission_generate_r_xxx")
* @Method({"GET"})
*/
public function generateRXXXsAction()
{
//remove time constraints if your script last very long
set_time_limit(0);
$rFolderPath = $this->container->getParameter('xxx_settings')['r_setting_folder_path'];
$script = 'R --slave -f ' . $rFolderPath . 'main.R';
$response = new StreamedResponse();
$process = new Process($script);
$response->setCallback(function() use ($process) {
$process->run(function ($type, $buffer) {
//if you don't want to render a template, please refer to the @Matteo's reply
echo $this->renderView('AppBundle:Commission:_process.html.twig',
array(
'type' => $type,
'buffer' => $buffer
));
//according to @Ilmari Karonen a flush call could fix some buffering issues
flush();
});
});
$response->setStatusCode(200);
return $response;
}
如果您需要启动一个简单的 shell 脚本并捕获输出,您可以将 StreamedResponse 与您发布的 Process
回调结合使用。
例如,假设您有一个非常简单的 bash 脚本,如下所示:
loop.sh
for i in {1..500}
do
echo "Welcome $i times"
done
您可以像这样实施您的操作:
/**
* @Route("/process", name="_processaction")
*/
public function processAction()
{
// If your script take a very long time:
// set_time_limit(0);
$script='/path-script/.../loop.sh';
$process = new Process($script);
$response->setCallback(function() use ($process) {
$process->run(function ($type, $buffer) {
if (Process::ERR === $type) {
echo 'ERR > '.$buffer;
} else {
echo 'OUT > '.$buffer;
echo '<br>';
}
});
});
$response->setStatusCode(200);
return $response;
}
并且取决于缓冲区长度,您可以得到如下输出:
.....
OUT > Welcome 40 times Welcome 41 times
OUT > Welcome 42 times Welcome 43 times
OUT > Welcome 44 times Welcome 45 times
OUT > Welcome 46 times Welcome 47 times
OUT > Welcome 48 times
OUT > Welcome 49 times Welcome 50 times
OUT > Welcome 51 times Welcome 52 times
OUT > Welcome 53 times
.....
您可以使用呈现控制器将其包装在页面的一部分中,例如:
<div id="process">
{{ render(controller(
'AcmeDemoBundle:Test:processAction'
)) }}
</div>
更多信息here
希望对您有所帮助