问题 curl_exec导致php脚本停止做任何事情


当我在特定网址上运行curl时,网站停止响应并且不会生成错误,尽管我已将错误报告设置为打开。我已经尝试将curl超时设置为低值,然后它会生成错误,所以我知道它不会超时。

我想知道的主要事情是,怎么会发生这种情况,我怎么能弄明白为什么?

我试图访问的网址是对Factual api的调用,以及我在这里使用的网址

http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={ “类别”: “汽车”, “$ LOC”:{ “内$”:{ “$中心”:[[41,-74],80467.2]}})

将它放入浏览器时可以正常工作。如果您将纬度和经度更改为基本上任何其他值,则php脚本将按预期工作。

error_reporting(E_ALL);
ini_set('display_errors', '2');
$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";
Echo "\n\n1";

$ch = curl_init($url);
Echo 2;
curl_setopt($ch, CURLOPT_HEADER, 0);
Echo 3;
curl_setopt($ch, CURLOPT_POST, 1);
Echo 4;
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT,30);
Echo 5;
$output = curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch));   
Echo 6;
curl_close($ch);
Echo "out: ".$output;

2481
2018-02-14 17:29


起源

您可以尝试设置不同的用户;我们以前遇到过垃圾邮件问题,而且我们用不喜欢的用户做有趣的事情。 - Glen Solsberry
此外,发布您的API密钥可能不是一个好主意 - DFectuoso
一件事: $output = curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch)); 不会做你期望的。基本上,它正在做 $output = (curl_exec($ch) or die("hhtrjrstjsrjt".curl_error($ch))); 因为它返回一个布尔值而不是一个字符串。相反,要么将错误检查移动到下一行,要么将其显式分组,如下所示: ($output = curl_exec($ch)) or die("hhtrjrstjsrjt".curl_error($ch)); - ircmaxell
ircmaxell,这里令我困惑的主要事情是它永远不会到达下一行,即使没有“或死”。将useragent更改为我的浏览器似乎也没有做任何事情。 - John
我遇到了同样的问题。不会抛出任何错误,脚本就会死掉。 - HappyDeveloper


答案:


看起来您的PHP配置文件中存在一些错误。

要修复错误,您必须编辑您的错误 php.ini 文件。

要在开发模式下显示错误,请更改 error_reporting 价值 E_ALL

error_reporting=E_ALL

然后你必须启用cURL扩展。 要在php.ini中启用它,您必须取消注释以下行:

extension=php_curl.dll

编辑此值后,请不要忘记重新启动Web服务器(Apache或Nginx)

我同意你的同事们的意见 url_encode 你的JSON字符串。

从我的角度来看,代码应该是:

<?php
ini_set('display_errors', '1');
error_reporting(E_ALL);

$apiKey = '*apikey*';
$filters = '{"category":"Automotive","$loc":{"$within":{"$center":[[41,-74],80467.2]}},"website":{"$blank":false}}';
$params = '?api_key=' . $apiKey . '&filters=' . url_encode($filters);

$url = 'http://api.factual.com/v2/tables/bi0eJZ/read';
$url .= $params;

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$output = curl_exec($ch) or die("cURL Error" . curl_error($ch));   
curl_close($ch);

echo "out: " . $output;

编辑:

另一种方法可能是使用Factual API的官方PHP驱动程序: Factual API的官方PHP驱动程序

它提供了一个 调试模式 用一个 cURL调试输出 和a 异常调试输出


3
2017-07-18 18:25



谢谢。我忽略了取消注释 extension=php_curl.dll。 - Ray Goudie


您的网址不是url_encoded,因为CURL是一个外部应用程序,必须转义,您的浏览器将自动url_encode params在URL上,但是你可能会破坏服务器上的卷曲并且它正在停止。

尝试改变这个:

$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";

至:

$url_filters = '{"category":"Automotive","$loc":{"$within":{"$center":[[41,-74],80467.2]}},"website":{"$blank":false}}';

$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters=".urlencode($url_filters);

但是,我确实有一些问题,你的电话是否正确? litlal“$ loc”的关键是正确的吗?

更新后不需要反斜杠所有单引号都不支持变量替换,并允许双引号而不转义它们


2
2017-07-18 12:38





我曾经使用过香草PHP的CURL调用。 CURL调用是其中的一部分 curl 类。正如其他用户所建议的那样 url_encode($url) 函数将准备字符串以供此特定类使用。如果你不运行它,那么你可以传入会破坏处理程序的URL(例如,通过使用无效字符或URL语法)。

最重要的是,您似乎正在尝试将JSON对象直接传递到页面的URL中。我不认为在这样的curl调用中使用JSON包是最佳做法。如果这是您要查看的内容,请参阅此页面: 如何使用Curl从终端/命令行发布JSON数据到测试Spring REST?


2
2017-07-18 16:25





在我的情况下,卷曲失败的原因是托管服务提供商用Litespeed取代了Apache,而litespeed在卷曲请求期间终止了这个过程。

php.ini设置没有解决这个问题,因为lsphp每次都会在30秒后终止。

我们进行了长时间的聊天,我确信他们的服务器实际上已经坏了(最终)。

为了使其他可能有类似或相关问题的人更清楚:
我的PHP脚本正在运行,并且PHP中没有记录任何错误,因为整个PHP进程(包括错误记录器)都被Web服务器终止。


2
2017-07-18 06:02





此代码仅用于测试,只需根据我的代码修改您的代码

<?php   

$useragent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.10 (KHTML, like Gecko)
Chrome/8.0.552.224: Safari/534.10'; // notice this
$url="http://api.factual.com/v2/tables/bi0eJZ/read?api_key=*apikey*&filters={\"category\":\"Automotive\",\"\$loc\":{\"\$within\":{\"\$center\":[[41,-74],80467.2]}},\"website\":{\"\$blank\":false}}";
$ch = curl_init(); // notice this

curl_setopt($ch, CURLOPT_URL, $url); // notice this
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

curl_setopt($ch, CURLOPT_USERAGENT, $useragent);




$contents = curl_exec($ch);
echo $contents;
?>

1
2018-05-05 19:38



对于我们这些在家里跟随的人...如果你解释了你改变了什么以及为什么你改变了它会很好:)你可能会注意到 - 像这样的问题在网站上停留了很长时间并且被发现者其他人,也许几个月后,谁有类似的问题,并希望从中学习:)谢谢。 - Taryn East
这也适用于使用双引号我确定花括号是为php中的变量。如果URL中的参数是URLencoded? - Martin Barker


为了将来的利益:

  1. 使用 进行urlencode 用于查询参数作为过滤器参数 包含许多对URL不安全/有效的字符

  2. 使用 curl_getinfo() 查看有关http_code和。的信息 其他有用的信息。


1
2017-07-19 14:15





脚本停止做任何事情你可以在这里找到它:

http://php.net/manual/en/function.set-time-limit.php

摘抄:

set_time_limit()函数和配置指令max_execution_time仅影响脚本本身的执行时间。在确定脚本运行的最长时间时,不会包括在执行脚本之外发生的任何活动,例如使用system()的系统调用,流操作,数据库查询等。在测量时间真实的Windows上,情况并非如此。

所以基本上,curl阻止所有的PHP脚本,基本上唯一真正运行的是curl,所以如果它永远阻止,你的网站将无法响应,这就是为什么你需要使用超时...

如何避免它,只需使用超时...


0
2017-07-19 22:04



如果PHP_CURL在主机系统上没有使用CURL本质上非常花哨的话,这通常是正确的 exec("curl ....")如果curl暂停用户输入php将等待并等待它,无论你将超时设置为多长时间。 - Martin Barker