0

I have a bash script that is execute in a function in a laravel Controller and I want to output the echos from within while the script is being executed. I tried this way but it does not work, it shows everything togheter after the script is executed.

This is the controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use File;
use Process;
use ProcessFailedException;

class DeployController extends Controller
{
    //
    public function execute_bash(command)
    {
        flush();
        $fp = popen(command, "r");
        while(!feof($fp))
        {
            // send the current file part to the browser
            print fread($fp, 1024);
            // flush the content to the browser
            flush();
        }
        fclose($fp);

    }

I do that with ajax

$.ajax({
        data:  parameters,
        url:   '/executeBash',
        type:  'get',
        beforeSend: function(){
            console.log("executing...");
        },
        success:  function(response){
            console.log("success: %O", response);
        },
        error:  function(response){
            console.log("error: %O", response);
        }
    });

This is my Route sentence in web.php Laravel route file called by the ajax function

Route::get('/executeBash', 'DeployController@execute_bash');

command parameter in execute_bash function is a path to the .sh script that inside do some stuff and for any stuff it do, it print an output with echo.

Now, the .sh script is being executed right, but all the outputs (echo) is showed after it finish

How can I achieve wath I want? Thanks!

alfreedom
  • 447
  • 5
  • 15
  • Can you elaborate a little bit more...for example, can you add a command sample, and the output of your success callback? – Hackerman Dec 09 '16 at 18:33
  • @Hackerman I edited the post! – alfreedom Dec 09 '16 at 18:41
  • Now I get it; you want to show the output of your script in like, real time scenario...right now the output data get displayed once the script finished running right? – Hackerman Dec 09 '16 at 18:45
  • Now I get it; you want to show the output of your script in like, real time scenario...right now the output data get displayed once the script finished running right? – Hackerman Dec 09 '16 at 18:45
  • Yes @Hackerman! Sorry for my poor english! – alfreedom Dec 09 '16 at 18:47
  • No problem man, I am from Chile, so mine's is not that good either...the short answer is that you can't do that...a good explanation here: http://stackoverflow.com/questions/15988369/how-get-the-output-from-process-opend-by-popen-in-php – Hackerman Dec 09 '16 at 19:00

1 Answers1

1

Ok, I achieved this with XHR methos by doing the following:

this is my new ajax function (XHR method)

function executeBash(){

    if (!window.XMLHttpRequest){
        alert("Your browser does not support the native XMLHttpRequest object.");
        return;
    }
    try{
        var xhr = new XMLHttpRequest();
        xhr.previous_text = '';

        xhr.onerror = function() {
            alert("[XHR] Fatal Error.");
        };
        xhr.onreadystatechange = function() {
            try{
                if (xhr.readyState == 4){
                    //alert('[XHR] Done')
                    document.getElementById("timeline").innerHTML += 'Done' + '';
                }
                else if (xhr.readyState > 2){
                    console.warn(xhr.responseText);
                    var new_response = xhr.responseText.substring(xhr.previous_text.length);
                    document.getElementById("timeline").innerHTML += new_response + '';
                    xhr.previous_text = xhr.responseText;
                }
            }
            catch (e){
                alert("[XHR STATECHANGE] Exception: " + e);
            }
        };
        xhr.open("GET", "/executeBash", true);
        xhr.send();
    }
    catch (e){
        alert("[XHR REQUEST] Exception: " + e);
    }

}

And this is the new function in my Laravel Controller

public function execute_bash(command)
    {
        header("Connection: Keep-alive");

        $fp = popen(command, "r");
        while($b = fgets($fp, 2048)) {
            echo $b."<br>";
            flush();
        }

        pclose($fp);
    }

It works just great!

I arrived to the solution by reading this post

http://stratosprovatopoulos.com/web-development/php/ajax-progress-php-script-without-polling/

And this answer

http://www.webhostingtalk.com/showthread.php?t=579738&p=4333537#post4333537

I hope it helps!

alfreedom
  • 447
  • 5
  • 15