flush / ob_flush not working on remote server - php

Please Read Before you mark as CLONE to this
I am running xampp on my local machine and when testing by writing http://localhost/test.php I am getting the desired output i.e. printing 1 to 10 after each second. But as soon as I change it to my local IP http://10.70.52.75/test.php it loads for 10 seconds and gives output in one shot. I actually need this method to collect output from a PHP script which will be running for 10-15 minutes.
Alredy checked the php.ini for buffering as off.
apache_setenv('no-gzip', 1); //can comment this line
header('Content-Encoding: none');
header( 'Content-type: text/html; charset=utf-8' );
for ($i=0; $i<10; $i++) {
echo $i.'<br>';
flush();
ob_flush();
sleep(1);
}
Tried all the hacks available on stackoverflow
PHP Flush/ob_flush not working
Calling ob_flush() and flush(), yet browser doesn't show any output until script finishes
and much more but did not get the correct one. Please try to run the code on your Linux server or try on my setup
http://host-1-89.linuxzoo.net/test.php
ssh to this machine with root#linuxzoo.net
Password is "secure"
Let me know any one succeed in any way

Related

Switch from php-mod to php-fpm Output buffering problem

When using php-mod and fastcgi the code executes perfectly and every second i get an output but switching to php-fpm the code lags a few seconds before outputting depending on output size
Tried the following and combinations of
setting output buffer 0 in php ini
ob_implicit_flush
ob_start
ob_end_flush
header Content-Encoding = none
implicit_flush 1
ob_end_clean
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while( true ){
$time = date('r');
echo "retry:1000\r\n";
echo "data: ".$time;
echo "\r\n\r\n";
ob_flush();
flush();
sleep(1);
}
?>
This is for a production server and php-mod is not an option i also got it to work in Fastcgi with
FcgidOutputBufferSize 0
is there a way to make the code work on php-fpm so the output is send immediately as in php-mod and fastcgi ?
P.S Running : Ubuntu 18.04, Apache 2.4.29, PHP 7.2
After a few days i have discovered the only way to get this to work in php-fpm is to fill the output buffer. This is really inefficient ! Let me explain :
Say you are using Server-send events and your output buffer is 4096, you process every second even if you do not return anything you still send about 4Kb output to client where mod_php and fast-cgi sends only data when there is an output.
If anyone else has this problem this is my best solution : run main site on php-fpm ex. example.com and make a sub-domain ex. push.example.com and setup fast-cgi / php_mod[NOT RECOMMENDED PRODUCTION] on sub-domain now you can keep the connection open and process data without sending output to client.
PS. I saved Session variables in database so both domain and sub-domain can access it see https://github.com/dominicklee/PHP-MySQL-Sessions the other thing is to let sub-domain send CORS. in PHP add header('Access-Control-Allow-Origin: https://example.com');

Send header before execution ends

On my development server (CentOS 6.3, PHP 5.3) this works fine:
ignore_user_abort(true);
header('Location: http://test.hooshmarketing.com/tools/test/test_pretty_output.php');
//here a long script keeps executing in the background a few seconds
this works fine too
ob_implicit_flush(true);
echo "foo"; //I see foo on the browser and...
sleep (15);
echo "bar"; //... about 15 seconds later I see bar on the browser
and this
ob_start();
echo "foo"; //foo is written...
sleep(10);
ob_flush(); //...about 10 second later, foo is sent
echo "bar"; //bar is written...
sleep(10);
ob_end_flush(); //...about 10 second later, bar is sent
On my contractor's production server (bluehost PHP 5.2 shared hosting) none of the three examples work. Nothing is sent to the client until the script finishes executing. I tried setting ini_set('output_buffering', '0') and output_buffering = Off on the script folder's php.ini file but no luck. Any ideas on why this could be happening?
If you are using ob_implicit_flush(true); then you no need to call the flush(); but you have to use the ob_flush();.
ob_flush(); brings out data from application initiated buffer. PHP internally has CGI buffer, ob_implicit_flush(true); will turn on the implicit flushing, which does not use CGI buffer and which uses application initiated buffer.
So once you are using ob_implicit_flush(true); then you have to use ob_flush();
I hope this helps.

Disabling output buffering in PHP

