首页 > 编程技术 > php

win2003使用preg_match_all导致apache崩溃解决办法

发布时间:2016-11-25 17:38

本文章来给大家介绍在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 时(大于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.
        if ($pcre_err === PREG_NO_ERROR) {
            $msg = 'Successful non-match.';
        } else {
            // preg_match error!
            switch ($pcre_err) {
                case PREG_INTERNAL_ERROR:
                    $msg = 'PREG_INTERNAL_ERROR';
                    break;
                case PREG_BACKTRACK_LIMIT_ERROR:
                    $msg = 'PREG_BACKTRACK_LIMIT_ERROR';
                    break;
                case PREG_RECURSION_LIMIT_ERROR:
                    $msg = 'PREG_RECURSION_LIMIT_ERROR';
                    break;
                case PREG_BAD_UTF8_ERROR:
                    $msg = 'PREG_BAD_UTF8_ERROR';
                    break;
                case PREG_BAD_UTF8_OFFSET_ERROR:
                    $msg = 'PREG_BAD_UTF8_OFFSET_ERROR';
                    break;
                default:
                    $msg = 'Unrecognized PREG error';
                    break;
            }
        }
    return($msg);
}

    对于正则的修饰符 isU 说明:
i: 表示in-casesensitive,即大小写不敏感
s: PCRE_DOTALL,表示点号可以匹配换行符。
U: 表示PCRE_UNGREEDY,表示非贪婪,相当于perl/python语言的.*?,在匹配过程中,对于.*正则,一有匹配立即执行,而不是等.*搜索了所有字符再一一返回
    在使用正则表达式时,我们应该尽量避免递归调用,递归容易导致堆栈溢出。比如:
/<table((?!<table).)*?</a>/isU 就会发生错误,而使用 /<table.*?</a>/i 就正常。


 那么如何增加win平台下 ThreadStackSize 的大小呢? 在apache的配置文件 httpd.conf 里启用 “Include conf/extra/httpd-mpm.conf”(删除前面的注释#),然后在 httpd-mpm.conf 文件里的 mpm_winnt_module 配置模块里设置 “ThreadStackSize 8400000”即可(大约8M)。

 代码如下 复制代码


<IfModule mpm_winnt_module>
    ThreadStackSize 8400000
    ThreadsPerChild      200
    MaxRequestsPerChild    10000
    Win32DisableAcceptEx
</IfModule>

这里需要注意的是,32位的Apache程序只能最多使用大约2GB内存空间! 因此,ThreadStackSize 和ThreadsPerChild 的值相乘后(8M * 200)不应该超过2G,否则无法启动apache,出现的错误日志如下:
[Thu Apr 11 20:02:45 2013] [crit] (OS 8)存储空间不足,无法处理此命令。  : Child 4832: _beginthreadex failed. Unable to create all worker threads. Created 212 of the 220 threads requested with the ThreadsPerChild configuration directive.
    通过上面的提示,飘易可以告诉大家的是在我的这台服务器上,当线程堆栈大小设为8M时,我可以设置的线程数最多是212个。

今天在配置apache与php环境时个人感觉配置好了,自己写了测试php文件都是可以成功执行了,但是在运行 phpMyAdmin时提示无法载入 mysql 扩展,
请检查 PHP 配置,后来经过排查找出了解决办法,下面分享给大 家。

环境配置好了我测试文件如一 a.php

 代码如下 复制代码

<?php
echo phpinfo();

$cn = mysql_connect('localhost','ttftroat','xxx') or die(mysql_error());
?>

输入结果是没有问题了,但我在利用phpmyadmin时提示

phpMyAdmin - 错误

无法载入 mysql 扩展,<br />请检查 PHP 配置 - 文档

解决办法

搜索“extension_dir = ./”,改成“extension_dir = C:phpext”,再把这些分号去了:

extension=php_mbstring.dll
extension=php_gd2.dll
extension=php_mysql.dll

再重启apache就解决了哦。

本文章来给在家介绍在php中IE7 iframe session丢失问题解决方案,有碰到此类问题的同学可进入参考参考

假设采用iframe方式,很可能会遇到这样的问题。而且这个问题只存 在于IE7浏览器中,我在firefox, IE6和chrome等浏览器中测试均没有问题


在运行session_start之前,在程序中加上如下一句(以php语言为例),大致是向浏览器声明一下安全级别,这样iframe子页面在创建session时就不会有问题了:

 代码如下 复制代码

header(’P3P: CP=”ALL ADM DEV PSAi COM OUR OTRo STP IND ONL”‘);

另外,我还了解到:如果二级域名中包含了下划线,如:your_domain.yourhost.com,在建立和传递session时也可能会出现问题。

 

导致php页面中中文乱码的问题有大量收集与解决办法,导致中文乱码一般是数据库与页面编码不一致引起的,下面我来给大家直接介绍解决办法。、


1.建立数据库的时候,选择utf-8编码

2.建立php 文件的时候选择UTF-8编码

3.防止数据传输中乱码 mysql_query('set names utf8');

4.在静态页面加上 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


个人建义:建议在进行开发之前把数据库、php文件、html charset三者的编码设置成一致的utf-8。

本文章来给大家介绍phpmyadmin无法连接:无效的设置解决办法,有需要了解的朋友可进入参考参考。

打开phpMyAdmin目录 找到phpMyAdmin的配置文件config.inc.php
将其中的

 代码如下 复制代码

$cfg['Servers'][$i]['auth_type'] = 'config';

 改为:

 代码如下 复制代码

$cfg['Servers'][$i]['auth_type'] = 'cookie';

标签:[!--infotagslink--]

您可能感兴趣的文章: