[PHP-users 28997] Re: curl関数によるデータ収集について

Reiji Matsumoto matsumoto @ spline.oc.to
2006年 4月 13日 (木) 17:09:06 JST


松本と申します。

> ある程度動くものが作られ、一定の成果を得ているのですが、かなり高い確立で
> プログラムの途中で応答なしの状態になってしまい、実行が中断されてしまうとい
う
> 現象に
> 悩まされております。

一般的な話しになりますが、phpを精々数秒で処理が完結するwebページ表示用の
スクリプトでは無く、処理が数時間に及ぶコマンドライン起動のスクリプトと
して利用するような場合、それなりにメモリに注意を払わないとまずい
です。phpは基本的にリークはしませんが、スクリプトが終わるまでどんどん
メモリが消費されてしまうという事があります。その結果利用可能メモリが
無くなり、予期せぬ結果になってしまったりする事があります。

また、組み込まれているリソース確保型の関数群も、一回のメソッド発行で破棄
される、使い捨て的な利用方法を前提にしている場合があり、phpにおけるcurl
の実装にも、そのような側面があります。

つまり、

>
>     $ch = curl_init();
>     curl_setopt($ch, CURLOPT_URL, $url);
>     curl_setopt($ch, CURLOPT_USERAGENT, $global_values["user_agent"]);
>     curl_setopt($ch, CURLOPT_TIMEOUT, 10);
>     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
>     $html = curl_exec($ch);
>     curl_close($ch);
>
上記プログラムは当然抜粋だと思いますが、本件ではループの中に置かれて
いると思います。その際、ループの中でcurl_init()とcurl_close()を繰り返す
構造になっているでしょうか。例えば

while(条件) {
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_USERAGENT, $global_values["user_agent"]);
     curl_setopt($ch, CURLOPT_TIMEOUT, 10);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     $html = curl_exec($ch);
     curl_close($ch);
}

このような構造でしょうか。これならば問題ありませんが、

$ch = curl_init();
while(条件) {
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_USERAGENT, $global_values["user_agent"]);
     curl_setopt($ch, CURLOPT_TIMEOUT, 10);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     $html = curl_exec($ch);
}
curl_close($ch);

このような構造になっていると、curl_exec()を実行するたびに少しずつ解放
されないメモリが蓄積されていき、いずれ動かなくなります。

私は php-4.3.x + linux + curl-7.10.4 で、この問題に遭遇しました。
OS含めご利用中の環境と大分違うようですので、参考にならなかったらごめんなさ
い。




PHP-users メーリングリストの案内