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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8868808/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 05:40:25  来源:igfitidea点击:

Make cURL output STDERR to file (or string)

phpcurlstderrverbose

提问by Radley Sustaire

We're trying to debug some cURL errors on the server, and I would like to see the STDERR log. Currently, all we can see for our error is "error code: 7" and that we can't connect to target server. We have contacted the host and made special rule to open the port we need and we're even ignoring the certificate for the time being.

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

Still, we can't connect. I need to debug this, but I can't see any pertinent information on my end.

尽管如此,我们还是无法连接。我需要调试这个,但我看不到任何相关信息。

The lines mentioning "VERBOSE" and "STDERR" are the most important, I think. Nothing is written to $curl_log. What am I doing wrong? Following the manuals logic, this should be correct...

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

PHP in use:

正在使用的 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...
?>

From PHP manual: http://php.net/manual/en/function.curl-setopt.php

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

CURLOPT_VERBOSETRUE to output verbose information. Writes output to STDERR CURLOPT_STDERRAn alternative location to output errors to instead of STDERR.

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

It is not a permission issue either, I have set file and script permissions to 777 on server side and my local client is windows and has never cared about permission settings (it's only for dev anyway).

这也不是权限问题,我已在服务器端将文件和脚本权限设置为 777,而我的本地客户端是 windows 并且从不关心权限设置(无论如何它只适用于开发人员)。

采纳答案by Jonez1

You are making couple mistakes in your example:

您在示例中犯了几个错误:

1)you have to call curl_exec()prior to reading from the "verbose log", because curl_setopt()doesn't perform any action, so nothing can be logged prior to the curl_exec().

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

2)you are opening $curl_log = fopen("curl.txt", 'w');only for write, so nothing could be read, even after you write to the file and rewind the internal file pointer.

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

So the correct shortened code should look like:

所以正确的缩短代码应该是这样的:

<?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);

// ...

?>

NOTE:verbose log could be longer than 2048 bytes, so you could "fclose" the $curl_log after curl_exec() and then read the whole file with for example file_get_contents(). In that case, the point 2)should not be considered as mistake :-)

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

回答by DavidKunz

A bit late to the party, but this page still pops up high in Google, so let's go.

聚会有点晚了,但这个页面仍然在谷歌中弹出,所以我们走吧。

It seems that CURLOPT_VERBOSE doesn't log anything if CURLINFO_HEADER_OUT is also set to TRUE.

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

This is a know bug in PHP (#65348), and due to reasons they decided not to fix it.

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

回答by ontananza

Putting al above answers together, I use this function to make a Curl Post Request with loggin to a file option:

将以上所有答案放在一起,我使用此函数来创建带有登录到文件选项的 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;
}

Hope this help to someone.

希望这对某人有所帮助。

回答by rkosegi

From php manual for function curl_setopt:

来自函数 curl_setopt 的 php 手册:

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

回答by Mine

You should put

你应该把

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

after $response = curl_exec($curl);otherwise, file is closed during curl is executing.

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

回答by Aba

I needed to close the file before being able to read it, this worked for me:

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

$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)

(PHP 5.6.0,Apache/2.2.15)