ホームページ >バックエンド開発 >PHPチュートリアル >win2003_PHP チュートリアルで preg_match_all を使用することによって引き起こされる Apache クラッシュの解決策

win2003_PHP チュートリアルで preg_match_all を使用することによって引き起こされる Apache クラッシュの解決策

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBオリジナル
2016-07-13 10:57:121139ブラウズ

この記事では、win2003 で preg_match_all を使用すると Apache がクラッシュする問題の解決策を紹介します。このような問題に遭遇した友人は参考にしてください。

Apache/2.2.9 (Win32) + PHP/5.2.17、分析と一致比較に正規表現 preg_match_all (preg_match_all("/ni(.*?)wo/", $html, $matches); など) を使用文字列 $html が長い場合 (通常、収集された Web ページのソース コードを分析するために使用される 100,000 バイトを超える)、Apache サーバーはクラッシュし、自動的に再起動します。

Apache エラー ログに次のプロンプトがあります:

[Thu Apr 11 18:31:31 2013] [通知] 親: 子プロセスがステータス 128 で終了しました -- 再起動中です。
[Thu Apr 11 18:31:31 2013] [通知] Apache/2.2.9 (Win32) PHP/5.2.17 設定済み -- 通常の操作を再開します
[Thu Apr 11 2013 18:31:31] [お知らせ] サーバー構築: Jun 13 2008 04:04:59
[Thu Apr 11 18:31:31 2013] [お知らせ] 親: 子プロセス 2964 を作成しました
[Thu Apr 11 18:31:31 2013] [お知らせ] WinSock2 API AcceptEx() の使用禁止
[Thu Apr 11 18:31:31 2013] [通知] 子 2964: 子プロセスが実行中です
[Thu Apr 11 18:31:31 2013] [お知らせ] Child 2964: 開始ミューテックスを取得しました
[Thu Apr 11 18:31:31 2013] [通知] Child 2964: 350 ワーカー スレッドを開始します。
[Thu Apr 11 18:31:31 2013] [通知] Child 2964: ポート 80 でリッスンしています

Apache 公式およびフォーラムの情報を調べた結果、Win プラットフォームで通常の preg_match_all または preg_match を使用して比較的長い文字列を分析する場合、Apache のクラッシュと再起動の原因は、Windows プラットフォームでデフォルトで割り当てられたスレッド スタック スペース ThreadStackSize であることがわかりました。小さすぎます。 win32 のデフォルト値はわずか 256KB ですが、Linux のデフォルト値は 8M です。これが、同じプログラムが Linux プラットフォームでは正常に動作するのに、Win プラットフォームでは正常に動作しない理由です。

PCRE ライブラリの公式説明によると、256 KB のスタック領域に対応する pcre.recursion_limit サイズは 524 を超えてはなりません。
以下は、さまざまな実行可能スタック サイズに対する pcre.recursion_limit の安全な値の表です:
以下は、Stacksize と pcre.recursion_limit に対応する推奨安全値です。この値を超えると、スタック オーバーフローが発生する可能性が高く、Apache がクラッシュします。

スタックサイズ pcre.recursion_limit

64 MB 134217
32 MB 67108
16 MB 33554
8MB16777
4MB8388
2MB 4194
1MB2097
512KB 1048
256 KB 524
スタック サイズを調整していない場合は、正規表現を使用して PHP ページの先頭にスタック サイズを追加する必要があります:

ini_set("pcre.recursion_limit", "524"); // PHP のデフォルトは 100,000 です
?>

特定のエラーを表示するには、次のコードを使用できます:

代码如下 复制幣
$resultsArray = preg_match_all("/table.*?/isU", $html, $contents);
if ($resultsArray === 0){
echo get_pcre_err();
}
関数 get_pcre_err(){
        $pcre_err = preg_last_error();  // PHP 5.2 以降。
        if ($pcre_err === PREG_NO_ERROR) {
            $msg = '不一致に成功しました。';
        } その他 {
            // preg_match エラー!
            スイッチ ($pcre_err) {
                ケース PREG_INTERNAL_ERROR:
                    $msg = 'PREG_INTERNAL_ERROR';
                    休憩;
                ケース PREG_BACKTRACK_LIMIT_ERROR:
                    $msg = 'PREG_BACKTRACK_LIMIT_ERROR';
                    休憩;
                ケース PREG_RECURSION_LIMIT_ERROR:
                    $msg = 'PREG_RECURSION_LIMIT_ERROR';
                    休憩;
                ケース PREG_BAD_UTF8_ERROR:
                    $msg = 'PREG_BAD_UTF8_ERROR';
                    休憩;
                ケース PREG_BAD_UTF8_OFFSET_ERROR:
                    $msg = 'PREG_BAD_UTF8_OFFSET_ERROR';
                    休憩;
                デフォルト:
                    $msg = '認識できない PREG エラー';
                    休憩;
            }
        }
    return($msg);
}

通常の修飾子の説明は U:
i: 大文字と小文字を区別する、つまり大文字と小文字を区別しないことを意味します
s: PCRE_DOTALL、ドットが改行文字と一致できることを示します。
U: PCRE_UNGREEDY を意味します。これは非貪欲を意味し、perl/Python 言語の .*? に相当します。 .* 正規表現の場合、一致を待つのではなく、すぐに実行されます。 .* すべての文字を検索して 1 つずつ返します
正規表現を使用する場合は、スタック オーバーフローが発生しやすい再帰呼び出しを避けるように努める必要があります。例:
//isU を使用するとエラーが発生しますが、//i を使用すると正常に動作します。


では、Win プラットフォームで ThreadStackSize のサイズを増やすにはどうすればよいでしょうか? Apache 構成ファイル httpd.conf で「Include conf/extra/httpd-mpm.conf」を有効にし (前のコメント # を削除)、httpd-mpm.conf ファイルの mpm_winnt_module 構成モジュールで「ThreadStackSize 8400000」を設定します。はい(約8M)。

コードは次のとおりです コードをコピー



スレッドスタックサイズ 8400000
子供あたりのスレッド数 200
子供あたりの最大リクエスト数 10000
Win32DisableAcceptEx

ここで、32 ビット Apache プログラムは最大約 2GB のメモリ空間しか使用できないことに注意してください。 したがって、ThreadStackSize と ThreadsPerChild を乗算した値 (8M * 200) が 2G を超えてはなりません。2G を超えない場合、Apache を起動できず、表示されるエラー ログは次のとおりです。
[Thu Apr 11 20:02:45 2013] [crit] (OS 8) このコマンドを処理するにはストレージ容量が不十分です。 : 子 4832: _beginthreadex が失敗しました。ThreadsPerChild 構成ディレクティブで要求された 220 個のスレッドのうち 212 個が作成されました。 上記のヒントを通じて、Piaoyi は、私のサーバーでは、スレッド スタック サイズが 8M に設定されている場合、設定できるスレッドの最大数は 212 であることがわかります。

http://www.bkjia.com/PHPjc/632107.htmlwww.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/632107.html技術記事この記事では、win2003 で preg_match_all を使用することによって引き起こされる Apache のクラッシュの解決策を紹介します。このような問題に遭遇した友人は参考にしてください。 Apache/2.2.9 (Win32) + PHP/5.2.17、...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。