0

I do have a strange problem. I'm trying to get around output buffering in PHP to run system() calls and get instant output. It works very well, but for some strange reason, the ping command on "test.de" isn't presenting instant output as the ping on google.de does. I do see the first line for 'ping test.de' in the linux shell instantly, but it doesn't appear instantly with this script. Anyone can help?

<?php

  // Turn off output buffering
  ini_set('output_buffering', 'off');
  // Turn off PHP output compression
  ini_set('zlib.output_compression', false);
  // Implicitly flush the buffer(s)
  ini_set('implicit_flush', true);
  ob_implicit_flush(true);
  // Clear, and turn off output buffering
  while (ob_get_level() > 0) {
      // Get the curent level
      $level = ob_get_level();
      // End the buffering
      ob_end_clean();
      // If the current level has not changed, abort
      if (ob_get_level() == $level) break;
  }
  // Disable apache output buffering/compression
  if (function_exists('apache_setenv')) {
      apache_setenv('no-gzip', '1');
      apache_setenv('dont-vary', '1');
  }

  header('Cache-Control: no-cache');

  $i=0;
  while( $i < 1000 ) {
    $i++;
    echo '                        ';
  }
  echo '<pre>';
  echo "Pinging google.de \n\n";
  passthru("ping -w 10 -c 4 google.de");
  echo "\n\nPinging test.de \n\n";
  passthru("ping -w 10 -c 4 test.de");
  echo '</pre>';
?>

I've marked the delayed line in this output:

Pinging google.de 

PING google.de (172.217.16.131) 56(84) bytes of data.
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=1 ttl=56 time=22.0 ms
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=2 ttl=56 time=22.0 ms
64 bytes from zrh04s06-in-f131.1e100.net (172.217.16.131): icmp_seq=3 ttl=56 time=22.2 ms
64 bytes from zrh04s06-in-f3.1e100.net (172.217.16.131): icmp_seq=4 ttl=56 time=22.0 ms

--- google.de ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 22.016/22.067/22.200/0.130 ms


Pinging test.de 

PING test.de (104.45.6.189) 56(84) bytes of data. <<<< THAT line is delayed!!

--- test.de ping statistics ---
11 packets transmitted, 0 received, 100% packet loss, time 9999ms
xsigndll
  • 513
  • 1
  • 5
  • 13

2 Answers2

1

Solution:

Apparently it has something to do with linux buffering. I've reworked the shell command so it is working now. The solution is to wrap the linux command with the script command. So:

passthru("script -q -c 'ping -w 10 -c 4 test.de' /dev/null")

This article helped: https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe

Community
  • 1
  • 1
xsigndll
  • 513
  • 1
  • 5
  • 13
0

I think it is because you are using the system() function as it will only return the last line. You might be better suited using the passthru() or exec() functions. Here is a great writeup on what these functions do and their differences:

https://stackoverflow.com/a/21016100/1789650

Update based on comments

You may also want to try appending an output argument to your shell script. Append 2>&1 to the end of your line and it will put each new shell output line into a variable. Here is what it should look like:

exec("ping -w 10 -c 4 google.de 2>&1", $output );
print_r( $output );
Community
  • 1
  • 1
Matthew R.
  • 4,332
  • 1
  • 24
  • 39
  • **`exec()`** returns the last line – Ruslan Osmanov Sep 29 '16 at 21:35
  • I've already tried `exec()` and `passthru()`. exec() is not suiteable for direct output. passthru() sounded reasonable, but it didn't work either. It produced the same delay :-/ I've also tried popen() and reading the STDOUT byte by byte, but that didn't work either. I've also tried sending the output to a file (with detached console) and doing a system() call to read the file while the other process is writing it - but that didn't work either... I'm kinda stuck :-/ – xsigndll Sep 29 '16 at 21:46
  • Add an `$output` variable and print to screen argument after the command, updating answer with this info... – Matthew R. Sep 29 '16 at 21:50
  • Thanks, but the exec() command is waiting for the command to finish. That's not what I need. I do need the output "as it occurs" (flushed buffers), without any delay. – xsigndll Sep 29 '16 at 21:59
  • Are you trying to get the page to update in real time to what is happening in shell? – Matthew R. Sep 29 '16 at 22:08
  • Ah, I see the issue. The reason it is delayed is because it's not receiving a response and is timing out. The delay is actually network delay (from the timeout). Does test.de exist on your system? Try updating that URL with another URL that does exist and see if you still get the delay. – Matthew R. Sep 29 '16 at 22:16
  • Yeah - the timeout is on purpose to demonstrate the problem. Within the linux shell the command 'ping test.de' prints **instantly** the first line (_PING test.de (104.45.6.189) 56(84) bytes of data._). But in the php script it doesn't show this first line instantly. It waits till the timeout kicks in and after that it presens the complete output of the script. So how can I resolve this? How do I get the first line to show as instant as on the linux shell? – xsigndll Sep 29 '16 at 22:21