PHPでCurlのタイムアウトを設定する


230

PHPを介してeXistデータベースでcurlリクエストを実行しています。データセットは非常に大きいため、データベースはXML応答を返すために一貫して長い時間を要します。これを修正するために、長いタイムアウトになるはずのカールリクエストを設定します。

$ch = curl_init();
$headers["Content-Length"] = strlen($postString);
$headers["User-Agent"] = "Curl/1.0";

curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:');
curl_setopt($ch,CURLOPT_TIMEOUT,1000);
$response = curl_exec($ch);
curl_close($ch);

ただし、curlリクエストは、リクエストが完了する前に一貫して終了します(ブラウザ経由でリクエストされた場合は<1000)。これがcurlでタイムアウトを設定する適切な方法であるかどうか誰かが知っていますか?

回答:


346

ドキュメントを参照してください:http : //www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT-接続を試みる間に待機する秒数。無期限に待機するには0を使用します。
CURLOPT_TIMEOUT-cURL関数の実行を許可する最大秒数。

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds

また、phpスクリプトの実行時間を拡大することを忘れないでください:

set_time_limit(0);// to infinity for example

13
set_time_limit(0);スクリプトがコンソールで実行されている場合は必要ありません。
CONvid19 2016年

6
@PedroLobitoは、cli上のphpのデフォルト設定ですが、変更されている可能性があります。
cherouvim 2017

4
@cherouvimは明らかに(ここでは正しいだけで実行しているphp -d max_execution_time=1 -r 'while(true){$r=1*1;}'CLIは魔法「は常に無制限」フラグを持っていないことを行動で観察するか何か。
Wrikken

@Pedro Lobito set_time_limit(0)ループ内で使用しない場合は不要です。
Viktor Joras 2018

58

うーん、CURLOPT_TIMEOUTcURL関数の実行にかかる時間を定義しているように見えます。CURLOPT_CONNECTTIMEOUT接続が完了するまで待機する最大時間をcURLに通知するので、実際には代わりに見ておくべきだと思います。


一方でPHPのドキュメント言うが、CURLOPT_TIMEOUT機能にかかる時間についてです、基本となるカールライブラリのドキュメントがないことを確認するものを読むための方法-面白い区別している、それは要求にかかる時間についてだと言うように見えます!
fideloper、2015

私はここだと思う最高の解釈です:stackoverflow.com/questions/27776129/...
fideloper

33

これには、一部の人々に関連するかもしれない癖があります... PHPのドキュメントのコメントから。

1秒未満でcURLをタイムアウトさせたい場合は、を使用できますCURLOPT_TIMEOUT_MS。ただし、「Unixのようなシステム」には、値が1000ミリ秒未満の場合に「cURL」エラーでlibcurlがすぐにタイムアウトするバグ/「機能」があります。エラー(28):タイムアウトに達しました。」この動作の説明は次のとおりです。

「libcurlが標準のシステム名リゾルバーを使用するように構築されている場合、転送のその部分は、タイムアウトに1秒の許容される最小タイムアウトで、フル秒の解決を引き続き使用します。」

これがPHP開発者にとって意味することは、「libcurlが標準のシステム名リゾルバーを使用しているかどうかがわからないため、最初にテストせずにこの関数を使用することはできません(ただし、それはかなり確実です)」。

問題は、(Li | U)nixでは、libcurlが標準の名前リゾルバーを使用するときに、libcurlがタイムアウトアラームであると考える名前解決中にSIGALRMが発生することです。

解決策は、CURLOPT_NOSIGNALを使用して信号を無効にすることです。タイムアウトをテストできるように、10秒の遅延を引き起こすことを要求するスクリプトの例を次に示します。

if (!isset($_GET['foo'])) {
    // Client
    $ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    // Server
    sleep(10);
    echo "Done.";
}

http://www.php.net/manual/en/function.curl-setopt.php#104597から


こんにちは、このコードは機能しますが、ソースファイルは7 MBで、ダウンロードは52 KBしかありません。何が問題なのでしょうか。URLは、webserver.tld / folder / download /…の
Muflix

@Simon東は、あなたは私を助けてくださいすることができますstackoverflow.com/questions/30861112/...
ネイサンSrivi

このスクリプトではタイムアウトエラーが発生することが予想されることに注意してください
kmoney12


13

あなたとファイルの間のタイムアウトについて確認する必要があります。この場合、PHPとCurlです。

転送がまだアクティブなときにタイムアウトしないようにCurlに指示するには、の代わりにに設定CURLOPT_TIMEOUTする必要があります。01000

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

PHPでも、時間制限を削除する必要があります。そうしないと、PHP自体(デフォルトでは30秒後)がCurlの要求に応じてスクリプトを強制終了します。これだけで問題が解決します
さらに、データの整合性が必要な場合は、次を使用してセキュリティの層を追加できますignore_user_abort

# The maximum execution time, in seconds. If set to zero, no time limit is imposed.
set_time_limit(0);

# Make sure to keep alive the script when a client disconnect.
ignore_user_abort(true);

クライアントの接続が切断されると、スクリプトの実行が中断され、データが損傷する可能性があります
。非一時的なデータベースクエリ、構成ファイルの構築など、あなたの場合、それは部分的なファイルをダウンロードします...そして、あなたはこれを気にするかもしれませんし、しないかもしれません。

このスレッドはエンジン検索で一番上にあるので、この古い質問に答えますCURL_TIMEOUT


8

ブラウザからリクエストを実行することはできません。CURLリクエストを実行しているサーバーが応答するのを待ってタイムアウトします。ブラウザはおそらくデフォルトのネットワークタイムアウトである1〜2分でタイムアウトします。

コマンドライン/ターミナルから実行する必要があります。


2
+1-タイムアウトはおそらくcurlの外部にあります。定期的に何かを出力することを確認することで、実際にブラウザのタイムアウトを回避できます。ブラウザは通常、より多くのデータを受信するたびにタイムアウトをリセットします。しかし、それはハックです。CLIを介して実行することは(ほぼ?)常に望ましいです。
フランクファーマー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.