Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: Outputting the system / Shell_exec command output in web browser

Tags:

javascript

php


I tried to output a simple ping command on a web page in a similar way( and same time) as it is displaying in terminal, using shell_exec; But it is displaying only after the complete execution, while I needed it to display whenever it is displaying on terminal,

My code is

<?php
$i= shell_exec("ping -c 4 google.com");
echo "<pre> $i <pre>";
?>

It is waiting for a while and the dumping the whole thing on a single shot.. can PHP recognize the outputting of each line and display it on the web page

EDIT
I tried this also

    <?php
    $proc = popen("ping -c 4 google.com", 'r');
    echo '<pre>';
    while (!feof($proc)) {
        echo fread($proc, 4096);
    }
    echo '</pre>';
    ?>

But still I gets the same result..

EDIT
When I tried to execute this PHP code in terminal , ( php test.php) it is working properly in the same way it gives when we directly do ping on server. but in web page it is still the same.

like image 216
user2723949 Avatar asked Nov 27 '13 16:11

user2723949


People also ask

What is shell_exec function in PHP?

The shell_exec() function is an inbuilt function in PHP which is used to execute the commands via shell and return the complete output as a string. The shell_exec is an alias for the backtick operator, for those used to *nix. If the command fails return NULL and the values are not reliable for error checking.

Can PHP run shell command?

The PHP functions to execute shell command are: shell_exec(), exec() or system(). These functions are remarkably similar but have slight differences.

How do I run a PHP script in Linux?

You can execute linux commands within a php script - all you have to do is put the command line in brackits (`). And also concentrate on exec() , this and shell_exec() ..

What is shell exec?

The exec command is a powerful tool for manipulating file-descriptors (FD), creating output and error logging within scripts with a minimal change. In Linux, by default, file descriptor 0 is stdin (the standard input), 1 is stdout (the standard output), and 2 is stderr (the standard error).


2 Answers

Uhm, strange behavior from the web browser. I'm using this code:

<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);

function pingtest()
{
    $proc = popen("ping -c 5 google.com", 'r');
    while (!feof($proc))
    {
        echo "[".date("i:s")."] ".fread($proc, 4096);
    }
}

?>
<!DOCTYPE html>
<html>
<body>
  <pre>
Immediate output: 
<?php
pingtest();
?>
  </pre>
</body>
</html>

In the browser the content appears after all bytes has been received. But, the content is actually delivered on time, do this test:

wget -O - -q "http://localhost/ping.php"

You will see that the response is delivered by php & apache2 on time.

I'm using this kind of execution on long task for a while, but using a more complex solution:

  • an html file for interface
  • a php file that run the long task
  • Connect html interface with php long execution using EventSource object (available on html5)

interface (test.html)

<!DOCTYPE html>
<html>
<head>
    <title>Simple EventSource example</title>
</head>
<body>
    <script type="text/javascript">
    function eventsourcetest() {
        var ta = document.getElementById('output');
        var source = new EventSource('test.php');
        source.addEventListener('message', function(e) {
            if (e.data !== '') {
               ta.value += e.data + '\n';
            }
        }, false);
        source.addEventListener('error', function(e) {
            source.close();
        }, false);
    }
    </script>
    <p>Output:<br/><textarea id="output" style="width: 80%; height: 25em;"></textarea></p>
    <p><button type="button" onclick="eventsourcetest();">ping google.com</button>
</html>

Server Side Component (test.php)

<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

function echoEvent($datatext) {
    echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
}

echoEvent("Start!");
$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc)) {
    echoEvent(fread($proc, 4096));
}
echoEvent("Finish!");

Put both files in one place on a webserver and enter test.html, I think this is what you are looking for from the beginning.

like image 163
Carlos C Soto Avatar answered Oct 14 '22 09:10

Carlos C Soto


Use output buffering and flush. You might also want to look into the Symfony 2 process component.

like image 26
max Avatar answered Oct 14 '22 10:10

max