<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>smallfish logs &#187; Apache</title>
	<atom:link href="http://chenxiaoyu.org/blog/archives/category/apache/feed" rel="self" type="application/rss+xml" />
	<link>http://chenxiaoyu.org</link>
	<description>关注 Python &#38; Go &#38; PostgreSQL</description>
	<lastBuildDate>Sat, 07 Aug 2010 10:31:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Python(Stackless) + MongoDB Apache 日志(2G)分析</title>
		<link>http://chenxiaoyu.org/blog/archives/213</link>
		<comments>http://chenxiaoyu.org/blog/archives/213#comments</comments>
		<pubDate>Thu, 04 Mar 2010 01:49:34 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=213</guid>
		<description><![CDATA[为何选择Stackless？ http://www.stackless.com
Stackless可以简单的认为是Python一个增强版，最吸引眼球的非“微线程”莫属。微线程是轻量级的线程，与线程相比切换消耗的资源更小，线程内共享数据更加便捷。相比多线程代码更加简洁和可读。此项目是由EVE Online推出，在并发和性能上确实很强劲。安装和Python一样，可以考虑替换原系统Python。:)
为何选择MongoDB？ http://www.mongodb.org
可以在官网看到很多流行的应用采用MongoDB，比如sourceforge，github等。相比RDBMS有啥优势？首先在速度和性能上优势最为明显，不仅可以当作类似KeyValue数据库来使，还包含了一些数据库查询（Distinct、Group、随机、索引等特性）。再有一点特性就是：简单。不论是应用还是文档，还是第三方API，几乎略过一下就可以使用。不过有点遗憾的就是，存储的数据文件很大，超过正常数据的2-4倍之间。本文测试的Apache日志大小是2G，生产的数据文件有6G。寒&#8230;希望在新版里能有所缩身，当然这个也是明显的以空间换速度的后果。
本文除去上面提及到的两个软件，还需要安装pymongo模块。http://api.mongodb.org/python/
模块安装方式有源码编译和easy_install，这里就不再累赘。
1. 从Apache日志中分析出需要保存的资料，比如IP，时间，GET/POST，返回状态码等。
fmt_str  = '(?P&#60;ip&#62;[.\d]+) - - \[(?P&#60;time&#62;.*?)\] "(?P&#60;method&#62;.*?) (?P&#60;uri&#62;.*?) HTTP/1.\d" (?P&#60;status&#62;\d+) (?P&#60;length&#62;.*?) "(?P&#60;referere&#62;.*?)" "(?P&#60;agent&#62;.*?)"'
fmt_name = re.findall('\?P&#60;(.*?)&#62;', fmt_str)
fmt_re   = re.compile(fmt_str)
定义了一个正则用于提取每行日志的内容。fmt_name就是提取尖括号中间的变量名。
2. 定义MongoDB相关变量，包括需要存到collection名称。Connection采取的是默认Host和端口。
conn     = Connection()
apache   = conn.apache
logs     = apache.logs
3. 保存日志行
def make_line(line):
    m = fmt_re.search(line)
    if m:
 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>为何选择Stackless？</strong> <a href="http://www.stackless.com" target="_blank">http://www.stackless.com</a></p>
<p>Stackless可以简单的认为是Python一个增强版，最吸引眼球的非“微线程”莫属。微线程是轻量级的线程，与线程相比切换消耗的资源更小，线程内共享数据更加便捷。相比多线程代码更加简洁和可读。此项目是由EVE Online推出，在并发和性能上确实很强劲。安装和Python一样，可以考虑替换原系统Python。:)</p>
<p><strong>为何选择MongoDB？</strong> <a href="http://www.mongodb.org" target="_blank">http://www.mongodb.org</a></p>
<p>可以在官网看到很多流行的应用采用MongoDB，比如sourceforge，github等。相比RDBMS有啥优势？首先在速度和性能上优势最为明显，不仅可以当作类似KeyValue数据库来使，还包含了一些数据库查询（Distinct、Group、随机、索引等特性）。再有一点特性就是：简单。不论是应用还是文档，还是第三方API，几乎略过一下就可以使用。不过有点遗憾的就是，存储的数据文件很大，超过正常数据的2-4倍之间。本文测试的Apache日志大小是2G，生产的数据文件有6G。寒&#8230;希望在新版里能有所缩身，当然这个也是明显的以空间换速度的后果。</p>
<p>本文除去上面提及到的两个软件，还需要安装pymongo模块。<a href="http://api.mongodb.org/python/" target="_blank">http://api.mongodb.org/python/</a></p>
<p>模块安装方式有源码编译和easy_install，这里就不再累赘。</p>
<p>1. 从Apache日志中分析出需要保存的资料，比如IP，时间，GET/POST，返回状态码等。</p>
<pre>fmt_str  = '(?P&lt;ip&gt;[.\d]+) - - \[(?P&lt;time&gt;.*?)\] "(?P&lt;method&gt;.*?) (?P&lt;uri&gt;.*?) HTTP/1.\d" (?P&lt;status&gt;\d+) (?P&lt;length&gt;.*?) "(?P&lt;referere&gt;.*?)" "(?P&lt;agent&gt;.*?)"'
fmt_name = re.findall('\?P&lt;(.*?)&gt;', fmt_str)
fmt_re   = re.compile(fmt_str)</pre>
<p>定义了一个正则用于提取每行日志的内容。fmt_name就是提取尖括号中间的变量名。</p>
<p>2. 定义MongoDB相关变量，包括需要存到collection名称。Connection采取的是默认Host和端口。</p>
<pre>conn     = Connection()
apache   = conn.apache
logs     = apache.logs</pre>
<p>3. 保存日志行</p>
<pre>def make_line(line):
    m = fmt_re.search(line)
    if m:
        logs.insert(dict(zip(fmt_name, m.groups())))</pre>
