I have some PHP scripts that can be called either from the command line or as a webpage (where the arguments are passed from other web pages using $GET or $POST).
They can take a while to execute, let’s say 5 minutes.
The scripts include some “echo” & “print” calls which allow me to know what is happening during the execution in real time.
The problem is that, in webpage mode, those echo calls don’t print anything in the browser till the end of the script execution. Or sometimes, half the echos appears after 2 minutes and the rest at the end.
Is there a simple way to make my print()/echo() calls appear in real time when my script are called in “webpage mode”?
Thanks in advance.
flush() may or may not work depending on the browser and size of the output (see: PHP Flush() not working in Chrome)
Apache can also buffer output if mod_gzip is enabled.
Your best bet is to log into a db/session/fs and have JS on client side polling for updates.
Use ob_flush() to force output to be sent to the browser before script execution completes.
I assume you are not using output buffering as your script outputs fine on consolde. Therefore use flush() to explicitely tell PHP it should send output to the browser.
I would suggest a flush every xxx outputs instead of flushing after every echo or print if they appear in short intervals.
Related
Say you have a big PHP web application doing echoing, output buffering, etc, all over the place. The end result is a finished HTML/XML document to the browser.
Now say you find yourself in a small function in a random place in a big PHP web application. Is there a simple way to output something, for example an HTML comment, in a way so that it is sent as the last thing to the browser?
Something like a hook for "when everything is finished send this piece of info as well to the browser"?
The end goal is basically to output some warnings or debug info in an easy way, without messing up the output.
There's register_shutdown_function(), which would essentially be the very last thing executed by PHP before terminating your script.
To preface, I know this isn't a great question and it will be hard to explain.
I have a PHP script that takes 5-10 minutes to run. I don't want the user to have to wait for it. If I "trigger" the script using jquery ajax, and then the user navigates away from that page or closes the browser (and doesn't wait for the response (if any) which will come much later), will the script still execute fully (assuming there are no errors etc)
Thanks!
Once the server receives the AJAX Request along with the data, it would process it as usual, even if you close the page or the window. If you close the browser window before the server receives the AJAX Request, the processing it not going to happen.
Furthermore, if the AJAX Request is returning any kind of data or displaying messages, it is advised that you leave the window open, so that there is some "Listening" page to the Server's Request Response.
In your PHP script you could call the ignore_user_abort(true) function which would cause the script to run regardless of the user closing the page or not.
You could use the command line if you have access to one:
php /loc/to/file.php
This does not have a timeout and might be faster than port:80 (a browser calling an phpfile)
Or call the main phpfile in another file via a php's exec():
<?php
exec("php /loc/to/file.php > /loc/to/result.txt");
?>
You might want to use shell_exec()
The dir of results.txt and the file itself need to be writable.
The 'greater than' sign writes the output of the phpfile to result.txt. If the php would echo 123, that would be the contents of result.txt
5 to 10 minutes is a very long time, you might want to check your code for improvements. If you are using a database, add indice (an index) on columns u use allot, that ccan save huge amounts of tim
I am writing a script that will probably need half a day because it gets data from about 14000 webpages from a website.
To find out whether it makes progress or not, is there any way to observe its execution, i.e. the outgoing connections to each of the scraped pages, with the mac os shell?
I am using curl to get the page contents, if that is of any help.
Thanks a lot!
Charles
EDIT
The script is written in php and executed from localhost.
When writing custom scripts it is very helpful to output some sort of status to stdout.
this can be done in a uniform way using printf http://www.php.net/manual/en/function.sprintf.php
What you log to stdout depends on what information you need to see. Perhaps for a curl request I would log Url, Response code, maybe start time and end time. Its really up to you, just make sure you can verfiy it's status/progress.
printf('%40s | %5s', 'URL', 'Status Code');
printf('%40s | %5s', $the_url, $status_code);
If you are running this via a web browser, output is not seen until the PHP has finished executing. However, file_put_contents() can append data to a logfile which you can look at.
An example line of code would be: file_put_contents("file name.txt", "\nWebsite abc was successfully scraped", FILE_APPEND);. You must have the FILE_APPEND flag or the PHP will just overwrite the file each time.
php.net Reference
I have this:
echo "<font color=\"#000000\">text</font>";
usleep(2000000);
header("location:/otherpage.php");
?>`
Please note that this will be included in an iframe...
The problem is that it isn't echoing the echo statement, but then sleeping for two seconds and then redirecting (which is all correct except for the echo part)...
Anyone have an idea why this is happening?? It's not the iframe because when you go straight to the file (separately from the iframe) the same happens. Could it be the usleep??
Thanks
What you are doing above will not work. First, you would need to do a flush in order to make sure the data was sent. Second, though, and more important, you can't change the header after the flush, which would result in either the header not being sent or the text not being sent.
If all you want to do is change the data after a delay, did you consider doing the following:
header('Refresh: 2; url=http://my.site.com/otherpage.php);
echo "<font color=\"#000000\">text</font>";
This will send the information in the browser, instructing the browser to change to the new URL after 2 seconds.
This won't work since you can't change the header after outputting text.
The only option is to use a meta refresh or javascript when you want to exact replicate this behaviour.
But the output problem you can solve by flushing the buffer but then no redirection is possible as i mentioned before.
Another very important thing is:
DONT USE USLEEP FOR SUCH THINGS.
Why? Because when your script is heavily loaded every request which needs too much time is very bad and you will run out of php threads (depending on your php webserver implementation). So, for such timeouts you should use clientside code (if possible).
It's sleeping while on the server, and then sending the output. Also you can't send headers after echoing something.
You should use javascript or a meta redirect, this will allow you to wait a few seconds before redirecting, and the time and url for both of those can be generated by your php script.
You can't to that. I have a feeling you're misunderstanding the purpose of PHP and it's role as a server-side language.
If you want to "redirect" to another page in PHP, you do so using HTTP headers, which you did. The thing is, those are the headers, so they must be sent before any text body (like an echo statement). You're trying to do something that should be done client-side on the server.
Instead, make an HTML page with some JavaScript code to do the redirection, like that:
<script>
setTimeout(function() {
window.location = "otherpage.html";
}, 2000);
</script>
Expanding my comment into an answer:
It's not possible to redirect like this (outputting some content and then trying to send in a header) because headers must be sent before all content. PHP will also complain about this, using default settings you should see a warning.
Second, the usleep delay might not be observable due to the server buffering the content throughout the sleep and only sending it in one big chunk afterwards. In general, it isn't reliable to make the browser display content "in steps" like this, although it can be made to work more or less if you pile the hacks high enough.
May I suggest that if this kind of behavior is what you need, you should look into making a (series of?) appropriate AJAX call, which can be orchestrated perfectly.
What everyone else said. Just adding that usleep() will make clients hold connections open on your server---it's a very inefficient use of limited server resources. Your PHP should always send everything it can as quickly as possible so your web server can close the connection.
Can PHP's ob_start be called more then once?
Sorry if this is a dumb question but I really don't know.
My site is really large (file quantity), its a social network and one of the included files uses ob_start PHP's output buffer for something, i'm not ure someone else started my site a long time ago and now it is mine I need to look into it more to see what it's doing exactly.
Anyways I am wanting to use ob_start ("ob_gzhandler"); to compress CSS files and all files on my site get loaded (included) through the index file so I am wanting to know if I am able to use that even though it is already in use somewhere else in the code?
Yes, you can call it more than once. It creates a new buffer each time however, so be careful.
From the manual: "Output buffers are stackable, that is, you may call ob_start() while another ob_start() is active. Just make sure that you call ob_end_flush() the appropriate number of times. If multiple output callback functions are active, output is being filtered sequentially through each of them in nesting order."
You say this :
I am wanting to use ob_start
("ob_gzhandler"); to compress CSS
files
I would rather serving and compressing JS/CSS (well, static) files is the job of the Web server (ie, Apache), and not PHP.
About that, you can take a look at mod_deflate -- at least, if you are using Apache 2.
all files on my site get loaded
(included) through the index file
Is that really necessary ? You're having PHP work with no apparent (?) reason, that way.
(Note that even if CSS/JS files are served through PHP, Apache should be able to compress them with mod_deflate ; same is also true for HTML, JSON, ... btw)
Another advantage of not going through PHP to server those files is that it would be easier to get them served by another server, as your site will grow (if it grows enough, actually) :
you could have a bunch of "PHP servers", to process PHP pages
and one or two "static-files servers", to server only CSS/JS/images, and lighten the load or your "application servers" ; no need for PHP on these ones ; you could also use something like lighttpd instead of Apache
That being said, ob_start says this :
Output buffers are stackable, that is,
you may call ob_start() while another
ob_start() is active. Just make sure
that you call ob_end_flush() the
appropriate number of times. If
multiple output callback functions are
active, output is being filtered
sequentially through each of them in
nesting order.
So, I think the answer to your question is "yes" :-)