Мне нужно выполнить долговременную команду в контроллере моего приложения Symfony2 и вернуть пользователю в режиме реального времени вывод терминала.
Я прочитал:
http://symfony.com/doc/current/components/process.html#getting-real-time-process-output
Я не могу понять, как печатать в режиме реального времени вывод терминала в шаблоне Twig.
EDIT: Благодаря коду 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; }
Если вам нужно запустить простой сценарий оболочки и захватить вывод, вы можете использовать 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>
Больше информации здесь
Надеюсь, что эта помощь