<p>4. 读取Apache日志文件</p>
<pre>def make_log(log_path):
    with open(log_path) as fp:
        for line in fp:
            make_line(line.strip())</pre>
<p>5. 运行把。</p>
<pre>if __name__ == '__main__':
    make_log('d:/apachelog.txt')</pre>
<p>脚本大致情况如此，这里没有放上stackless部分代码，可以参考下面代码：</p>
<pre>import stackless
def print_x(x):
    print x
stackless.tasklet(print_x)('one')
stackless.tasklet(print_x)('two')
stackless.run()</pre>
<p>tasklet操作只是把类似操作放入队列中，run才是真正的运行。这里主要用于替换原有多线程threading并行分析多个日志的行为。</p>
<p><strong>补充：</strong></p>
<p>Apache日志大小是2G，671万行左右。生成的数据库有6G。</p>
<p>硬件：Intel(R) Core(TM)2 Duo CPU E7500 @ 2.93GHz 台式机</p>
<p>系统：RHEL 5.2 文件系统ext3</p>
<p>其他：Stackless 2.6.4 MongoDB 1.2</p>
<p>在保存300万左右时候，一切正常。不管是CPU还是内存，以及插入速度都很不错，大概有8-9000条/秒。和以前笔记本上测试结果基本一致。再往以后，内存消耗有点飙升，插入速度也降低。500万左右记录时候CPU达到40%，内存消耗2.1G。在生成第二个2G数据文件时候似乎速度和效率又提升上去了。最终保存的结果不是太满意。</p>
<p>后加用笔记本重新测试了一下1000万数据，速度比上面的671万明显提升很多。初步怀疑有两个地方可能会影响性能和速度：</p>
<p>1. 文件系统的差异。笔记本是Ubuntu 9.10，ext4系统。搜了下ext3和ext4在大文件读写上会有所差距。</p>
<p>2. 正则匹配上。单行操作都是匹配提取。大文件上应该还有优化的空间。</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2010. |
<a href="http://chenxiaoyu.org/blog/archives/213">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/213#comments">6 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/213&title=Python(Stackless) + MongoDB Apache 日志(2G)分析">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/mongodb" rel="tag">MongoDB</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/python" rel="tag">Python</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/213/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>C Apache Module 开发入门</title>
		<link>http://chenxiaoyu.org/blog/archives/140</link>
		<comments>http://chenxiaoyu.org/blog/archives/140#comments</comments>
		<pubDate>Wed, 16 Dec 2009 01:52:27 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=140</guid>
		<description><![CDATA[前言：
扩展Apache模块开发网上大部分教程都是围绕Perl语言，老外的《Writing Apache Modules with Perl and C》可以算是经典之作了，可惜一直都是针对老版本开发，而且主力语言是Perl，C语言部分只是略有介绍。不过相比较而言用Perl来扩展模块功能确实比 C语言来的快速以及便捷多了，也简单容易。我自己也在工作里应用了一部分，主要是在防盗链上面写了两个简单都模块，可以参考我写的另外两篇文章：apache+mod_perl防盗链以及apache+mod_perl实现url rewrite。说了那么多题外话，回到正题，这里只是用C语言实现一个简单的hello模块，模块功能是查询MySQL自带mysql数据库里都user表。
系统环境：
ArchLinux Apache2.2 MySQL 5.0
具体开发步骤：
1. 利用Apache自带都apxs建立hello模块：
[root#localhost] apxs -g -n hello
这样就会在当前目录下新建一个hello模块的文件目录，可以看到里面有：Makefile mod_hello.c modules.mk这样的文件，具体apxs路径查询下本机apache/bin目录。
2. 预览下mod_hello.c，可以看到里面apxs自动帮你生成一堆代码了，我们需要的只是修改里面的代码部分，先简单都介绍下里面的函数说明。
include 部分就是引入了一些必要都头文件
hello_handler 这个就是hello模块都主体部分，所有的显示、处理请求什么的都在这里。
hello_register_hooks hello_module 这俩个是需要导出的函数所必须的，先可以不管他们，按照生成的不动即可。
3. 修改hello_handler函数，里面可以看到request_rec *r，r有很多函数和变量，具体要参见文档了。里面的ap_rputs是输出，可以简单的理解为把字符串输出到r。
static int hello_handler(request_rec *r)
{
if (strcmp(r-&#62;handler, "hello")) { // 判断apache配置文件里handler是否等于hello，不是就跳过
          return DECLINED;
     }
     r-&#62;content_type [...]]]></description>
			<content:encoded><![CDATA[<p><strong>前言：</strong></p>
<p>扩展Apache模块开发网上大部分教程都是围绕Perl语言，老外的《Writing Apache Modules with Perl and C》可以算是经典之作了，可惜一直都是针对老版本开发，而且主力语言是Perl，C语言部分只是略有介绍。不过相比较而言用Perl来扩展模块功能确实比 C语言来的快速以及便捷多了，也简单容易。我自己也在工作里应用了一部分，主要是在防盗链上面写了两个简单都模块，可以参考我写的另外两篇文章：<a href="http://chenxiaoyu.org/blog/archives/120" target="_blank">apache+mod_perl防盗链</a>以及<a href="http://chenxiaoyu.org/blog/archives/123" target="_blank">apache+mod_perl实现url rewrite</a>。说了那么多题外话，回到正题，这里只是用C语言实现一个简单的hello模块，模块功能是查询MySQL自带mysql数据库里都user表。</p>
<p><strong>系统环境：</strong></p>
<p>ArchLinux Apache2.2 MySQL 5.0</p>
<p><strong>具体开发步骤：</strong></p>
<p><strong>1. </strong>利用Apache自带都apxs建立hello模块：</p>
<pre>[root#localhost] apxs -g -n hello</pre>
<p>这样就会在当前目录下新建一个hello模块的文件目录，可以看到里面有：Makefile mod_hello.c modules.mk这样的文件，具体apxs路径查询下本机apache/bin目录。</p>
<p><strong>2.</strong> 预览下mod_hello.c，可以看到里面apxs自动帮你生成一堆代码了，我们需要的只是修改里面的代码部分，先简单都介绍下里面的函数说明。</p>
<p>include 部分就是引入了一些必要都头文件<br />
hello_handler 这个就是hello模块都主体部分，所有的显示、处理请求什么的都在这里。<br />
hello_register_hooks hello_module 这俩个是需要导出的函数所必须的，先可以不管他们，按照生成的不动即可。</p>
<p><strong>3. </strong>修改hello_handler函数，里面可以看到request_rec *r，r有很多函数和变量，具体要参见文档了。里面的ap_rputs是输出，可以简单的理解为把字符串输出到r。</p>
<pre>static int hello_handler(request_rec *r)
{
if (strcmp(r-&gt;handler, "hello")) { // 判断apache配置文件里handler是否等于hello，不是就跳过
          return DECLINED;
     }
     r-&gt;content_type = "text/html"; // 设置content-type
     if (!r-&gt;header_only)
          ap_rputs("The sample page from mod_hello.c\n", r); // 输出一段文字
     return OK;// 返回 200 OK状态
}</pre>
<p>增加#include &#8220;mysq.h&#8221;，查询需要用到这个头文件。<br />
具体代码参见本文结尾部分。</p>
<p><strong>4. </strong>编译模块</p>
<pre>[root#localhost] apxs -c -a -i -I/usr/include/mysql/ -lmysqlclient mod_hello.c</pre>
<p>可以看到一堆编译指令，加上-I和-l是编译mysql必须的，编译完会自动在httpd.conf加上 LoadModule hello_module modules/mod_hello.so</p>
<p><strong>5.</strong> 修改httpd.conf<br />
&lt;Location /hello&gt;<br />
SetHandler hello<br />
&lt;/Location<br />
<strong>6. </strong>重启apache，访问http://localhost/hello，看是否成功。</p>
<p>=====================</p>
<p>完整代码：</p>
<pre>#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
/* 头文件，本文用到了ap_rprintf函数 */
#include "apr.h"
#include "apr_lib.h"
#include "apr_strings.h"
#include "apr_want.h"
#include "mysql.h"

/* 定义mysql数据变量 */
const char *host = "localhost";
const char *user = "root";
const char *pass = "smallfish";
const char *db    = "mysql";

/* The sample content handler */
static int hello_handler(request_rec *r)
{
    if (strcmp(r-&gt;handler, "hello")) {
        return DECLINED;
    }
    r-&gt;content_type = "text/html";
    /* 定义mysql变量 */
    MYSQL mysql;
    MYSQL_RES *rs;
    MYSQL_ROW row;
    mysql_init(&amp;mysql); /* 初始化 */
    if (!mysql_real_connect(&amp;mysql, host, user, pass, db, 0, NULL, 0)) {/* 连接数据库 */
        ap_rprintf(r, "&lt;li&gt;Error:%d %s&lt;/li&gt;\n", mysql_errno(&amp;mysql), mysql_error(&amp;mysql));
        return OK;
    }
    char *sql = "select host,user from user order by rand()";
    if (mysql_query(&amp;mysql, sql)!=0) { /* 查询 */
        ap_rprintf(r, "&lt;li&gt;Error : %d %s&lt;/li&gt;\n", mysql_errno(&amp;mysql), mysql_error(&amp;mysql));
        return OK;
    }
    rs = mysql_store_result(&amp;mysql); /* 获取查询结果 */
    while ((row = mysql_fetch_row(rs))) { /* 获取每一行记录 */
        ap_rprintf(r, "&lt;li&gt;%s - %s&lt;/li&gt;\n", row[0], row[1]);
    }
    mysql_free_result(rs); /* 释放结果集 */
    mysql_close(&amp;mysql); /* 关闭连接 */
    return OK;
}

static void hello_register_hooks(apr_pool_t *p)
{
    ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA hello_module = {
    STANDARD20_MODULE_STUFF,
    NULL,                            /* create per-dir              config structures */
    NULL,                            /* merge  per-dir              config structures */
    NULL,                            /* create per-server config structures */
    NULL,                            /* merge  per-server config structures */
    NULL,                            /* table of config file commands                 */
    hello_register_hooks  /* register hooks                                */
};</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/140">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/140#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/140&title=C Apache Module 开发入门">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/140/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>修改 ModPython 下 PYTHON_EGG_CACHE 报错</title>
		<link>http://chenxiaoyu.org/blog/archives/137</link>
		<comments>http://chenxiaoyu.org/blog/archives/137#comments</comments>
		<pubDate>Wed, 16 Dec 2009 01:43:01 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=137</guid>
		<description><![CDATA[环境：Linux Apache Python(mod_python)
换了一台新机器，没有配置Mod_Python了，在一些应用里import MySQLdb出现了下面错误：
ExtractionError: Can't extract file(s) to egg cache
The following error occurred while trying to extract file(s) to the Python egg
cache:
  [Errno 13] Permission denied: '/root/.python-eggs'
The Python egg cache directory is currently set to:
  /root/.python-eggs
Perhaps your account does not have write access to this directory?  You can
change the cache directory by [...]]]></description>
			<content:encoded><![CDATA[<p>环境：Linux Apache Python(mod_python)</p>
<p>换了一台新机器，没有配置Mod_Python了，在一些应用里<strong>import MySQLdb</strong>出现了下面错误：</p>
<pre>ExtractionError: Can't extract file(s) to egg cache
The following error occurred while trying to extract file(s) to the Python egg
cache:
  [Errno 13] Permission denied: '/root/.python-eggs'
The Python egg cache directory is currently set to:
  /root/.python-eggs
Perhaps your account does not have write access to this directory?  You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.</pre>
<p>解决办法有两种：</p>
<p>1.设置PYTHON_EGG_CACHE环境变量</p>
<pre>$ SetEnv PYTHON_EGG_CACHE /tmp/aaa/</pre>
<p>目录权限注意要是apache用户，或者简单点就777</p>
<p>2.把egg格式转成目录</p>
<pre>$ cd /python-path/site-packages/
$ mv MySQL_python-1.2.3c1-py2.5-linux-x86_64.egg foo.zip
$ mkdir MySQL_python-1.2.3c1-py2.5-linux-x86_64.egg
$ cd MySQL_python-1.2.3c1-py2.5-linux-x86_64.egg
$ unzip ../foo.zip
$ rm ../foo.zip</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/137">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/137#comments">One comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/137&title=修改 ModPython 下 PYTHON_EGG_CACHE 报错">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/python" rel="tag">Python</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/137/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apache 虚拟主机配置笔记</title>
		<link>http://chenxiaoyu.org/blog/archives/126</link>
		<comments>http://chenxiaoyu.org/blog/archives/126#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:36:44 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=126</guid>
		<description><![CDATA[环境：Linux Apache2.2 （路径 /usr/local/apache）
步骤：
1. 修改 conf/httpd.conf，找到如下位置，去除 # 注释符

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

2.修改 conf/extra/httpd-vhosts.conf

&#60;VirtualHost *:80&#62;
    ServerAdmin webmaster@aa.com
    DocumentRoot "/usr/aa"
    ServerName ww.aa.com
    ServerAlias ww.aa.com
    ErrorLog "logs/ww.aa.com-error_log"
    CustomLog "logs/ww.aa.com-access_log" common
&#60;/VirtualHost&#62;

注意CustomLog这行，默认给的配置是：&#8221;logs/dummy-host.example.com-access_log common&#8221;
这个其实是错误的，Apache启动时候会报错，common这个应该放在双引号外面：

Syntax error on line 32 of /usr/local/apache/conf/extra/httpd-vhosts.conf:
CustomLog takes two or three [...]]]></description>
			<content:encoded><![CDATA[<p>环境：Linux Apache2.2 （路径 /usr/local/apache）</p>
<p>步骤：</p>
<p>1. 修改 conf/httpd.conf，找到如下位置，去除 # 注释符</p>
<pre>
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
</pre>
<p>2.修改 conf/extra/httpd-vhosts.conf</p>
<pre>
&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@aa.com
    DocumentRoot "/usr/aa"
    ServerName ww.aa.com
    ServerAlias ww.aa.com
    ErrorLog "logs/ww.aa.com-error_log"
    CustomLog "logs/ww.aa.com-access_log" common
&lt;/VirtualHost&gt;
</pre>
<p>注意CustomLog这行，默认给的配置是：&#8221;logs/dummy-host.example.com-access_log common&#8221;</p>
<p>这个其实是错误的，Apache启动时候会报错，common这个应该放在双引号外面：</p>
<pre>
Syntax error on line 32 of /usr/local/apache/conf/extra/httpd-vhosts.conf:
CustomLog takes two or three arguments, a file name, a custom log format string or format name, and an optional "env=" clause (see docs)
</pre>
<p>另外还有个问题，在Apache+Tomcat时候出现的，在配置好mod_jk之后，通过默认80端口访问jsp总会提示403禁止访问，纳闷了！后来 才发现是Directory配置问题，因为每个VirtualHost配置的目录不是默认的DocumentRoot目录，在Apache2以后对于权限 和安全有了更高的要求，所以必须手动配置下每个Directory属性。</p>
<pre>
&lt;Directory "/usr/aa"&gt;
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
&lt;/Directory&gt;
</pre>
<p>OK，到这里虚拟主机部分已经配置完成！</p>
<p>补充一点，加上日志按天保存，避免一个巨大无比的文件！</p>
<pre>
CustomLog "|/usr/local/apache/bin/rotatelogs /usr/local/apache/logs/ww.aa.com-access-%y%m%d.log 86400 480 " combined
</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/126">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/126#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/126&title=Apache 虚拟主机配置笔记">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/126/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Mod_Perl实现 URL Rewrite</title>
		<link>http://chenxiaoyu.org/blog/archives/123</link>
		<comments>http://chenxiaoyu.org/blog/archives/123#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:33:07 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=123</guid>
		<description><![CDATA[相信apache的mod_rewrite模块都很熟悉了，今天这儿换个思路，利用mod_perl来实现下，发现竟然是如此的简单！
首先得保证apache已经安装了mod_perl模块，具体安装配置可以看上一篇文章哦。
修改下http.conf配置，添加一下内容：

PerlTransHandler MyTrans # MyTrans 这个是自己添加的处理模块名

具体MyTrans.pm脚本如下：

package MyTrans;

use strict;
use Apache2::Const qw(DECLINED);

sub handler {
    my $r = shift;
    my $uri = $r-&#62;uri;
    my ($id) = ($url =~ m&#124;^/news/(.*)\.html&#124;);
    $r-&#62;uri("/news.php");
    $r-&#62;args("id=$id");
    return Apache2::Const::DECLINED;
}
1;

实现就是：/news/12345.html  =&#62; /news.php?id=12345

© smallfish for smallfish logs, 2009. &#124;
Permalink [...]]]></description>
			<content:encoded><![CDATA[<p>相信apache的mod_rewrite模块都很熟悉了，今天这儿换个思路，利用mod_perl来实现下，发现竟然是如此的简单！</p>
<p>首先得保证apache已经安装了mod_perl模块，具体安装配置可以看上一篇文章哦。</p>
<p>修改下http.conf配置，添加一下内容：</p>
<pre>
PerlTransHandler MyTrans # MyTrans 这个是自己添加的处理模块名
</pre>
<p>具体MyTrans.pm脚本如下：</p>
<pre>
package MyTrans;

use strict;
use Apache2::Const qw(DECLINED);

sub handler {
    my $r = shift;
    my $uri = $r-&gt;uri;
    my ($id) = ($url =~ m|^/news/(.*)\.html|);
    $r-&gt;uri("/news.php");
    $r-&gt;args("id=$id");
    return Apache2::Const::DECLINED;
}
1;
</pre>
<p>实现就是：/news/12345.html  =&gt; /news.php?id=12345</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/123">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/123#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/123&title=Apache Mod_Perl实现 URL Rewrite">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/123/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache Mod_Perl 防盗链</title>
		<link>http://chenxiaoyu.org/blog/archives/120</link>
		<comments>http://chenxiaoyu.org/blog/archives/120#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:31:15 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=120</guid>
		<description><![CDATA[大体思路是这样的，比如有 一个地址：http://www.aa.com/down/1.mp3，不幸搜索引擎或者迅雷扒到了，就无偿为他们奉献流量了。 但是假如在http://www.aa.com/down/1.mp3?key=123，key参数每天变化或者几分钟变化一次，在apache服务端校 验下这个参数，不正确则显示拒绝访问或者找不到的话，那样防盗链的效果就算达到了把。
modperl强大到可以任意应用apache内部API，官方地址是：http://perl.apache.org 。根据apache版本选择相应的modperl版本，现在大部分都apache2了，就选择modperl2把。具体安装配置可以看官方文档。
先建立/home/httpd/modperl/startup.pl(目录请自行修改)，内容如下：
use strict;

use lib qw(/home/httpd/modperl); # 把这个路径加入到perl lib路径

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Request ();

1;
部分本机httpd.conf配置：

LoadModule perl_module                modules/mod_perl.so
LoadModule apreq_module             modules/mod_apreq2.so
PerlPostConfigRequire /home/httpd/modperl/startup.pl
&#60;Location /down &#62;
    SetHandler modperl # 设置该目录交给modper处理
    PerlAccessHandler Down # Down是模块名称
    [...]]]></description>
			<content:encoded><![CDATA[<p>大体思路是这样的，比如有 一个地址：http://www.aa.com/down/1.mp3，不幸搜索引擎或者迅雷扒到了，就无偿为他们奉献流量了。 但是假如在http://www.aa.com/down/1.mp3?key=123，key参数每天变化或者几分钟变化一次，在apache服务端校 验下这个参数，不正确则显示拒绝访问或者找不到的话，那样防盗链的效果就算达到了把。</p>
<p>modperl强大到可以任意应用apache内部API，官方地址是：<a href="http://perl.apache.org/" target="_blank">http://perl.apache.org</a> 。根据apache版本选择相应的modperl版本，现在大部分都apache2了，就选择modperl2把。具体安装配置可以看官方文档。</p>
<p>先建立/home/httpd/modperl/startup.pl(目录请自行修改)，内容如下：</p>
<pre>use strict;

use lib qw(/home/httpd/modperl); # 把这个路径加入到perl lib路径

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Request ();

1;</pre>
<p>部分本机httpd.conf配置：</p>
<pre>
LoadModule perl_module                modules/mod_perl.so
LoadModule apreq_module             modules/mod_apreq2.so
PerlPostConfigRequire /home/httpd/modperl/startup.pl
&lt;Location /down &gt;
    SetHandler modperl # 设置该目录交给modper处理
    PerlAccessHandler Down # Down是模块名称
    PerlSetVar key 123 # 设置校验参数值
&lt;/Location&gt;
</pre>
<p>mod_apreq2.so这个模块需要安装Apache2::Request，具体安装：<a href="http://pyh7.spaces.live.com/blog/cns%2147D8D44208AC51E5%21128.entry" target="_blank">http://pyh7.spaces.live.com/blog/cns!47D8D44208AC51E5!128.entry</a></p>
<p>startup.pl文件一般modperl应用都有，加载一些常用库，可以在apache启动时预先载入，避免重复加载。</p>
<p>修改这些后可以重启下apache，看下logs/error_log里最后是否有mod_apreq和mod_perl字样，如果有就说明成功了。剩下都就是写校验的perl脚本了，/home/httpd/modperl/Down.pm，内容如下：</p>
<pre>
package Down;
use strict;
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Connection ();
use Apache2::RequestUtil ();
use Apache2::ServerUtil ();
use Apache2::Log ();
use Apache2::Const -compile =&gt; qw(OK FORBIDDEN);
use Apache2::Request ();

sub handler {
    my $r = shift;
    my $req = Apache2::Request-&gt;new($r);
    my $ip = $r-&gt;connection-&gt;remote_ip;
    my $k = $req-&gt;param('key') || ''; # 判断访问时是否带key参数
    my $key = $r-&gt;dir_config('key') || '123'; # 加载httpd.conf配置中的key值
    if ($key eq $k) { # 相等可以正常访问
        return Apache2::Const::OK;
    } else { # 否则显示拒绝访问
        my $s = Apache2::ServerUtil-&gt;server;
        $s-&gt;log_error("[$ip--------forbidden.]");
        return Apache2::Const::FORBIDDEN;
    }
}

1;
</pre>
<p>提示一下，以上两个perl脚本文件末尾记得加上1;</p>
<p>重启下apache。现在可以通过http://www.aa.com/down/1.mp3和http://www.aa.com/down /1.mp3?key=123测试下。可以看见不加参数拒绝访问了把。这里只是简单的判断，实际上可以根据日期或者IP加密生成一个字符串来判断。</p>
<p>写这个帖子完全是无意中搜索modperl应用时候发现了，具体可以参见：<br />
<a href="http://pyh7.spaces.live.com/blog/cns%2147D8D44208AC51E5%21140.entry" target="_blank">http://pyh7.spaces.live.com/blog/cns!47D8D44208AC51E5!140.entry</a></p>
<p>上面的文档已经写都很详细了，包括怎么安装modperl、Apache2::Request等模块以及配置apache的http.conf就不在累赘都重复了。</p>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/120">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/120#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/120&title=Apache Mod_Perl 防盗链">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/120/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用 Perl 快速解析 Apache Log</title>
		<link>http://chenxiaoyu.org/blog/archives/100</link>
		<comments>http://chenxiaoyu.org/blog/archives/100#comments</comments>
		<pubDate>Tue, 15 Dec 2009 01:11:24 +0000</pubDate>
		<dc:creator>smallfish</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://chenxiaoyu.org/blog/?p=100</guid>
		<description><![CDATA[功能简述
统计出日志里一个或多个页面总共访问的次数，比如aa.jsp, bb.jsp这样页面分别多少次。
实现简述
Apache单个日志文件800M。
最初程序使用Python编写，按行来统计，分别使用in(最慢)和index方法去查找，然后使用了正则匹配，程序运行时间从最初的1分50多秒优化到1分10秒左右，参考了qyb博客中提到的gc.disable()，有了一定的提升，最终还是需要1分左右。
然后随意用了Perl写了一个，用了最土鳖的&#60;LOG&#62;这样的按行分析，最后正则匹配，然后++，速度竟然在40-50秒之间，惊叹！后来经过shucho指点，在正则部分采用了预编译，效果那是相当惊人！800M文件只用了7秒左右。卧槽！
程序片段
# --------------------------------------------------------------------
use strict;
use Benchmark;

my $LOG_FILE = '/usr/local/apache/logs/access.log';
# 下面qr部分起了关键作用，预编译了表达式
my @EXT_LIST = map {qr/$_/} qw{
aaServlet
bbServlet
};

my $startime = new Benchmark;
my %result;
map {$result{$_} = 0} @EXT_LIST;
open LOG_FILE, $LOG_FILE;
while (&#60;LOG_FILE&#62;){
    foreach my $ext (@EXT_LIST){
        $result{$ext}++ if $_ =~ /$ext/;
    }
}
close LOG_FILE;

while (my ($key, $value) = each(%result)){
 [...]]]></description>
			<content:encoded><![CDATA[<p><strong>功能简述</strong></p>
<p>统计出日志里一个或多个页面总共访问的次数，比如aa.jsp, bb.jsp这样页面分别多少次。</p>
<p><strong>实现简述</strong></p>
<p>Apache单个日志文件800M。</p>
<p>最初程序使用Python编写，按行来统计，分别使用in(最慢)和index方法去查找，然后使用了正则匹配，程序运行时间从最初的1分50多秒优化到1分10秒左右，参考了<a href="http://www.dup2.org/node/1006" target="_blank">qyb</a>博客中提到的gc.disable()，有了一定的提升，最终还是需要1分左右。</p>
<p>然后随意用了Perl写了一个，用了最土鳖的&lt;LOG&gt;这样的按行分析，最后正则匹配，然后++，速度竟然在40-50秒之间，惊叹！后来经过<a href="http://shucho.org/blog/" target="_blank">shucho</a>指点，在正则部分采用了预编译，效果那是相当惊人！800M文件只用了7秒左右。卧槽！</p>
<p><strong>程序片段</strong></p>
<pre># --------------------------------------------------------------------
use strict;
use Benchmark;

my $LOG_FILE = '/usr/local/apache/logs/access.log';
# 下面qr部分起了关键作用，预编译了表达式
my @EXT_LIST = map {qr/$_/} qw{
aaServlet
bbServlet
};

my $startime = new Benchmark;
my %result;
map {$result{$_} = 0} @EXT_LIST;
open LOG_FILE, $LOG_FILE;
while (&lt;LOG_FILE&gt;){
    foreach my $ext (@EXT_LIST){
        $result{$ext}++ if $_ =~ /$ext/;
    }
}
close LOG_FILE;

while (my ($key, $value) = each(%result)){
    $key =~ s/\(\?-xism:(.*?)\)/$1/g;
    print "$key:\t$value\n";
}

printf "** %s\n\n", timestr(timediff(new Benchmark, $startime));</pre>
<hr />
<p><small>© smallfish for <a href="http://chenxiaoyu.org">smallfish logs</a>, 2009. |
<a href="http://chenxiaoyu.org/blog/archives/100">Permalink</a> |
<a href="http://chenxiaoyu.org/blog/archives/100#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://chenxiaoyu.org/blog/archives/100&title=使用 Perl 快速解析 Apache Log">del.icio.us</a>
<br/>
Post tags: <a href="http://chenxiaoyu.org/blog/archives/tag/apache" rel="tag">Apache</a>, <a href="http://chenxiaoyu.org/blog/archives/tag/perl" rel="tag">Perl</a><br/>
</small></p>
<p>
<script type="text/javascript"><!--
google_ad_client = "pub-8914011260472945";
/* 468x60, 创建于 09-11-19 */
google_ad_slot = "7198645178";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</p>
<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://chenxiaoyu.org/blog/archives/100/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
