I have this function that gets the html from a list of pages and once I run it for
two hours or so the script interrupts and shows that memory limit has been exceeded,
Now i've tried to unset/set to null some variables hopefully to free up some memory
but it's the same problem. Can you guys please take a look at the following piece of
code? :
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if ($proxystatus == 'on'){
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
}
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($ch, CURLOPT_URL, $site);
ob_start();
return curl_exec($ch); // the line the script interrupts because of memory
ob_end_clean();
curl_close($ch);
ob_flush();
$site = null;
$ch = null;
}
Any suggestion is highly appreciated. I've set the memory limit to 128M, but before
increasing it (doesnt seem like the best option to me) I would like to know if there's
anything I can do to use less memory/free up memory while running the script.
Thank you.
You are indeed leaking memory. Remember that return immediately ends execution of the current function, so all your cleanup (most importantly ob_end_clean() and curl_close()) is never called.
return should be the very last thing the function does.
I know it's been a while, but others might run into a similar issue, so in case it helps anyone else...
To me the problem here is that curl is set to save the output to a string. [That's what happens with curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);] If the output gets too long, the script will run out of allowed memory for that string. [That returns an error like FATAL ERROR: Allowed memory size of 134217728 bytes exhausted (tried to allocate 130027520 bytes)] The way around this is to use one of the other output methods offered by curl: output to standard output, or output to file. In either case, ob-start shouldn't be needed at all.
Hence you could replace the content of the braces with either option below:
OPTION 1: Output to standard output:
$ch = curl_init();
if ($proxystatus == 'on'){
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
}
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($ch, CURLOPT_URL, $site);
curl_exec($ch);
curl_close($ch);
OPTION 2: Output to file:
$file = fopen("path_to_file", "w"); //place this outside the braces if you want to output the content of all iterations to the same file
$ch = curl_init();
if ($proxystatus == 'on'){
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
}
curl_setopt($curl, CURLOPT_FILE, $file);
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($ch, CURLOPT_URL, $site);
curl_exec($ch);
curl_close($ch);
fclose($file); //place this outside of the braces if you want to output the content of all iterations to the same file
For sure this is not a cURL issue. Use tools like xdebug to detect which part of your script is consuming memory.
Btw I would also change it not to run for two hours, I will move it to a cronjob that runs everyminute, check what it needs and then stops.
Related
My php curl request is timing out as i expected it to and giving me the error message: "Operation timed out after 120000 milliseconds with 234570 bytes received"
But how do i get the bytes received despite its timeout?
$url = "example.com";
$timeout = 120;
$ch = curl_init();
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$curl_page = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
var_dump($curl_page, $error);
don't use CURLOPT_RETURNTRANSFER. use CURLOPT_FILE instead, eg
$outfileh=tmpfile();
$outfile=stream_get_meta_data($outfileh)['uri'];
curl_setopt($ch,CURLOPT_FILE,$outfileh);
curl_exec($ch);
$curl_page=file_get_contents($outfile);
(and don't forget to fclose($outfileh), or you'll have a resource leak, and keep in mind that with tmpfile()'s, fclose() will delete the file for you as well... the good news is, php will clean it up anyway at the end of execution, though) - another option is to use CURLOPT_WRITEFUNCTION, eg
$curl_page = '';
curl_setopt ( $ch, CURLOPT_WRITEFUNCTION, function ($ch, $recieved) use (&$curl_page) {
$curl_page .= $recieved;
return strlen ( $recieved );
} );
curl_exec($ch);
which has the advantage of less IO, this will be handled enterly in memory, unlike the CURLOPT_FILE approach, which may start writing it to disk, depending on the OS IO cache.
I'm Currently proxying an endpoint by running a cURL however the size of my cURL is about 10 times larger than the original API, Why is that, and how can I decrease the size? This is all JSON BTW.
Original API return size = 32.2kb
cURL return size = 488KB
And here is my cURL script:
$ch = curl_init();
// set url
$url = 'http://domain.com/api/v1';
// set options
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// $output contains the output string
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
return $output;
ob_start('ob_gzhandler');
php output buffer controll was the fix to my problem. Thanks all that tried to help!
Hello I'm having problems uploading a file to the site bellow, I have inspected the elements and added them to the $data file, I'm fairly new to this, so please guide me.
function upload($url,$data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, "C:/xampp/htdocs/curl_upload/cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEFILE, "C:/xampp/htdocs/curl_upload/cookies.txt");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1000);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
$data = array("file_0"=>"#C:\files\somerarfile.rar","submit_btn"=>" Upload! ");
echo upload("http://180upload.com/",$data);
Have you tried this on a live domain? Everything appears to be in shape, maybe there's a problem with the local php.ini, filesize or your operating system (with its security).
Try on a live (sub)domain.
To set you max filesize, try
<?php
ini_set('upload_max_filesize', '40M');
ini_set('post_max_size', '40M');
?>
Obviously, set the values to whatever you need.
With your upload page, have you tried logging all the POST, GET, FILES variables?
What I do when I'm debugging and something doesn't want to work is:
<?php
$f = fopen("access.log", "a+");
$data = print_r($_REQUEST,1);
fwrite($f, $data);
fclose($f);
?>
Same with $_FILES. If there's an access log with the information, I know the page is being reached, everything is being sent but I'm handling it wrong.
If there's no file then, obviously, the page isn't getting reached.
Hope this helps
Mark
I get files by their urls by this code
file_get_contents($_POST['url'];
Then I do something with them.
But I don't want to operate with big files, how do I limit size of received file?
It should throw an error if file is bigger than 500kb.
See my answer to this question. You need to have the cURL extension, with which you can make a HEAD HTTP request to the remote server. The response will let you know how big the file is, and you can then decide accordingly.
You are interested specifically in this line:
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
Agree with #Jon
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url); //specify the url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$head = curl_exec($ch);
$size = curl_getinfo($ch,CURLINFO_CONTENT_LENGTH_DOWNLOAD);
if(<limit the $size>){
file_get_contents($url);
}
The following is part of a script which is used to authenticate paypal payments.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
curl_error($ch);
curl_close($ch);
On some rare occasions there is a problem with curl_exec which causes the the script to stop executing at that line.
No errors are recorded in the cpanel error log and after trying a number of different things I am no clearer as to what may be causing this error with curl.
I am not very familiar with curl, so if anyone knows of a good way to obtain error information from this, or what could possibly cause this problem, I'd really appreciate it.
Thanks
It could just take a long time.
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
Set the time out to 30 seconds. Are you sure you waited that long?
Use CURLOPT_TIMEOUT_MS to set the timeout in milliseconds.
curl_error() returns a string, it doesn't do any output/logging of its own. The proper way to detect curl errors is as follows:
$result = curl_exec($curl);
if ($result === FALSE) {
error_log("CURL failed at " . date('c'));
error_log("CURL message: " . curl_error($curl));
}