I have an object for tasks and on __deconstruct(), it's meant to run some of the lengthier cleanup tasks after the rest of the page has already loaded. Unfortunately, it buffers the output and won't send it until after the tasks are finished (nothing is printed in the tasks).
I've read through http://www.php.net/flush and tried all the suggestions there. Obviously I've tried disabling output_buffering in php.ini. I've disabled deflate_module, zlib compression is off, don't have mod_gzip. Calling flush() or ob_flush() has no effect, nor does enabling implicit_flush.
I'm just running XAMPP (currently apache 2.2.17, php 5.3.4) under Windows Server 2008 R2. PHP is being run as a module.
And yes, I could set up some little AJAX hack to run the task manager or even set up a scheduled task to run this specific task, but output buffering has been an issue elsewhere, too. Would just like it to be gone sometimes.
From a similar thread, someone suggested seeing what the following would do:
<?php
while (TRUE)
{
echo 'x';
flush();
sleep(1);
}
?>
As expected, the page displays nothing until the maximum execution time is reached, at which point it flushes the buffer.
This has become extremely frustrating. Anyone have any ideas what could still be causing it to buffer?
You're only sending a small amount of data. Browsers have their own buffer, which can be based on a number of bytes, by which elements have been received, or by something else.
In short, there is nothing you can do about this. The buffering is happening client-side, not server-side. You could try sending more data before your xs.
You can prove this by packet sniffing the connection between the server and the browser, with Wireshark or similar.
hmmm, interesting grabbed a snip of code I have used else where and it works as expected...
https://stackoverflow.com/a/9728519/632951
<?php
echo str_repeat('fillerbytes',20*1024/strlen('fillerbytes'));
echo '<body style="font-size:6px;font-family:arial;">';
echo str_repeat('<br>',2);
for($i=1; $i<=5000; $i++){
echo $i . ' ';
ob_flush();
flush();
usleep(2000); // 2 ms each = 10s total
}
?>
Watch my server count to 5000 http://atwebresults.com/texttest/new.php
(Doesn't work on some free hosts like freehostingeu.com.)

PHP script not echo'ing logs in real time - Was working on my other server

I wasn't sure how to title this thread, sorry.
I have a script that processes some logs and I echo a lot of debug information as the process goes. Since moving to the new server, it seems that the script hangs for 30 odd seconds, then spits out all the logging, then hangs again for 30 odd seconds and the process continues.
This is really odd behavior and I don't know where to start. Its like it isn't processing the file line by line but in blocks ...
PHP version is 5.1.6 on a CentOS running plesk. (My old CP was CPanel)
Any ideas?
EDIT: Simple example of my issue - Running this code:
for ($i=0; $i<100; $i++) {
echo "test $i";
sleep(1);
}
the script will hang for 100 seconds, then print out all the "test 1" ect. Sleep is required in my main script and on the other server just echoed the values in turn.
EDIT2: Have tried setting output_buffering = 0 and implicit_flush = On and didn't help.
You may have output_buffering On. Try to disable it first.
You can do it either in the php.ini file, in a .htaccess file if your server allows it, or use the following code at the beginning of your PHP script:
while (ob_get_level()) ob_end_clean();
Also, use flush() after each echo or print, and it should be all right!
Update:
You might also encounter other buffers that you cannot control from within PHP (web server, browser, ...), which is why you're still not seing anything. A workaround is to send some blank bytes after each print:
while (ob_get_level()) ob_end_clean();
for ($i=0; $i<100; $i++) {
echo "test $i";
echo str_repeat(' ', 256);
flush();
sleep(1);
}
However, while this example works for me on IE & Firefox, it does not work on Chrome!

PHP flushing output as soon as you call echo

I thought flush(); would work, at least from what Google/Stackoverflow tell me, but on my Windows WAMP (Windows, Apache, MySQL, PHP) system it doesn't work.
Is there some PHP setting I have to set to make flush() work?
Here's my code:
<?php
echo "Fun";
flush();
sleep(5);
echo "<br>Mo";
?>
The code just outputs all together when the script is done executing (after 5 seconds).. I don't want this, I want 'Fun' to show up right away, and then after 5 seconds 'Mo'.
I've tried other combinations of flush like ob_end_flush(); or ob_implicit_flush(true); but nothing is working. Any ideas?
So that's what I found out:
Flush would not work under Apache's mod_gzip or Nginx's gzip because, logically, it is gzipping the content, and to do that it must buffer content to gzip it. Any sort of web server gzipping would affect this. In short, at the server side, we need to disable gzip and decrease the fastcgi buffer size. So:
In php.ini:
. output_buffering = Off
. zlib.output_compression = Off
In nginx.conf:
. gzip off;
. proxy_buffering off;
Also have this lines at hand, specially if you don't have acces to php.ini:
#ini_set('zlib.output_compression',0);
#ini_set('implicit_flush',1);
#ob_end_clean();
set_time_limit(0);
Last, if you have it, coment the code bellow:
ob_start('ob_gzhandler');
ob_flush();
PHP test code:
ob_implicit_flush(1);
for($i=0; $i<10; $i++){
echo $i;
//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
The script works fine from CLI, displaying "Fun", waiting 5 secs before displaying "<br>Mo".
For a browser the results might be a bit different because:
The browser wont start rendering right away. Getting 3 bytes of data for HTML document isn't enough to do anything, so it'll most likely wait for a few more.
Implicit IO buffering on the lib level will most likely be active until a newline is received.
To work around 1) use text/plain content type for your test; 2) needs newlines, so do an echo "Fun\n"; and echo "<br>Mo\n"; Of course you wont be using text/plain for real HTML data.
If you're using CGI/FastCGI, forget it! These don't implement flush. The Webserver might have it's own buffer.
You can disable all output buffering in PHP with following command:
ob_implicit_flush();
If the problem persists, although you explicitly set
implicit_flush = yes
in your php.ini, you might also want to set
output_buffering = off
which did the trick in my case (after pulling my hair for 4+hrs)
Check your php.ini for output_buffering.
Maybe the problem is Apache here, which also may have buffers...

Categories