I am creating an API that receives a post request and then returns data. This data needs to be returned immediately but then I need to execute a long running curl operation after that.
<?php
if (!empty($_POST)) {
$numbers = isset($_POST['numbers']) ? $_POST['numbers'] : 0;
$numbers = $numbers*$secrethash;
$result = array("error" => false,
"numbers" => $numbers);
echo json_encode($result);
$curlfunction($numbers);
exit;
Unfortunately, data is not returned until the curl function completes which causes my application to timeout. It is possible to execute the curl in the background so my data can be returned immediately?
You could put the function in a separate file and execute it similar to this. This would cause a separate process to be created. Maybe write the result to a file and read it. Set up your php to take your variable as a parameter.
exec("/usr/bin/php /path/to/script.php > /dev/null &");
It might be worth a shot. :-)
There are several options for you.
You can install CRON job after outputting json content via exec() function.
Make AJAX request from your page after json data was returned.
Related
So I am making a simple website for personal use, it sends an Post request via Ajax, PHP code is something like that:
$cmd = "some command";
$r = shell_exec($cmd);
echo $r;
Now, the first time I send the request it works, but if I send more requests without refreshing whole page it returns nothing. PHP script does execute, just shell_exec returns nothing. I have no idea what is causing this.
(Debian, Apache2, PHP7.0)
ajax code:
$.post("exec.php", {command: val}).done(function(data){
self.outp.append(data);
});
And I confirmed that val is correct, if in PHP i add something to $r (example: $r .= "test") it does return that.
#Edit I've found out using GET insted of POST makes the problem disappear, it does not really resolve the problem, but it's something.
I am building a WebService, using PHP:
Basically,
User sends a request to the server, via HTTP Request. 'request.php', ie.
Server starts php code asynchronously. 'update.php', ie.
The connection with the user is finished.
The code 'update.php' is still running, and will finish after some time.
The code 'update.php' is finished.
The problem is with php running asynchronously some external code.
Is that possible? Is there another way to do it? With shell_exec?
Please, I need insights! An elegant way is preferable.
Thank you!
The best approach is using message queue like RabbitMQ or even simple MySQL table.
Each time you add new task in front controller it goes to queue. Then update.php run by cron job fetch it from queue, process, save results and mark task as finished.
Also it will help you distribute load over time preventing from DoS caused by your own script.
You could have the user connect to update.php, generate some sort of unique ID to keep track of the process, and then call fsockopen() on itself with a special GET variable to signify that it's doing the heavy lifting rather than user interaction. Close that connection immediately, and then print out the appropriate response to the user.
Meanwhile, look for the special GET variable you specified, and when present call ignore_user_abort() and proceed with whatever operations you need in that branch of the if clause. So here's a rough skeleton of what your update.php file would look like:
<?php
if ( isset($_GET['asynch']) ) {
ignore_user_abort();
// check for $_GET['id'] and validate,
// then execute long-running code here
} else {
// generate $id here
$host = $_SERVER['SERVER_NAME'];
$url = "/update.php?asynch&id={$id}";
if ( $handle = fsockopen($host, 80, $n, $s, 5) ) {
$data = "GET {$url} HTTP/1.0\r\nHost: {$host}\r\n\r\n";
fwrite($handle, $data);
fclose($handle);
}
// return a response to the user
echo 'Response goes here';
}
?>
You could build a service with PHP.
Or launch a PHP script using bash : system("php myScript.php param param2 &")
Look into worker processes with Redis resque or gearman
In my previous question I had a problem with sending parameters over the command line to an PHP file. The PHP is sending an json back, but I only receive true or false.
Previous question:
Rails, PHP and parameters
New problem:
Ruby.rb
data = system('php public/jira.php param')
puts data
PHP
$output = array(
"total" => $total
);
echo json_encode($output);
EDIT:
Answer:
data = JSON.parse(data)
puts data['total'] #5
See this answer.
Basically you'll want to use:
data = `php public/jira.php param`
data JSON.parse(data)
puts data['total']
Instead of:
data = system('php public/jira.php param')
puts data
system() will return TrueClass or FalseClass and display output, try it on console .
I suggest , You can use the open method on any URL to call it, so you can call your PHP script using that:
require 'open-uri'
open('YOUR PHP SCRIPT PATH WITH PARAMETER') do |response|
content = response.read
end
Or below link will help you .
6 Ways to Run Shell Commands in Ruby
How to exectue a shell file with PHP?
I have a file called sync.sh, so how to run the file in php and how to take the response after complete the execution? I think shell_exec() will help to trigger the file but how can I get the response that script is completed the task properly or not?
Take a look at the exec() function. You can pass in a return_var which will hold the exit code from the shell script.
$out = array();
$status = -1;
exec( '/path/to/sync.sh', $out, $status );
if ( $status != 0 ) {
// shell script indicated an error return
}
One thing to watch out for is that the script will run with the web server's permissions, not your own as a user.
Also, be sure to heed the doc's security-related warning:
When allowing user-supplied data to be passed to this function, use
escapeshellarg() or escapeshellcmd() to ensure that users cannot trick
the system into executing arbitrary commands.
According to the documentation:
Return Values
The output from the executed command or NULL if an error occurred.
Just get the return value of that function.
$result = shell_exec('sync.sh');
And $result will contain what you want.
I am making use of AJAX on my site and I would like to show users progress of a file that is being downloaded by my server.
The download is done by script that outputs a percentage to the shell. I would like to pass this info back to the user using AJAX. How can I do this?
Thank you for any help and direction.
I hope your solutions do not involve writing to a text file and retrieving that percentage from the text file!! Too much over head I think.
EDIT - More Info
It is a Linux Shell command - Fedora Core 10.
Currently this is how the shell output looks like:
[download] 9.9% of 10.09M at 10.62M/s ETA 00:00
The percentage changes and I wish to capture that and send it back to the user as it changes.
To execute this, I make use of PHPs exec() function.
Instead of exec, you could use popen. This will give you a handle you use with fread to grab the output your command generates as it happens.
You'll need to parse out the updates it makes to the percentage indicator. Once you have that data, there are a few ways you could get it to a client, e.g. with a "comet" style push, or have an Ajax request poll for updates.
I haven't tried this, but I think this approach would work.
You need three pieces:
Have shell script output its stream to netcat connected to a port
Have a php script listening to stream coming from said port for incoming data, updating a record in memcache or some database w/ the percentage finished.
Have your web script periodically make ajax calls, to the server which checks this value in your backend store.
I'm working on a similar problem. I have to parse the output of my video conversion shell script. I use popen and parse the output of the returned resource. At first I used fgets but that didn't recognize the updated values as new lines. So I created a simple function to that takes an optional $arg_delimiter so you can check for other return types like the chr(13) cariage return. The example code is a bit modified and therefor untested because in my case these functions were methods on my parser object.
function get_line ($arg_handle, $arg_delimiter = NULL)
{
$delimiter = (NULL !== $arg_delimiter) ? $arg_delimiter : chr(10);
$result = array();
while ( ! feof($arg_handle))
{
$currentCharacter = fgetc($arg_handle);
if ($delimiter === $currentCharacter)
{
return implode('', $result);
}
$result[] = $currentCharacter;
}
return implode('', $result);
}
I simply loop over the results from the popen() resource like this:
$command = '/usr/bin/yourcommand';
$handle = popen($command . ' 2>&1', 'r');
while ( ! feof($handle))
{
$line = get_line($handle, chr(13));
preg_match($yourParserRegex, $line, $data);
if (count($data) > 0)
{
printf("<script type='text/javascript'>\n //<![CDATA[\n window.alert('Result: %s');\n // ]]>\n</script>"
,$data[1]
);
flush();
}
}
Now all you need to do is figure out the comet stuff.