I am running an external script in PHP using its exec() function. I was looking for various options to create a progress bar. I am able to create a plain rotating loader through AJAX but I couldn't achieve the percentage progress bar. Is there any way to do that?
Depending on the program you want to execute, you could use proc_open() instead of exec(), so you can proccess the output, calculate a percentage and throw it back to your ajax script using ob_flush() and flush().
It's not true that you need to wait for the execution to finish before sending any output, but there are some caveats with your server cache configuration and browsers rendering engines, so it is not so reliable.
If you're not using Websockets (the clean and modern option, which can be achieved with PHP using Ratchet or with nodejs using various options), the most reliable way of doing what you want is with polling.
Briefly, instead of calling your script once, you do a first ajax request to init the proccess and then start poking the server again and again to ask the execution status of your script.
For more information, take a look at those answers:
Run process with realtime output in PHP
PHP - Flushing While Loop Data with Ajax
Grab results from a php exec() while the command is still running?
PHP runs on the server, thus can not achieve this (to my knowledge),
here are some answered questions that might be able to help you.
How to show loading status in percentage for ajax response?
Jquery:: Ajax powered progress bar?
Related
I'm trying to write a long executing code, but it hangs after a set amount of seconds, and I want avoid this using any workaround.
The workflow:
User send an AJAX request on the press of a button. This initates a process (function), which for example polls multiple websites for info or sends POST data using cUrl. Ideally, it should provide some info once in a while, but it would be even better if it would run in the background.
The no-no's:
The following functions cannot be used in the code: set_time_limit, exec, fork, anything pcntl related.
Possible solution:
I searched through many posts, and one possible workaround would be to split the code to multiple parts (ex. send one cUrl at a time) and have have jQuery reinitiate the connection until a given condition.
But is there a way on the server side to avoid timeout? I also tried using the Process component of Symfony, Ratchet, sockets...
Many thanks!
Edit: Fixed formatting. I forgot to mention that the code has to be reusable on any server, so editing any config files is not an option either.
Use this function at the start of your script set_time_limit(0).
I am working on a site plugin that takes advantage of the YouTube API to grab some data for a specific channel. The problem is that the code takes several seconds to load on larger channels meaning the user has to wait quite a bit of time for the script to finish loading before they can view each page. Most of the time the data retrieved isn't even relevant to them but the script still needs to run its checks. So how can I initialize the PHP script without the user having to wait for it?
My first thought is to use AJAX and make a request to the remote script but will that cause parts of the page to hang as the script is running? I don't need the results from the script, I just need the script to run and do its own thing.
You can use exec to start a separate PHP script. And adding & at the end will make exec return imidiately.
Let script.php do the heavy stuff and call it from a mall script like so:
exec("php script.php > /dev/null &");
You need to have a *nix server environment. Don't think it will work on Windows platform.
AJAX stands for Asynchronous JavaScript and XML, which means that, when using it, the execution of the rest of the code will not be blocked.
You can make an AJAX request to the script you want to execute and then keep rendering the page normally. The AJAX request will be performed in the background, and won't be of any disturb whatsoever.
I am using ubuntu and mktorrent, I am wondering is it possible to get the output from my mktorrent command to my php app live? So I can watch the status of the creating torrent?
At the moment, exec just sits there and waits (sometimes for over an hour :O) for the torrent to be finished making.
Does the php proc open command do something similar to this or do I have to figure out some sort of crazy ajax with a screen session setup?
PHP executes completely on the server and the rendered page gets sent to your browser. In order to show any progress and have it update, you'd have to request it from the server repeatedly (or have the server send progress through sockets or long polling or something, but the idea is the same)
You'll need a way for the server to issue progress updates from the command and some sort of JS (AJAX) to communicate with the server to get those updates.
If you can have the mktorrent command output progress to a file, you can have php read the file on page load and echo it to the user. You can use a simple meta refresh tag to refresh the progress page after a few seconds.
See Asynchronous shell exec in PHP for info on having PHP execute a shell command asynchronously so your PHP script doesn't have to wait for it to finish, causing your page to hang until the task is done.
is there any method to call a webpage using curl or anything else , without pausing the calling script?
in other words:
php code here
.
.
.
.
call_web_page();
.
.
.
php codes 2 here
the script runs through php code , then calls the webpage and resumes the php code to the end without waiting for a result from the webpage being called .
no need to the call_web_page(); to be a function it could be some lines of code to call the page ...
PS : No AJAX or EXEC
You could do a Ajax Request to the PHP script that executes when the page is finished loading. This way you can just let the user know that you are waiting for a response and let them finish loading the page. But if you need some of the data that you are retrieving you could consider hiding the real pages elements and showing only a progress bar. Then when you have the data you could populate the elements with it, just a idea.
Update, You could maybe delegate the task to a process running on the machine (if you have that level of access)
And have a look at Run PHP Task Asynchronously maybe that helps too.
You could execute a second php script (or system command - curl for example) as a background process using a similar method to this answer: php execute a background process
Edit: Due to no exec sys commands
You could use file('http://yourserver.com/another.php'); which makes a request to start another php process. The file contains this code, and returns immediately. The request should happen all on your server without trekking off to the internet.
header("Connection: close");
header("Content-Length: " . mb_strlen($response));
echo $response;
flush();
do_function_that_takes_five_mins();
code taken from: How to continue process after responding to ajax request in PHP?
What you want to doe is doing asynchroneaus calls what is achived by running some paralell threads and then to wait at a certain joinpoint for all the threads to finish.
Actually there is no native multithreading support in PHP but you can look at this post: Does PHP have threading?
There are some suggestions on what to use if you want to realize multithreading in php.
Why not just grab the pages and cache them for say 30 minutes (or longer depending on content). Then you don't need to wait each time a user opens the page.
You would use a process of something like:
check if local cached copy exists / is not too old
if old/not exist -> fopen remote file
fopen the local file cache
repeat for as many files as you need
More reading on SO:
How can I force PHP's fopen() to return the current version of a web page?
Does PHPs fopen function implement some kind of cache?
5-minute file cache in PHP
Since PHP isn't event-based i/o will block, and since your dismissing any AJAX/Exec solution i don't think you'll be able to implement this in PHP.
Maybe try with Node, Ruby EventMachine or Twisted Python?
I was wondering if is is possible to send output from application ran by php to client.
For example i have application that outputs:
Hello world
And after 10 seconds it outputs
10 seconds passed
I'd like to know if it is possible to send "Hello word" and "10 seconds passed" to client without waiting until whole program finishes its job. Client would receive "Hello world" first and after 10 seconds second output.
Thank you.
Your title says "Asynchronous external aplication execution". By this, you would mean something that will execute a program from your PHP script, yet continue on its own process and not hang PHP page load. You may want passthru() specifically setting the command to output to a local file rather than your script (personally not tested, though the PHP manual says you can), or pcntl_fork() to split off your script into a separate process which will handle the program execution on the side. However, double-sending to a browser after it had already disconnected from your server and expecting it to display your uninvited message is impossible unless you install a trojan on the client which will auto-accept your second, new tcp forced connection.
But, if you want a progress message for your page load, simply echo "still loading..." anywhere along a number of for or while loops. File download progress bars on the other hand cannot be dealt with in PHP. Echoing "still loading..." in the middle of the download will corrupt the file. At the moment, I'm not aware of any facility to do this using any PHP, Javascript, or VB method, except in the browsers own API (if documented) if the client allows it by installing a plugin you authored. But why, when browsers already have built-in progress bars?
I think you should do this with javascript. It's totally unnecessary to use cpu-cycles on the server until all of your requirements are that show time passed.
Usually, a client pulls content from the server. If you want to push from the server to the client, you need to look into push technologies like Comet. There is not too much available for PHP though. Periodically pushing with the PHP script terminating inbetween requires a Message Queue.
I don't understand your application, but for batch processing this comes to mind:
php hello-world.php | php client.php
To scale it, use Hadoop.