当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    win2003下PHP使用preg

    栏目:win服务器问题汇总 时间:2018-12-15 09:19

    这篇文章主要介绍了win2003下PHP使用preg_match_all导致apache崩溃问题的解决方法,详细的分析了问题产生原因以及解决方案,需要的朋友可以参考下

    小编的平台是windows server 2003(32位系统) + Apache/2.2.9 (Win32) + PHP/5.2.17,在使用正则表达式 preg_match_all (如 preg_match_all("/ni(.*?)wo/", $html, $matches);)进行分析匹配比较长的字符串 $html 时(大于10万字节,一般用于分析采集回来的网页源码),Apache服务器会崩溃自动重启。
        在Apache错误日志里有这样的提示:
    复制代码 代码如下:[Thu Apr 11 18:31:31 2013] [notice] Parent: child process exited with status 128 -- Restarting.
    [Thu Apr 11 18:31:31 2013] [notice] Apache/2.2.9 (Win32) PHP/5.2.17 configured -- resuming normal operations
    [Thu Apr 11 18:31:31 2013] [notice] Server built: Jun 13 2008 04:04:59
    [Thu Apr 11 18:31:31 2013] [notice] Parent: Created child process 2964
    [Thu Apr 11 18:31:31 2013] [notice] Disabled use of AcceptEx() WinSock2 API
    [Thu Apr 11 18:31:31 2013] [notice] Child 2964: Child process is running
    [Thu Apr 11 18:31:31 2013] [notice] Child 2964: Acquired the start mutex.
    [Thu Apr 11 18:31:31 2013] [notice] Child 2964: Starting 350 worker threads.
    [Thu Apr 11 18:31:31 2013] [notice] Child 2964: Listening on port 80.
        经过查阅Apache官方以及论坛资料后,发现win平台下用正则 preg_match_all 或preg_match 分析比较长的字符串时,导致apache崩溃重启的原因是windows平台下默认分配的线程堆栈空间 ThreadStackSize 太小导致的。 win32默认只有256KB,而在 linux下默认值是 8M,这就是为什么同样的程序在 linux平台下正常,而在 win平台下不正常的原因。
        根据PCRE library的官方说明:256 KB 的堆栈空间对应的pcre.recursion_limit大小应该不超过524。
    Here is a table of safe values of pcre.recursion_limit for a variety of executable stack sizes:
    下面就是一张Stacksize和pcre.recursion_limit对应的建议安全值,超过这个数值就极有可能发生堆栈溢出,apache crash:
    复制代码 代码如下:Stacksize   pcre.recursion_limit
     64 MB      134217
     32 MB      67108
     16 MB      33554
      8 MB      16777
      4 MB      8388
      2 MB      4194
      1 MB      2097
    512 KB      1048
    256 KB      524

    如果你没有调整堆栈大小,就必须在使用正则的PHP页面最开头加入:
    复制代码 代码如下:<?php
    ini_set("pcre.recursion_limit", "524"); // PHP default is 100,000.
    ?>

    查看具体的错误可以使用下面的代码:
    复制代码 代码如下:$resultsArray = preg_match_all("/table.*?<a>/isU", $html, $contents);
    if ($resultsArray === 0){
    echo get_pcre_err();
    }
    function get_pcre_err(){
            $pcre_err = preg_last_error();  // PHP 5.2 and above.