打开google reader,好开心,发现一篇精品文章,不敢独享,放上来。毕竟,独乐乐不如众乐乐嘛。没看这篇文章之前,我一直没有想通,那些空间商是怎么让一个用户注册一下就生成一个空间,而不用重启apache的。这一直是我的心头疑问,直到看到这篇文章的黑体字,所以。。。。转摘一下,哈哈
作者:FinalBSD
日期:2008-09-11
原文地址:http://www.sanotes.net/html/y2008/181.html
需求:
一台apache上要服务很多的虚拟主机,这些虚拟主机的域名具有规律性,比如说是:xxx.example.com
实现:
使用mod_rewrite进行跳转
优点:
* 不需要为每一个虚拟主机配置一段;
* 新增了vhost不需要重启apache,只需要编辑vhosts.map即可;
缺点:
* 无法为特定的vhosts设定具体配置
配置:
- RewriteEngine On
- RewriteMap lowercase int:tolower
- RewriteMap vhost txt:/usr/local/etc/apache22/vhost.map
- RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
- RewriteCond ${vhost:%1} ^(/.*)$
- RewriteRule ^/(.*)$ %1/$1
/usr/local/etc/apache22/vhost.map的内容是:
- site1.example.com /usr/local/www/data/1
- site2.example.com /usr/local/www/data/2
- site3.example.com /usr/local/www/data/3
- site4.example.com /usr/local/www/data/4
- site5.example.com /usr/local/www/data/5
- site6.example.com /usr/local/www/data/6
原理:
1.构建2个映射表,分别是lowercase和vhost;
2.对每个URL进行RewriteCond检查,比如http://Site5.Example.com/index.html
2.1 第一条RewriteCond:
- RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
1)这里首先查询lowercase表,lowercase表属于int类型,使用apache内部函数tolower将
- key:Site5.Example.com替换为value:site5.example.com.
2)查完之后用查询到的Value进行RewriteCond判断
- input='site5.example.com' pattern='^(.+)$' => matched
2.2 第二条RewriteCond:
- RewriteCond ${vhost:%1} ^(/.*)$
1)这里首先查询vhost表,vhost表属于txt类型,key:site5.example.com对应value为/usr/local/www/data/5.
2)查完之后用查询到的value进行RewriteCond判断
- input='/usr/local/www/data/5' pattern='^(/.*)$' => matched
3.在2条RewriteCond都符合的情况下,执行RewriteRule规则:
- RewriteRule ^/(.*)$ %1/$1
将/下面的所有文件重写到%1/$1,这里的
%1:是上一个RewriteCond的value:/usr/local/www/data/5
$1:即(.*)的括号里面的内容,即请求的文件名
最终的执行为:
- rewrite '/index.html' -> '/usr/local/www/data/5/index.html'
可以看详细的日志了解整个过程。
requested uri /index.html
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (3) applying pattern '^/(.*)$' to uri '/index.html'
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (5) map lookup OK: map=lowercase key=site5.example.com -> val=site5.example.com
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (4) RewriteCond: input='site5.example.com' pattern='^(.+)$' => matched
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (6) cache lookup FAILED, forcing new map lookup
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (5) map lookup OK: map=vhost[txt] key=site5.example.com -> val=/usr/local/www/data/5
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (4) RewriteCond: input='/usr/local/www/data/5' pattern='^(/.*)$' => matched
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (2) rewrite '/index.html' -> '/usr/local/www/data/5/index.html'
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (2) local path result: /usr/local/www/data/5/index.html
- 192.168.1.2 - - [11/Sep/2008:22:09:25 +0800] [site5.example.com/sid#2840feb8][rid#28cbe050/initial] (1) go-ahead with /usr/local/www/data/5/index.html [OK]
Reference:Apache模块 mod_rewrite
更强大的方法:使用mod_vhost_alias(由Tonny推荐):
那么对http://site1.example.com/file.html
的请求将会返回文件/usr/local/www/data/site1.example.com/file.html
Reference:Apache模块 mod_vhost_alias
Appendix:比较专业的模块(i_amok推荐)
http://www.oav.net/projects/mod_vhs/