I tried to output a simple ping mand 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 plete execution, while I needed it to display whenever it is displaying on terminal,
My code is
<?php
$i= shell_exec("ping -c 4 google");
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", '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.
I tried to output a simple ping mand 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 plete execution, while I needed it to display whenever it is displaying on terminal,
My code is
<?php
$i= shell_exec("ping -c 4 google.");
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.", '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.
- 1 shell_exec doesn't return until the mand pletes. it would not be possible for it to fire off the mand and then let execution continue on to the echo mand. you probably popen() and then fread in a loop to grab lines as they e available. – Marc B Commented Nov 27, 2013 at 17:00
- @MarcBSo that should be the way to do it ! Could you please elaborate? – user2723949 Commented Nov 27, 2013 at 17:08
- @MarcB I have edited my question, I tried the above piece of code with popen and fread, but it is also giving me the same output? Anything I have done wrong? – user2723949 Commented Nov 28, 2013 at 10:55
- That might not (only) be a problem of getting the info step-by-step, but also of outputting it to the browser – look into flushing the output buffer. This is quite a plex subject matter, as multiple factors play a role here – output buffering by PHP, possible also by the web server … and last but not least whether or not the browser wants to display partial info as soon as he receives it. – C3roe Commented Nov 28, 2013 at 11:10
- @CBroe As I mentioned in my edit, I was able to execute this php program through mand line with the desired output, But as you mentioned , it is causing problems when ing to web pages. is there any way to solve this?? – user2723949 Commented Nov 28, 2013 at 11:21
7 Answers
Reset to default 8Uhm, 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.", '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 plex 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.</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.", '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.
Use output buffering and flush
. You might also want to look into the Symfony 2 process ponent.
Its not a PHP matter, or rather its a shared matter between php and the browser.
In PHP: Make sure output buffering is off, you can do this by running ob_end_clean()
before outputting anything.
As this SO post suggests you have to either pad the very first string outputted to 512 bytes OR specify a charset encoding via http header. The padding solution may very well be the easiest way around this, its basically this: echo(str_pad("Live Ping Test!",512));
and then start echoing the result of your fread
.
You might want to try using flush() to flush the output as and when its ready, and use passthru() to execute the mand.
Carlos C Soto is right, you have to use javascript. EventSource is the way to go. Basically, it's javascript code that will constantly call a url
You can write the output of ping in a file, and write a php script that will read the last line, then call this script with eventsource.
Search "Server Sent Events" on the web to find more examples
if can resolve using apache execution user. if your root user is diffrent and server user different then it will not allow to execute mand line mand.
I tested Carlos's answer on my side...
and I HAD to add flush();ob_flush(); for it to work properly (both needed flush AND ob_flush)
like this
<?php
$proc = popen("ping -c 5 google.", 'r');
while (!feof($proc))
{
echo "[".date("i:s")."] ".fread($proc, 4096).'<br>';flush();ob_flush();
}
?>