10.1期間,一位朋友問我一個(gè)apache的 Rewrite規(guī)則中一個(gè)高級(jí)語法RewriteMap的用法問題。其想要實(shí)現(xiàn)的是這個(gè)功能,有個(gè)多用戶的blog,用戶訪問的時(shí)候,是用三級(jí)域名訪問的。比如http://cfc4n1.blog.cnxct.com,http://cfc4n2.blog.cnxct.com這種三級(jí)域名。在服務(wù)器上,是對三級(jí)域名做泛解析。每個(gè)三級(jí)域名都生成了一個(gè)靜態(tài)的html主頁文件。由于用戶數(shù)量較多,linux ext硬盤格式上同一目錄文件太多,檢索文件的速度會(huì)有折扣,遂將文件打散到不同的目錄下。打散方式是以用戶名【三級(jí)域名中的cfc4n1,cfc4n2等】的MD5值的每隔兩位作為一個(gè)目錄。MD5的默認(rèn)長度是32位,每隔兩位分一次目錄的話,那就有16級(jí)目錄。每級(jí)目錄的目錄名是2個(gè)字符,每個(gè)字符的有16種可能【0-9a-f】,那么每級(jí)目錄的目錄數(shù)為256個(gè)目錄,16級(jí)的話就有4096個(gè)目錄。每個(gè)目錄存1000個(gè)文件的話,可以存放4096000個(gè)文件,這樣做,即可以把文件均勻打散到各個(gè)小目錄中,同時(shí),每個(gè)目錄下的文件數(shù)又不是很多。當(dāng)用戶訪問的時(shí)候,取目錄里的用戶名,計(jì)算MD5hash,做字符分割,重寫到對應(yīng)的目錄下的文件中,如果文件不存在,則重寫到生成這個(gè)文件的動(dòng)態(tài)頁面中。
到apache手冊里找了下RewriteMap的用法
RewriteMap MapName MapType:MapSource
遂順手在.htaccess里這么寫了
查看源代碼打印幫助1 RewriteMap cfc prg:/var/www/1.php
2 RewriteRule ^([a-f0-9-]+)\.blog\.cnxct\.com ${cfc:$1} [L,PT]
然后訪問一個(gè)三級(jí)域名試試。結(jié)果提示500 http 錯(cuò)誤。到apache日志里看到如下
/var/www/.htaccess: RewriteMap not allowed here
搜了半天,不知道是什么錯(cuò)誤,只好再次看手冊,這時(shí)候,才發(fā)現(xiàn)rewritemap的作用域卻是server config, virtual host,真汗了一下。自己沒認(rèn)真看手冊。
改到virtual host里之后,重啟apache,結(jié)果,還是http 500。再到錯(cuò)誤日志里查個(gè)究竟。里面記錄的確實(shí)(13)Permission denied: mod_rewrite: could not start RewriteMap program /var/www/1.php。呃,權(quán)限,權(quán)限。。趕緊chmod了一下。再次啟動(dòng),卻提示404。。。 /0a/c1/…./…html那種MD5字符串切割之后的文件找不到。但目錄里確實(shí)是存在的啊。又到日志里查看,原來卻是/0a/c1/…../…html\r 文件無法找到了。為什么地址后面多個(gè)\r呢?打開MapSource的腳本文件,才看到里面PHP操作流的結(jié)束字符里是“\r\n”了,去掉\r 才可以。
總結(jié)一下使用APACHE URL REwrite的RewriteMap方法要注意以下幾點(diǎn):
作用域-server config, virtual host,其他配置里無效。
自定義規(guī)則MapSource中流的結(jié)束符要跟操作系統(tǒng)符合,linux的要用“\n”,同時(shí),切記在win平臺(tái)編輯腳本傳到linux上的時(shí)候,文件換行符要用linux格式的,不然,同樣會(huì)出現(xiàn)問題。
要給apache賦予對腳本的讀權(quán)限。
apache會(huì)在啟動(dòng)的時(shí)候,將自定義規(guī)則的腳本讀取到內(nèi)存中,之后,再次修改腳本時(shí),不會(huì)立刻生效,需要重啟 apache
apache 的error.log中會(huì)記錄[warn] mod_rewrite: Running external rewrite maps without defining a RewriteLock is DANGEROUS!這樣的錯(cuò)誤日志,在apache2.conf【我的系統(tǒng)是ubuntu,其他linux在httpd.conf中】中添加RewriteLock /etc/apache2/script/cfc.lock來指定RewriteLock的文件位置。記得給apache對script目錄下有讀寫權(quán)限。
自定義腳本的代碼格式如下:
查看源代碼打印幫助1 <?php
2 while($in = trim(fgets(STDIN)))
3 fputs(STDOUT, getfile($in)."\n");
4 function($str)
5 {
6 //函數(shù)判斷文件是否存在等邏輯
7 }