PHP shell_exec 在 CURL 命令中插入 CR 字符,导致服务器错误 500

PHP shell_exec inserts CR character in CURL command, leading to server error 500

我使用以下测试程序来检索网站的内容:

<?php

function getData( $url, $output ) {
    // set the path for CURL
    if (file_exists( '/var/lib')) 
        $curl = 'curl';
    else
        $curl = 'curl.exe';
    $curl .= ' --trace trace.txt --header "User-Agent: Some-Agent/1.0" ';
    echo "\nreading $url...\n";
    $buffer = shell_exec( "$curl -i \"$url\"" );
    // if this is a 301 redirection URL, follow it one step
    if ((preg_match( '~^HTTP.+? 301 ~', $buffer )) and preg_match( '~Location: (.+)~', $buffer, $location )) {
        $cmd = "$curl -i \"$location[1]\"";
        echo "$cmd\n";
        $buffer = shell_exec( $cmd );
    }
    file_put_contents( $output, $buffer );
}

// test with a URL that will be redirected:
getData( "http://www.onvista.de/aktien/fundamental/EISEN-UND-HUETTENWERKE-AG-Aktie-DE0006055007", "DE0006055007-AG.html" );

在我的 windows 机器上,这段代码运行良好。在 linux 机器上它 returns 500 内部服务器错误。 这是跟踪文件的开始 trace.txt:

== Info: About to connect() to www.onvista.de port 80 (#0)<br>
== Info:   Trying 217.11.205.10... == Info: connected<br>
== Info: Connected to www.onvista.de (217.11.205.10) port 80 (#0)<br>
=> Send header, 130 bytes (0x82)<br>
0000: 47 45 54 20 2f 61 6b 74 69 65 6e 2f 66 75 6e 64 GET /aktien/fund<br>
0010: 61 6d 65 6e 74 61 6c 2f 31 53 54 2d 52 45 44 2d amental/1ST-RED-<br>
0020: 41 47 2d 41 6b 74 69 65 2d 44 45 30 30 30 36 30 AG-Aktie-DE00060<br>
0030: 35 35 30 30 37 0d 20 48 54 54 50 2f 31 2e 31 0d 55007. HTTP/1.1.<br>
0040: 0a 48 6f 73 74 3a 20 77 77 77 2e 6f 6e 76 69 73 .Host: www.onvis<br>
0050: 74 61 2e 64 65 0d 0a 41 63 63 65 70 74 3a 20 2a ta.de..Accept: *<br>
0060: 2f 2a 0d 0a 55 73 65 72 2d 41 67 65 6e 74 3a 20 /*..User-Agent: <br>
0070: 53 6f 6d 65 2d 41 67 65 6e 74 2f 31 2e 30 0d 0a Some-Agent/1.0..<br>
0080: 0d 0a                                           ..<br>
<= Recv header, 36 bytes (0x24)<br>
0000: 48 54 54 50 2f 31 2e 31 20 35 30 30 20 49 6e 74 HTTP/1.1 500 Int<br>
0010: 65 72 6e 61 6c 20 53 65 72 76 65 72 20 45 72 72 ernal Server Err<br>
0020: 6f 72 0d 0a  <br>

windows 跟踪和这个跟踪之间的唯一区别是文件名后的一个 CR 字符(以 DE0006055007 结尾)。我是如何到达那里的,我该如何抑制它?(不,我不想使用会导致其他问题的 PHP cURL 模块。)

您应该以 \r\n 结束的 http headers。如果检测到输出是 tty,linux 上的 curl 似乎会将它们转换为 \n,但尝试重定向到一个文件,您会在其中看到 \rs .

preg_match 中的

. 也匹配 \r 字符,因此它成为 $location[1] 的一部分。简单的解决方法就是trim吧。

这不会发生在 windows 上,只是因为您可以执行 curl -i "http://google.com。报价由换行后的 shell 自动结束。

你真的应该使用 escapeshellarg