简体   繁体   English

php curl多错误处理程序

[英]php curl multi error handler

i want to capture curl errors and warnings in my error handler so that they do not get echo ed to the user. 我想在我的错误处理程序中捕获curl错误和警告,以便它们不会echo给用户。 to prove that all errors have been caught i prepend the $err_start string to the error. 为了证明所有错误都已被捕获,我将$err_start字符串添加到错误中。 currently here is a working (but simplified) snippet of my code (run it in a browser, not cli): 目前这里是我的代码的一个工作(但简化)片段(在浏览器中运行,而不是cli):

<?php
set_error_handler('handle_errors');
test_curl();
function handle_errors($error_num, $error_str, $error_file, $error_line)
{           
    $err_start = 'caught error'; //to prove that the error has been properly caught
    die("$err_start $error_num, $error_str, $error_file, $error_line<br>");
}           
function test_curl()
{   
    $curl_multi_handle = curl_multi_init();
    $curl_handle1 = curl_init('iamdooooooooooown.com');
    curl_setopt($curl_handle1, CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($curl_multi_handle, $curl_handle1);
    $still_running = 1;
    while($still_running > 0) $multi_errors = curl_multi_exec($curl_multi_handle, $still_running);
    if($multi_errors != CURLM_OK) trigger_error("curl error [$multi_errors]: ".curl_error($curl_multi_handle), E_USER_ERROR);
    if(strlen(curl_error($curl_handle1))) trigger_error("curl error: [".curl_error($curl_handle1)."]", E_USER_ERROR);
    $curl_info = curl_getinfo($curl_handle1); //info for individual requests
    $content = curl_multi_getcontent($curl_handle1);
    curl_multi_remove_handle($curl_multi_handle, $curl_handle1);
    curl_close($curl_handle1);
    curl_multi_close($curl_multi_handle);
}
?>

note that my full code has multiple requests in parallel, however the issue still manifests with a single request as shown here. 请注意,我的完整代码并行存在多个请求,但问题仍然显示在此处显示的单个请求中。 note also that the error handler shown in this code snippet is very basic - my actual error handler will not die on warnings or notices, so no need to school me on this. 另请注意,此代码段中显示的错误处理程序非常基本 - 我的实际错误处理程序不会因警告或通知而死亡,因此无需在此学习我。

now if i try and curl a host which is currently down then i successfully capture the curl error and my script dies with: 现在,如果我尝试卷曲当前关闭的主机,那么我成功捕获卷曲错误,我的脚本死了:

caught error 256, curl error: [Couldn't resolve host 'iamdooooooooooown.com'], /var/www/proj/test_curl.php, 18

however the following warning is not caught by my error handler function, and is being echo ed to the page: 但是我的错误处理函数没有捕获到以下警告,并且正在echo该页面:

Warning: (null)(): 3 is not a valid cURL handle resource in Unknown on line 0

i would like to capture this warning in my error handler so that i can log it for later inspection. 我想在我的错误处理程序中捕获此警告,以便我可以将其记录以供以后检查。

one thing i have noticed is that the warning only manifests when the curl code is inside a function - it does not happen when the code is at the highest scope level. 我注意到的一件事是警告仅在curl代码位于函数内时才会显示 - 当代码处于最高范围级别时,它不会发生。 is it possible that one of the curl globals (eg CURLM_OK ) is not accessible within the scope of the test_curl() function? 是否有可能在test_curl()函数的范围内无法访问其中一个curl全局(例如CURLM_OK )?

i am using PHP Version 5.3.2-1ubuntu4.19 我正在使用PHP版本5.3.2-1ubuntu4.19

edits 编辑

  • updated the code snippet to fully demonstrate the error 更新了代码段以完全演示错误
  • the uncaptured warning only manifests when inside a function or class method 未捕获的警告仅在函数或类方法中出现

I don't think i agree with the with the way you are capturing the error ... you can try 我不认为我同意你捕获错误的方式...你可以试试

$nodes = array(
        "http://google.com",
        "http://iamdooooooooooown.com",
        "https://gokillyourself.com"
);

echo "<pre>";
print_r(multiplePost($nodes));

Output 产量

Array
(
    [google.com] => #HTTP-OK 48.52 kb returned
    [iamdooooooooooown.com] => #HTTP-ERROR 0  for : http://iamdooooooooooown.com
    [gokillyourself.com] => #HTTP-ERROR 0  for : https://gokillyourself.com
)

Function Used 使用的功能

function multiplePost($nodes) {
    $mh = curl_multi_init();
    $curl_array = array();
    foreach ( $nodes as $i => $url ) {
        $url = trim($url);
        $curl_array[$i] = curl_init($url);
        curl_setopt($curl_array[$i], CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl_array[$i], CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)');
        curl_setopt($curl_array[$i], CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($curl_array[$i], CURLOPT_TIMEOUT, 15);
        curl_setopt($curl_array[$i], CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl_array[$i], CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl_array[$i], CURLOPT_SSL_VERIFYPEER, 0);
        curl_multi_add_handle($mh, $curl_array[$i]);
    }
    $running = NULL;
    do {
        usleep(10000);
        curl_multi_exec($mh, $running);
    } while ( $running > 0 );
    $res = array();

    foreach ( $nodes as $i => $url ) {
        $domain = parse_url($url, PHP_URL_HOST);
        $curlErrorCode = curl_errno($curl_array[$i]);
        if ($curlErrorCode === 0) {
            $info = curl_getinfo($curl_array[$i]);
            $info['url'] = trim($info['url']);
            if ($info['http_code'] == 200) {
                $content = curl_multi_getcontent($curl_array[$i]);
                $res[$domain] = sprintf("#HTTP-OK %0.2f kb returned", strlen($content) / 1024);
            } else {
                $res[$domain] = "#HTTP-ERROR {$info['http_code'] }  for : {$info['url']}";
            }
        } else {
            $res[$domain] = sprintf("#CURL-ERROR %d: %s ", $curlErrorCode, curl_error($curl_array[$i]));
        }
        curl_multi_remove_handle($mh, $curl_array[$i]);
        curl_close($curl_array[$i]);
        flush();
        ob_flush();
    }
    curl_multi_close($mh);
    return $res;
}

it is possible that this is a bug with php-curl. 这可能是php-curl的错误。 when the following line is removed, then everything behaves ok: 当删除以下行时,一切都行为正常:

if(strlen(curl_error($curl_handle1))) trigger_error("curl error: [".curl_error($curl_handle1)."]", E_USER_ERROR);

as far as i can tell, curl ing a host that is down is corrupting $curl_handle1 in some way that the curl_error() function is not prepared for. 据我所知, curl一个正在关闭的主机正在以某种方式破坏$curl_handle1 ,因为curl_error()函数没有准备好。 to get around this problem (until a bug fix is made) just test if the http_code returned by curl_getinfo() is 0 . 要解决这个问题(直到一个bug修复制成)只是测试,如果http_code由归国curl_getinfo()0 if it is 0 then do not use the curl_error function: 如果为0则不要使用curl_error函数:

if($multi_errors != CURLM_OK) trigger_error("curl error [$multi_errors]: ".curl_error($curl_multi_handle), E_USER_ERROR);
$curl_info = curl_getinfo($curl_handle1); //info for individual requests
$is_up = ($curl_info['http_code'] == 0) ? 0 : 1;
if($is_up && strlen(curl_error($curl_handle1))) trigger_error("curl error: [".curl_error($curl_handle1)."]", E_USER_ERROR);

its not a very elegant solution, but it may have to do for now. 它不是一个非常优雅的解决方案,但它现在可能必须要做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM