使cURL输出STDERR为文件(或字符串)

时间:2012-01-15 09:46:01

标签: php curl stderr verbose

我们正在尝试调试服务器上的一些cURL错误,我希望看到STDERR日志。目前,我们所能看到的错误是“错误代码:7”,我们无法连接到目标服务器。我们已联系主持人并制定了特殊规则来打开我们需要的端口,我们暂时忽略了证书。

仍然,我们无法连接。我需要对此进行调试,但我无法在最终看到任何相关信息。

我认为提及“VERBOSE”和“STDERR”的路线是最重要的。没有任何内容写入$ curl_log。我究竟做错了什么?按照手册逻辑,这应该是正确的......

正在使用PHP:

<?php
$curl = curl_init();
$curl_log = fopen("curl.txt", 'w');
$url = "http://www.google.com";

curl_setopt_array($curl, array(
    CURLOPT_URL             => $url,        // Our destination URL
    CURLOPT_VERBOSE         => 1,           // Logs verbose output to STDERR
    CURLOPT_STDERR          => $curl_log,   // Output STDERR log to file
    CURLOPT_SSL_VERIFYPEER  => 0,           // Do not verify certificate
    CURLOPT_FAILONERROR     => 0,           // true to fail silently for http requests > 400
    CURLOPT_RETURNTRANSFER  => 1            // Return data received from server
));

$output = fread($curl_log, 2048);
echo $output; // This returns nothing!
fclose($curl_log);

$response = curl_exec($curl);
//...restofscript...
?>

来自PHP手册:http://php.net/manual/en/function.curl-setopt.php

  

CURLOPT_VERBOSE TRUE输出详细信息。将输出写入STDERR    CURLOPT_STDERR 输出错误的替代位置,而不是STDERR。

这也不是权限问题,我已经在服务器端为777设置了文件和脚本权限,而我的本地客户端是Windows,并且从不关心权限设置(它只适用于dev)。

6 个答案:

答案 0 :(得分:6)

你在例子中犯了几个错误:

1)您必须在阅读“详细日志”之前调用curl_exec(),因为curl_setopt()不会执行任何操作,因此之前无法记录任何内容到curl_exec()。

2)只是为了写入而打开$curl_log = fopen("curl.txt", 'w');,所以即使在您写入文件并回放内部文件指针之后也无法读取任何内容。

因此,正确的缩短代码应如下所示:

<?php
$curl = curl_init();
$curl_log = fopen("curl.txt", 'rw'); // open file for READ and write
$url = "http://www.google.com";

curl_setopt_array($curl, array(
    CURLOPT_URL             => $url,
    CURLOPT_VERBOSE         => 1,
    CURLOPT_STDERR          => $curl_log,
    CURLOPT_RETURNTRANSFER  => 1
));

$response = curl_exec($curl);

rewind($curl_log);
$output= fread($curl_log, 2048);
echo "<pre>". print_r($output, 1). "</pre>";
fclose($curl_log);

// ...

?>

注意:详细日志可能超过2048字节,因此您可以在curl_exec()之后“fclose”$ curl_log,然后使用例如file_get_contents()读取整个文件。 在这种情况下,点 2)不应被视为错误: - )

答案 1 :(得分:6)

派对有点晚了,但是这个页面在谷歌中仍然很高,所以我们走吧。

如果CURLINFO_HEADER_OUT也设置为TRUE,似乎CURLOPT_VERBOSE不会记录任何内容。

这是PHP中的一个已知错误(#65348),并且由于他们决定不修复它的原因。

答案 2 :(得分:1)

将上面的答案放在一起,我使用此函数创建一个带有loggin到文件选项的Curl Post请求:

function CURLPostRequest($url, array $post = NULL, array $options = array(), $log_file = NULL){
    $defaults = array(
            CURLOPT_POST => 1,
            CURLOPT_HEADER => 0,
            CURLOPT_URL => $url,
            CURLOPT_FRESH_CONNECT => 1,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_FORBID_REUSE => 1,
            CURLOPT_TIMEOUT => 4,
            CURLOPT_POSTFIELDS => http_build_query($post)
    );

    if (is_resource($log_file)){
        $defaults[CURLOPT_VERBOSE]=1;
        $defaults[CURLOPT_STDERR]=$log_file;
        $defaults[CURLINFO_HEADER_OUT]=1;
    }

    $ch = curl_init();
    curl_setopt_array($ch, ($options + $defaults));
    if( ! $result = curl_exec($ch)){
        throw new Exception(curl_error($ch));
    }

    if (is_resource($log_file)){

        $info = curl_getinfo($ch);

        if (isset($info['request_header'])){
            fwrite($log_file, PHP_EOL.PHP_EOL.'* POST Content'.PHP_EOL.PHP_EOL);
            fwrite($log_file, print_r($info['request_header'],true));
            fwrite($log_file, http_build_query($post));
        }

        fwrite($log_file, PHP_EOL.PHP_EOL.'* Response Content'.PHP_EOL.PHP_EOL);
        fwrite($log_file, $result.PHP_EOL.PHP_EOL);
    }

    curl_close($ch);
    return $result;
}

希望对某人有所帮助。

答案 3 :(得分:0)

从php手册中获取函数curl_setopt:

CURLOPT_FILE The file that the transfer should be written to. The default is STDOUT (the browser window).  

答案 4 :(得分:0)

你应该把

$output = fread($curl_log, 2048);
echo $output; // This returns nothing!
fclose($curl_log);

$response = curl_exec($curl);之后,文件在curl执行期间关闭。

答案 5 :(得分:0)

我需要先关闭文件,然后才能读取文件,这对我有用:

$filename = 'curl.txt';
$curl_log = fopen($filename, 'w'); // open file for write (rw, a, etc didn't help)
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, $curl_log);        

$result = curl_exec($ch);

fclose($curl_log);      
$curl_log = fopen($filename, 'r'); // open file for read
$output= fread($curl_log, filesize($filename));
echo $output;

(PHP 5.6.0,Apache / 2.2.15)