<?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>后院&#124;kevin’s backyard &#187; 技术备案</title>
	<atom:link href="http://kevin.9511.net/archives/category/%e6%8a%80%e6%9c%af%e5%a4%87%e6%a1%88/feed" rel="self" type="application/rss+xml" />
	<link>http://kevin.9511.net</link>
	<description>立志做一个混事业型男人</description>
	<lastBuildDate>Fri, 30 Apr 2010 16:55:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>使用7z命令行打包Firefox扩展</title>
		<link>http://kevin.9511.net/archives/503.html</link>
		<comments>http://kevin.9511.net/archives/503.html#comments</comments>
		<pubDate>Fri, 30 Apr 2010 16:55:05 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[七零八碎]]></category>
		<category><![CDATA[技术备案]]></category>
		<category><![CDATA[firefox]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=503</guid>
		<description><![CDATA[将一下命令保存成build.bat文件：
set  x=%cd%\%1
cd %x%\chrome
7z a -tzip %1.jar * -r
cd ..
7z a -tzip %1.xpi * -ir!*.jar -x!*.zip  -x!*.xpi
del %x%\chrome\%1.jar
cd ..
执行以下命令即可：
build.bat 扩展的相对路径
关于7z命令行的说明，在这里：http://www.anywolfs.com/liuhui/article.asp?id=291
]]></description>
			<content:encoded><![CDATA[<p>将一下命令保存成build.bat文件：</p>
<blockquote><p><span style="font-family: Courier New,Courier,mono;">set  x=%cd%\%1<br />
cd %x%\chrome<br />
7z a -tzip %1.jar * -r<br />
cd ..<br />
7z a -tzip %1.xpi * -ir!*.jar -x!*.zip  -x!*.xpi<br />
del %x%\chrome\%1.jar<br />
cd ..</span></p></blockquote>
<p>执行以下命令即可：</p>
<blockquote><p>build.bat 扩展的相对路径</p></blockquote>
<p>关于7z命令行的说明，在这里：<a href="http://www.anywolfs.com/liuhui/article.asp?id=291">http://www.anywolfs.com/liuhui/article.asp?id=291</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/503.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>通过GoogleReader备份博客并恢复到Wordpress中</title>
		<link>http://kevin.9511.net/archives/454.html</link>
		<comments>http://kevin.9511.net/archives/454.html#comments</comments>
		<pubDate>Wed, 13 Jan 2010 20:24:15 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[互联网]]></category>
		<category><![CDATA[技术备案]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[atom2rss]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[reader]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=454</guid>
		<description><![CDATA[备份的方法很简单，当然就是通过feed订阅喽。下面是导出的方法。
在google reader中将要导出的博客归入一个新建的类别（label），最好为英文，并在“设置”中将此类别设为“公开”。
通过以下URL即可查看该博客的atom格式的种子（feed）输出：
http://www.google.com/reader/public/atom/user/{userid}/label/{labelname}?n=1000
其中{userid}，可以在 这个页面 的“在新窗口中预览共享条目页”连接中找到。{labelname}是刚刚那个新建的类别名称。n=1000代表一次性输出1000条。
google reader只提供了atom格式的feed输出(后来知道blogger也是如此)，但wordpress却只接受rss格式的输入。他俩不会有仇吧？
为了将atom转换成rss，于是在GAE上做了个atom2rss的工具：http://atom2rss.appspot.com。如果不知道修改hosts文件直接访问appspot的方法，访问可能需要翻墙。
简单介绍下atom2rss这个小工具吧。
1，只支持Atom1.0到RSS2.0的转换并需要提供atom1.0格式种子的URL
2，使用jython+modjy编写，运行于Google AppEngine
3，使用了 http://atom.geekhood.net/ 提供的XSLT转换模板。
4，代码在这里：http://code.google.com/p/atom2rss-jython/
]]></description>
			<content:encoded><![CDATA[<p>备份的方法很简单，当然就是通过feed订阅喽。下面是导出的方法。</p>
<p>在google reader中将要导出的博客归入一个新建的类别（label），最好为英文，并在“设置”中将此类别设为“公开”。</p>
<p>通过以下URL即可查看该博客的atom格式的种子（feed）输出：</p>
<blockquote><p>http://www.google.com/reader/public/atom/user/{userid}/label/{labelname}?n=1000</p></blockquote>
<p>其中{userid}，可以在 <a href="http://www.google.com/reader/view/user/-/state/com.google/broadcast#friends-manager-page" target="_blank">这个页面</a> 的“在新窗口中预览共享条目页”连接中找到。{labelname}是刚刚那个新建的类别名称。n=1000代表一次性输出1000条。<span id="more-454"></span></p>
<p>google reader只提供了atom格式的feed输出(后来知道blogger也是如此)，但wordpress却只接受rss格式的输入。他俩不会有仇吧？</p>
<p>为了将atom转换成rss，于是在GAE上做了个atom2rss的工具：<a href="http://atom2rss.appspot.com" target="_blank">http://atom2rss.appspot.com</a>。如果不知道修改hosts文件直接访问appspot的方法，访问可能需要翻墙。</p>
<p>简单介绍下atom2rss这个小工具吧。</p>
<p>1，只支持Atom1.0到RSS2.0的转换并需要提供atom1.0格式种子的URL</p>
<p>2，使用jython+modjy编写，运行于Google AppEngine</p>
<p>3，使用了 http://atom.geekhood.net/ 提供的XSLT转换模板。</p>
<p>4，代码在这里：<a href="http://code.google.com/p/atom2rss-jython/" target="_blank">http://code.google.com/p/atom2rss-jython/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/454.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>htpasswd命令及crypt函数</title>
		<link>http://kevin.9511.net/archives/343.html</link>
		<comments>http://kevin.9511.net/archives/343.html#comments</comments>
		<pubDate>Sat, 22 Aug 2009 19:09:32 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[crypt]]></category>
		<category><![CDATA[htpasswd]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=343</guid>
		<description><![CDATA[在apache上应用basic auth的时候，会有一步是使用apache提供的htpasswd命令来生成passwd文件。如下：
/usr/local/apache-2.2.4/bin/htpasswd -c ./passwd kevin
这样，就为用户名为“kevin”的用户在当前目录下的passwd文件中创建了一条记录，内容包含用户名及将用户输入的密码加密后字符串。如果文件已存在，则可忽略参数“-c”。
用久了，就会发现，相同的用户名和密码，每一次使用htpasswd命令之后生成的加密字符串都是不同的。那么在随后的应用中，apache又是怎么来校验“用户输入密码经加密后的结果”与“文件中已存在的加密结果”是否匹配呢？
htpasswd默认情况，是使用系统库中的crypt()函数来对密码明文进行单向加密的。在网上找到该函数的说明：
crypt()将使用Data Encryption Standard(DES)演算法将参数key所指的字符串加以编码，key字符串长度仅取前8个字符，超过此长度的字符没有意义。参数salt为两个字 符组成的字符串，由a-z,A-Z,0-9,".",和"/"所组成，用来决定使用4096种不同内建表格的哪一个。函数执行成功后会返回指向编码过的字符串指针，参数key所指的字符串不会有所更动。编码过的字符串长度为13个字符，前两个字符为参数salt代表的字符串。
默认情况下，htpasswd在对密码明文加密的时候，会随机生成一个两位的salt值。加密后的13位字符串的头两位即是这个salt的值。
在应用过程中，apache根据用户输入的用户名查找出密码文件中已存在的加密字符串，并取该字符串的头两位作为salt，以此对用户输入的密码明文进行crypt()加密，如果结果与密码文件中的加密字符串相同，则匹配上了。
综上所述，对于同一个字符串，crypt()函数的加密结果受到第二个可选参数“salt”(干扰串)影响，而加密结果中又含有这个干扰串。这就明白了虽然用htpasswd每次生成的加密结果不同(随机生成salt并包含在结果中)但apache又可以进行正确校验(salt已知)的原因了。
还有，因为htpasswd默认使用crypt()函数进行加密，所以，在这种情况下密码内容超过8位的字符没有意义。即，“12345678”与“123456789”的加密结果是一样的。
]]></description>
			<content:encoded><![CDATA[<p>在apache上应用basic auth的时候，会有一步是使用apache提供的htpasswd命令来生成passwd文件。如下：</p>
<blockquote><p>/usr/local/apache-2.2.4/bin/htpasswd -c ./passwd kevin</p></blockquote>
<p>这样，就为用户名为“kevin”的用户在当前目录下的passwd文件中创建了一条记录，内容包含用户名及将用户输入的密码加密后字符串。如果文件已存在，则可忽略参数“-c”。<span id="more-343"></span></p>
<p>用久了，就会发现，相同的用户名和密码，每一次使用htpasswd命令之后生成的加密字符串都是不同的。那么在随后的应用中，apache又是怎么来校验“用户输入密码经加密后的结果”与“文件中已存在的加密结果”是否匹配呢？</p>
<p>htpasswd默认情况，是使用系统库中的crypt()函数来对密码明文进行单向加密的。在网上找到该函数的说明：</p>
<blockquote><p><code><span style="color: #000000;">crypt()将使用Data Encryption Standard(DES)演算法将参数key所指的字符串加以编码，key字符串长度仅取前8个字符，超过此长度的字符没有意义。参数salt为两个字 符组成的字符串，由a-z,A-Z,0-9,".",和"/"所组成，用来决定使用4096种不同内建表格的哪一个。</span></code><code><span style="color: #000000;">函数执行成功后会返回指向编码过的字符串指针，参数key所指的字符串不会有所更动。编码过的字符串长度为13个字符，前两个字符为参数salt代表的字符串。</span></code></p></blockquote>
<p>默认情况下，htpasswd在对密码明文加密的时候，会随机生成一个两位的salt值。加密后的13位字符串的头两位即是这个salt的值。</p>
<p>在应用过程中，apache根据用户输入的用户名查找出密码文件中已存在的加密字符串，并取该字符串的头两位作为salt，以此对用户输入的密码明文进行crypt()加密，如果结果与密码文件中的加密字符串相同，则匹配上了。</p>
<p>综上所述，对于同一个字符串，crypt()函数的加密结果受到第二个可选参数“salt”(干扰串)影响，而加密结果中又含有这个干扰串。这就明白了虽然用htpasswd每次生成的加密结果不同(随机生成salt并包含在结果中)但apache又可以进行正确校验(salt已知)的原因了。</p>
<p>还有，因为htpasswd默认使用crypt()函数进行加密，所以，在这种情况下密码内容超过8位的字符没有意义。即，“12345678”与“123456789”的加密结果是一样的。</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/343.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>基本连接验证(Basic Access Authorization)的原理</title>
		<link>http://kevin.9511.net/archives/332.html</link>
		<comments>http://kevin.9511.net/archives/332.html#comments</comments>
		<pubDate>Sat, 22 Aug 2009 12:06:04 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[gtap]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=332</guid>
		<description><![CDATA[前段时间在搞GTAP，最近又研究ZendFramework的Auth模块，重新又对身份认证的这个小东西小小的研究了一小下。在查找资料时，同样没有在中文互联网内找到什么可用的资源。以下文字大部分翻译自wikipedia关于Basic Access Authorization的英文页面。
我们通常说的基于HTTP的基本验证(Basic Authorization)的英文全称应该是“Basic Access Authorization”，这是在RFC2617中定义的。
在一个HTTP交互的过程中，“基本连接认证”(没有找到中文翻译，姑且这么叫吧)是一个允许浏览器或其他客户端程序在发起请求时向服务器端以用户名+密码的方式提供身份证明的方法。
在传输之前，用户名和密码被一个冒号连接在一起，并以base64算法进行编码，如用户名“kevin”和密码“9511.net”先用冒号进行连接成“kevin:9511.net”，然后再对这个新字符串用base64算法编码，结果就是“a2V2aW46OTUxMS5uZXQ==”。这个经base64算法编码后的字符串被提交到服务器端，并由服务器端用base64算法进行解码，然后用一个冒号分割出用户名和密码，最后由服务器端针对用户和密码进行认证。
在具体的传输环节上，由于此认证方式是基于HTTP协议，所以请求和响应的内容都是存在于header中。For Example：
客户端请求
GET /private/index.html HTTP/1.0
Host: localhost
服务器端响应：
HTTP/1.0 401 Authorization Required   &#60;== 状态码
Server: HTTPd/1.0
Date: Sat, 27 Nov 2004 10:18:15 GMT
WWW-Authenticate: Basic realm=&#8221;Secure Area&#8221;  &#60;==必要值，realm的值可自定义
Content-Type: text/html
Content-Length: 311
此时客户端收到响应后，会出现一个对话框，由用户填写用户名和密码。并将用户填写的内容经处理发送到服务器端：
GET /private/index.html HTTP/1.0
Host: localhost
Authorization: Basic a2V2aW46OTUxMS5uZXQ==
服务端对再次收到的数据进行处理，如果认为此用户通过，则返回正常的请求结果。
基本连接认证的整个过程就是这么简单，在最流行、装机量最大的WEB服务器软件apache中内置了对基本连接认证的支持。怎么在apache内配置实用，网上到处都是复制来复制去的文章，就不多说了。
其实包括PHP在内的语言好多语言，都可以通过自定义header信息来提供独立于web server之外的基本连接认证支持。比如PHP，如果一个Request中包含“Authorization: Basic a2V2aW46OTUxMS5uZXQ==”这样的内容，PHP就会将“a2V2aW46OTUxMS5uZXQ==”进行解码然后将用户名和密码分别放入$_SERVER['PHP_AUTH_USER']和$_SERVER['PHP_AUTH_PW']两个超全局变量中，那么剩下的就跟上面说的过程都一样了。
$_SERVER['PHP_AUTH_USER']))

]]></description>
			<content:encoded><![CDATA[<p>前段时间在搞<a href="http://code.google.com/p/gtap/" target="_blank">GTAP</a>，最近又研究ZendFramework的Auth模块，重新又对身份认证的这个小东西小小的研究了一小下。在查找资料时，同样没有在中文互联网内找到什么可用的资源。以下文字大部分翻译自wikipedia<a href="http://en.wikipedia.org/wiki/Basic_access_authentication" target="_self">关于Basic Access Authorization的英文页面</a>。</p>
<p>我们通常说的基于HTTP的基本验证(Basic Authorization)的英文全称应该是“Basic Access Authorization”，这是在<a href="http://tools.ietf.org/html/rfc2617" target="_blank">RFC2617</a>中定义的。<span id="more-332"></span></p>
<blockquote><p>在一个HTTP交互的过程中，“基本连接认证”(没有找到中文翻译，姑且这么叫吧)是一个允许浏览器或其他客户端程序在发起请求时向服务器端以用户名+密码的方式提供身份证明的方法。</p>
<p>在传输之前，用户名和密码被一个冒号连接在一起，并以base64算法进行编码，如用户名“kevin”和密码“9511.net”先用冒号进行连接成“kevin:9511.net”，然后再对这个新字符串用base64算法编码，结果就是“a2V2aW46OTUxMS5uZXQ==”。这个经base64算法编码后的字符串被提交到服务器端，并由服务器端用base64算法进行解码，然后用一个冒号分割出用户名和密码，最后由服务器端针对用户和密码进行认证。</p></blockquote>
<p>在具体的传输环节上，由于此认证方式是基于HTTP协议，所以请求和响应的内容都是存在于header中。For Example：</p>
<blockquote><p>客户端请求<br />
GET /private/index.html HTTP/1.0<br />
Host: localhost</p></blockquote>
<blockquote><p>服务器端响应：<br />
HTTP/1.0 401 Authorization Required   &lt;== 状态码<br />
Server: HTTPd/1.0<br />
Date: Sat, 27 Nov 2004 10:18:15 GMT<br />
WWW-Authenticate: Basic realm=&#8221;Secure Area&#8221;  &lt;==必要值，realm的值可自定义<br />
Content-Type: text/html<br />
Content-Length: 311</p></blockquote>
<blockquote><p>此时客户端收到响应后，会出现一个对话框，由用户填写用户名和密码。并将用户填写的内容经处理发送到服务器端：<br />
GET /private/index.html HTTP/1.0<br />
Host: localhost<br />
Authorization: Basic a2V2aW46OTUxMS5uZXQ==</p></blockquote>
<p>服务端对再次收到的数据进行处理，如果认为此用户通过，则返回正常的请求结果。</p>
<p>基本连接认证的整个过程就是这么简单，在最流行、装机量最大的WEB服务器软件apache中内置了对基本连接认证的支持。怎么在apache内配置实用，网上到处都是复制来复制去的文章，就不多说了。</p>
<p>其实包括PHP在内的语言好多语言，都可以通过自定义header信息来提供独立于web server之外的基本连接认证支持。比如PHP，如果一个Request中包含“Authorization: Basic a2V2aW46OTUxMS5uZXQ==”这样的内容，PHP就会将“a2V2aW46OTUxMS5uZXQ==”进行解码然后将用户名和密码分别放入$_SERVER['PHP_AUTH_USER']和$_SERVER['PHP_AUTH_PW']两个超全局变量中，那么剩下的就跟上面说的过程都一样了。</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 354px; width: 1px; height: 1px;"><span style="color: #0000bb;">$_SERVER</span><span style="color: #007700;">[</span><span style="color: #dd0000;">'PHP_AUTH_USER'</span><span style="color: #007700;">]))<br />
</span></div>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/332.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>安装Bugzilla遇到的问题</title>
		<link>http://kevin.9511.net/archives/294.html</link>
		<comments>http://kevin.9511.net/archives/294.html#comments</comments>
		<pubDate>Tue, 28 Jul 2009 10:27:57 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[bugzilla]]></category>
		<category><![CDATA[ldconfig]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=294</guid>
		<description><![CDATA[几天前，要为公司架设Bugzilla系统，因为一个DBD::mysql的问题，花费了整整一宿的时间。该问题的解决，又是在浩瀚的英文互联网资源的帮助下得到的解决。中文资料，除了复制就是粘贴，根本没有解决问题的方法，而且按照资料根本无法安装成功，也不知道这些人是怎么弄成的。现在就做个简单的中文版的备份吧。
由于checksetup.pl脚本的存在，其实bugzilla的安装应该是非常顺利的，10多分钟，基本所有bugzilla需要的cpan扩展包都安装成功，最后出了一个数据库选择的提示。bugzilla目前可支持MySQL、PostgreSQL、Oracle三种数据库，需要要按自己的实际环境安装不同数据库的CPAN模块。所有的中文文档里，对这个步骤的形容都是跟其他模块一样，一条“/usr/bin/perl install-module.pl DBD::mysql”就可以搞定，可实际上……并非如此，起码我这么装没有成功，我个人估计，是因为他们安装Bugzilla的服务器跟mysql所运行的服务器在一台上面。我要安装Bugzilla的服务器，只编译安装了mysqlclient，并没有server存在。
在安装Bugzilla的时候，通过其提供的“install-module.pl”命令安装的CPAN模块，都是装在Bugzilla所在目录的lib目录下。而手动下载CPAN模块并安装的时候，在我的这台服务器上，默认是安装到“/usr/lib/perl5/5.8.5/”目录下的。这两个目录的结构相同。Bugzilla的checksetup.pl脚本在检测安装所需模块的时候，这连个路径都会扫描。
通过http://search.cpan.org搜索“DBD-mysql”，并下载“DBD::mysql”。解压缩后运行下面命令：
perl Makefile.PL &#8211;libs=&#8221;-L/usr/local/mysql-5.1.36/lib/mysql -lmysqlclient -L/usr/lib -lz&#8221; &#8211;cflags=-I/usr/local/mysql-5.1.36/include/mysql &#8211;mysql_config=/usr/local/mysql-5.1.36/bin/mysql_config &#8211;testhost=192.168.1.208 &#8211;testdb=test &#8211;testuser=bugs &#8211;testpassword=bugs
其中的“/usr/local/mysql-5.1.36”是安装mysqlclient的路径。在安装DBD::mysql的时候，会检测与mysql服务器的联通性，这里的testhost、testdb、testuser、testpassword就是做这个用的。用户bugs我事先在mysql服务器添加好了。
安装好“DBD::mysql”后，再次运行checksetup.pl脚本，出现了如下提示：
Reading ./localconfig&#8230;
Checking for       DBD-mysql (v2.9003) ok: found v4.005
Had to create DBD::mysql::dr::imp_data_size unexpectedly at /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm line 1213, &#60;DATA&#62; line 228.
Use of uninitialized value in subroutine entry at /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm line 1213, &#60;DATA&#62; line 228.
Had to create DBD::mysql::db::imp_data_size unexpectedly at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/DBI.pm line 1243, [...]]]></description>
			<content:encoded><![CDATA[<p>几天前，要为公司架设Bugzilla系统，因为一个DBD::mysql的问题，花费了整整一宿的时间。该问题的解决，又是在浩瀚的英文互联网资源的帮助下得到的解决。中文资料，除了复制就是粘贴，根本没有解决问题的方法，而且按照资料根本无法安装成功，也不知道这些人是怎么弄成的。现在就做个简单的中文版的备份吧。<span id="more-294"></span></p>
<p>由于checksetup.pl脚本的存在，其实bugzilla的安装应该是非常顺利的，10多分钟，基本所有bugzilla需要的cpan扩展包都安装成功，最后出了一个数据库选择的提示。bugzilla目前可支持MySQL、PostgreSQL、Oracle三种数据库，需要要按自己的实际环境安装不同数据库的CPAN模块。所有的中文文档里，对这个步骤的形容都是跟其他模块一样，一条“/usr/bin/perl install-module.pl DBD::mysql”就可以搞定，可实际上……并非如此，起码我这么装没有成功，我个人估计，是因为他们安装Bugzilla的服务器跟mysql所运行的服务器在一台上面。我要安装Bugzilla的服务器，只编译安装了mysqlclient，并没有server存在。</p>
<p>在安装Bugzilla的时候，通过其提供的“install-module.pl”命令安装的CPAN模块，都是装在Bugzilla所在目录的lib目录下。而手动下载CPAN模块并安装的时候，在我的这台服务器上，默认是安装到“/usr/lib/perl5/5.8.5/”目录下的。这两个目录的结构相同。Bugzilla的checksetup.pl脚本在检测安装所需模块的时候，这连个路径都会扫描。</p>
<p>通过http://search.cpan.org搜索“DBD-mysql”，并下载“DBD::mysql”。解压缩后运行下面命令：</p>
<blockquote><p>perl Makefile.PL &#8211;libs=&#8221;-L/usr/local/mysql-5.1.36/lib/mysql -lmysqlclient -L/usr/lib -lz&#8221; &#8211;cflags=-I/usr/local/mysql-5.1.36/include/mysql &#8211;mysql_config=/usr/local/mysql-5.1.36/bin/mysql_config &#8211;testhost=192.168.1.208 &#8211;testdb=test &#8211;testuser=bugs &#8211;testpassword=bugs</p></blockquote>
<p>其中的“/usr/local/mysql-5.1.36”是安装mysqlclient的路径。在安装DBD::mysql的时候，会检测与mysql服务器的联通性，这里的testhost、testdb、testuser、testpassword就是做这个用的。用户bugs我事先在mysql服务器添加好了。</p>
<p>安装好“DBD::mysql”后，再次运行checksetup.pl脚本，出现了如下提示：</p>
<blockquote><p>Reading ./localconfig&#8230;<br />
Checking for       DBD-mysql (v2.9003) ok: found v4.005<br />
Had to create DBD::mysql::dr::imp_data_size unexpectedly at /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm line 1213, &lt;DATA&gt; line 228.<br />
Use of uninitialized value in subroutine entry at /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/DBI.pm line 1213, &lt;DATA&gt; line 228.<br />
Had to create DBD::mysql::db::imp_data_size unexpectedly at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/DBI.pm line 1243, &lt;DATA&gt; line 228.<br />
Use of uninitialized value in subroutine entry at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/DBI.pm line 1243, &lt;DATA&gt; line 228.<br />
There was an error connecting to MySQL:</p>
<p>Undefined subroutine &amp;DBD::mysql::db::_login called at /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/DBD/mysql.pm line 142, &lt;DATA&gt; line 228.</p></blockquote>
<p>在网上查了很长时间，按照网上的描述，修改localconfig文件n次，重新安装配置DBD::mysqln次，依然未果，而且就网上的说法，造成这个错误提示的原因有很多种。正在抓耳挠腮，郁闷之极的时候，突然看到一个邮件里表里有说mysql lib的问题。马上想到自己安装mysql的时候，是rpm卸载掉系统默认的4.0后，手动编译安装的mysql5.1。赶紧运行ldconfig，靠的，还真没有mysql的lib。修改/etc/ld.so.conf文件，把mysql的lib路径加进去，运行ldconfig。然后回到bugzilla目录重新运行checksetup.pl，一切哦耶了。</p>
<p>在中文论坛里，也看到一些人说mysql本来是4.x，bugzilla运行正常，后来升级成5.x之后，就出错了。这些错误应该也是跟我的问题一样，跟mysql的版本没什么关系。</p>
<p>关于ldconfig的问题，再次提醒下自己……<a href="http://kevin.9511.net/archives/177.html" target="_blank">http://kevin.9511.net/archives/177.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/294.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>windows下查看占用某端口的是哪个进程</title>
		<link>http://kevin.9511.net/archives/248.html</link>
		<comments>http://kevin.9511.net/archives/248.html#comments</comments>
		<pubDate>Fri, 05 Jun 2009 03:18:23 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[进程]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/?p=248</guid>
		<description><![CDATA[&#62;netstat -aon&#124;findstr &#8220;8000&#8243;   得到进程号
&#62;tasklist&#124;findstr &#8220;xxxxx&#8221;           OVER

]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: medium;">&gt;netstat -aon|findstr &#8220;8000&#8243;   得到进程号</span></p>
<p><span style="font-size: medium;">&gt;tasklist|findstr &#8220;xxxxx&#8221;           OVER<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/248.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>设置PHP的默认时区</title>
		<link>http://kevin.9511.net/archives/188.html</link>
		<comments>http://kevin.9511.net/archives/188.html#comments</comments>
		<pubDate>Sun, 24 May 2009 17:44:48 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[时区]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/188.html</guid>
		<description><![CDATA[自 PHP 5.1.0 起（此版本日期时间函数被重写了），如果时区不合法则每个对日期时间函数的调用都会产生一条 E_NOTICE 级别的错误信息，如果使用系统设定或 TZ 环境变量则还会产生 E_STRICT 级别的信息。
不像Unix/Linux平台还有一个 TZ 环境变量可以用，在WIN32平台下， 不设置时区，那么时间都是按照格林威治标准时间走的。比如“北京时间上午10点”，在你的脚本里就会认为是凌晨2点(减8小时)。
PHP的默认时区，可以通过修改php.ini的 date.timezon 值来设定。
date_default_timezone_get()函数可以得到你的脚本中所有日期时间函数所使用的默认时区。如果它返回的是UTC，则说明没有被设置一个默认的时区。除了修改php.ini文件，我们还可以在脚本中用 date_default_timezone_set()函数来进行默认时区的设置。
下面这些，都是设置为北京时间(GMT+8)的
date_default_timezone_set(&#8217;Asia/Chongqing&#8217;); //重庆
date_default_timezone_set(&#8217;Asia/Chungking&#8217;); //重庆
date_default_timezone_set(&#8217;Asia/Harbin&#8217;);//哈尔滨
date_default_timezone_set(&#8217;Asia/Hong_Kong&#8217;);//香港
date_default_timezone_set(&#8217;Asia/Macau&#8217;);//澳门
date_default_timezone_set(&#8217;Asia/Macao&#8217;);//澳门
date_default_timezone_set(&#8217;Asia/Shanghai&#8217;);//上海
date_default_timezone_set(&#8217;Asia/Taipei&#8217;);//台北
date_default_timezone_set(&#8217;Asia/Urumqi&#8217;);//乌鲁木齐
参见：date_default_timezone_get() date_default_timezone_set PHP所支持时区列表
]]></description>
			<content:encoded><![CDATA[<p>自 PHP 5.1.0 起（此版本日期时间函数被重写了），如果时区不合法则每个对日期时间函数的调用都会产生一条 <tt class="constant"><strong>E_NOTICE</strong></tt> 级别的错误信息，如果使用系统设定或 TZ 环境变量则还会产生 <tt class="constant"><strong>E_STRICT</strong></tt> 级别的信息。</p>
<p>不像Unix/Linux平台还有一个 TZ 环境变量可以用，在WIN32平台下， 不设置时区，那么时间都是按照格林威治标准时间走的。比如“北京时间上午10点”，在你的脚本里就会认为是凌晨2点(减8小时)。</p>
<p>PHP的默认时区，可以通过修改php.ini的 date.timezon 值来设定。</p>
<p><strong class="function">date_default_timezone_get()</strong>函数可以得到你的脚本中所有日期时间函数所使用的默认时区。如果它返回的是UTC，则说明没有被设置一个默认的时区。除了修改php.ini文件，我们还可以在脚本中用 <strong class="function">date_default_timezone_set()</strong>函数来进行默认时区的设置。</p>
<p>下面这些，都是设置为北京时间(GMT+8)的</p>
<blockquote><p>date_default_timezone_set(&#8217;Asia/Chongqing&#8217;); //重庆<br />
date_default_timezone_set(&#8217;Asia/Chungking&#8217;); //重庆<br />
date_default_timezone_set(&#8217;Asia/Harbin&#8217;);//哈尔滨<br />
date_default_timezone_set(&#8217;Asia/Hong_Kong&#8217;);//香港<br />
date_default_timezone_set(&#8217;Asia/Macau&#8217;);//澳门<br />
date_default_timezone_set(&#8217;Asia/Macao&#8217;);//澳门<br />
date_default_timezone_set(&#8217;Asia/Shanghai&#8217;);//上海<br />
date_default_timezone_set(&#8217;Asia/Taipei&#8217;);//台北<br />
date_default_timezone_set(&#8217;Asia/Urumqi&#8217;);//乌鲁木齐</p></blockquote>
<p>参见：<a href="http://cn.php.net/manual/en/function.date-default-timezone-get.php"><span class="function">date_default_timezone_get()</span></a> <a href="http://cn.php.net/manual/en/function.date-default-timezone-set.php">date_default_timezone_set</a> <a title="所支持时区列表" href="http://cn.php.net/manual/en/timezones.php" target="_blank">PHP所支持时区列表</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/188.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php+nginx实现的文件下载</title>
		<link>http://kevin.9511.net/archives/187.html</link>
		<comments>http://kevin.9511.net/archives/187.html#comments</comments>
		<pubDate>Fri, 22 May 2009 18:43:13 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/187.html</guid>
		<description><![CDATA[发送X-Accel-Redirect头实现直接定位成静态下载
$root_path = &#8216;/web/www&#8217;; //网站根目录
$file_path = &#8216;/data/t.txt&#8217;;  //文件路径
//发送下载的头信息
header(&#8221;Content-type: application/x-octet-stream&#8221;);
header(&#8221;Accept-Ranges: bytes&#8221;);
header(&#8221;Content-Disposition: attachment; filename=&#8221;.basename($file_path));
header(&#8221;Content-Length: &#8220;.filesize($root_path.$file_path));
//发送文件定位，是相对网站目录的路径
header(&#8221;X-Accel-Redirect: &#8220;.$file_path);
]]></description>
			<content:encoded><![CDATA[<p>发送X-Accel-Redirect头实现直接定位成静态下载</p>
<blockquote><p><span><span class="vars">$root_path = &#8216;/web/www&#8217;; //网站根目录<br />
$file_path = &#8216;/data/t.txt&#8217;;  //文件路径</span></span></p>
<p>//发送下载的头信息<br />
header(&#8221;Content-type: application/x-octet-stream&#8221;);<br />
header(&#8221;Accept-Ranges: bytes&#8221;);<br />
header(&#8221;Content-Disposition: attachment; filename=&#8221;.basename($file_path));<br />
header(&#8221;Content-Length: &#8220;.filesize($root_path.$file_path));</p>
<p>//发送文件定位，是相对网站目录的路径<br />
header(&#8221;X-Accel-Redirect: &#8220;.$file_path);</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/187.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql中text字段类型的长度限制</title>
		<link>http://kevin.9511.net/archives/186.html</link>
		<comments>http://kevin.9511.net/archives/186.html#comments</comments>
		<pubDate>Thu, 07 May 2009 18:54:06 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/186.html</guid>
		<description><![CDATA[TEXT 是  64k
MEDIUMTEXT 是 2G
LONGTEXT 是 4G .
]]></description>
			<content:encoded><![CDATA[<p>TEXT 是  64k</p>
<p>MEDIUMTEXT 是 2G</p>
<p>LONGTEXT 是 4G .</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/186.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>windows下导入postgresql的数据库备份文件</title>
		<link>http://kevin.9511.net/archives/184.html</link>
		<comments>http://kevin.9511.net/archives/184.html#comments</comments>
		<pubDate>Mon, 27 Apr 2009 05:48:13 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[pgsql]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/184.html</guid>
		<description><![CDATA[在linux下面用pg_dump导出一个数据库到文本文件，在windows下面如果用这个命令导入的话，会因为字符集的问题在某些地方失败：
psql my_db &#60; backup.sql
但是，如果通过这个命令导入，就会成功，并且数据是完全正确的：
psql -d my_db -f backup.sql
上面的两种导入方式，在linux下面都是没有问题的。至于为什么windows下出问题，完全不知道&#8230;&#8230;
]]></description>
			<content:encoded><![CDATA[<p>在linux下面用pg_dump导出一个数据库到文本文件，<span id="note_temp" class="noted"></span>在windows下面如果用这个命令导入的话，会因为字符集的问题在某些地方失败：</p>
<p>psql my_db &lt; backup.sql</p>
<p>但是，<span id="note_temp" class="noted">如果通过这个命令导入</span>，就会成功，并且数据是完全正确的：</p>
<p>psql -d my_db -f backup.sql</p>
<p><span id="note_temp" class="noted">上面的两种导入方式</span>，在linux下面都是没有问题的。至于为什么windows下出问题，完全不知道&#8230;&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/184.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ProFTPD搭载sqlite3，简单配置轻量级FTP服务器</title>
		<link>http://kevin.9511.net/archives/182.html</link>
		<comments>http://kevin.9511.net/archives/182.html#comments</comments>
		<pubDate>Mon, 20 Apr 2009 16:15:10 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[proftpd]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/182.html</guid>
		<description><![CDATA[所谓简单，是因为ProFTPD的一些复杂功能都没有写进来，比如用户磁盘空间配额、上传下载速率限制等。
所谓轻量级，是因为配这个平台，是为了公司内部使用，用户有限。更复杂的配置，日后再说吧:)
网上的很多关于ProFTPD搭载数据库进行管理的文章，大多用的都是MySQL(搜baidu的结果)和PostgreSQL(搜google的结果)，可是单单为了一个公司内部使用的这么一个小平台，使用这么两个重量级的数据库，是在有点杀鸡用牛刀的感觉。对于我的需求，Sqlite这个轻量级的嵌入式数据库，显然是最最合适的选择。在网上跑来跑去找了1个多小时，也没有一篇像样的配置文档，甚至连ProFTPD的官方doc里，提起sqlite也是只言片语。没办法，只有自己对着英文的Howto，自己摸索了。
1，Install Sqlite3 and ProFTPD
下载安装Sqlite3最新版：http://www.sqlite.org/
#tar -zxf sqlite-amalgamation-3.6.13.tar.gz
#cd sqlite-3.6.13/
#./configure
#make
#make install
下载安装ProFTPD最新版：http://www.proftpd.org/
ProFTPD对于数据库的支持，并不是通过linux的PAM方式来实现的
而是内置了模块，这点曾经让我走了很多弯路，TMD居然没有文章提及这点。使用sqlite模块:
#tar -zxf proftpd-1.3.2.tar.gz
#cd proftpd-1.3.2
#./configure &#8211;prefix=/usr/local/proftpd &#8211;with-modules=mod_sql:mod_sql_sqlite
#make
#make install
2，配置ProFTPD
编辑/usr/local/proftpd/etc/proftpd.conf文件，加入下面列出来的这一大坨参数。
这里只说说跟Sqlite3有关的参数，其他比较有用的参数配置说明，满世界都是。完整配置文件放在最后。
其实除了SQLBackend和SQLConnectInfo两个参数之外，剩下的一些参数在配置其他数据库时也会用到
我在配置这些数据库相关参数的时候，走了很多弯路，查了很多文档，记下来也给自己脑子备个份。
#首先来说这俩，定义proftpd以什么身份来运行，跟apache里的是一个意思
#我是习惯了apache定义为www用户和www组，配置proftpd也就这样了
#以什么身份运行，我个人感觉没啥特别意义，关键是虚拟用户对实体用户的映射！
User                    www
Group                   www
#sqlite2跟3差别较大，各软件平台对其支持也是分开来的，比如PHP
#这里就是指明，使用sqlite3
SQLBackend sqlite3
#数据库文件的绝对路径，一定要绝对
SQLConnectInfo /home/www/ftpd.db
#数据库内虚拟用户的密码认证方式
#我认为Backend的意思就是数据库自己的认证方式，比如mysql的password方案
#该方案可以指定多种，使用空格隔开，按照先后，依次try
#下面这句的意思就是“先用sqlite自己的认证方式(我用的明文，其他解决方案没研究)
#如果不行，再使用crypt(3)的方案”，实际配置文件里我只要了一个Backend
SQLAuthTypes [...]]]></description>
			<content:encoded><![CDATA[<p>所谓简单，是因为<a title="Highly configurable GPL-licensed FTP server software " href="http://www.proftpd.org/" target="_blank">ProFTPD</a>的一些复杂功能都没有写进来，比如用户磁盘空间配额、上传下载速率限制等。<br />
所谓轻量级，是因为配这个平台，是为了公司内部使用，用户有限。更复杂的配置，日后再说吧:)</p>
<p>网上的很多关于ProFTPD搭载数据库进行管理的文章，大多用的都是MySQL(搜baidu的结果)和PostgreSQL(搜google的结果)，可是单单为了一个公司内部使用的这么一个小平台，使用这么两个重量级的数据库，是在有点杀鸡用牛刀的感觉。对于我的需求，<a title="a lightweight embeddable database system" href="http://www.sqlite.org" target="_blank">Sqlite</a>这个轻量级的嵌入式数据库，显然是最最合适的选择。在网上跑来跑去找了1个多小时，也没有一篇像样的配置文档，甚至连ProFTPD的官方doc里，提起sqlite也是只言片语。没办法，只有自己对着英文的Howto，自己摸索了。</p>
<p><strong>1，Install Sqlite3 and ProFTPD</strong><br />
下载安装Sqlite3最新版：http://www.sqlite.org/</p>
<blockquote><p>#tar -zxf sqlite-amalgamation-3.6.13.tar.gz<br />
#cd sqlite-3.6.13/<br />
#./configure<br />
#make<br />
#make install</p></blockquote>
<p>下载安装ProFTPD最新版：http://www.proftpd.org/<br />
<span style="color: #ff6600;">ProFTPD对于数据库的支持，并不是通过linux的PAM方式来实现的<br />
而是内置了模块，这点曾经让我走了很多弯路，TMD居然没有文章提及这点。使用sqlite模块:</span></p>
<blockquote><p>#tar -zxf proftpd-1.3.2.tar.gz<br />
#cd proftpd-1.3.2<br />
#./configure &#8211;prefix=/usr/local/proftpd &#8211;with-modules=mod_sql:mod_sql_sqlite<br />
#make<br />
#make install</p></blockquote>
<p><strong>2，配置ProFTPD</strong><br />
编辑/usr/local/proftpd/etc/proftpd.conf文件，加入下面列出来的这一大坨参数。<br />
这里只说说跟Sqlite3有关的参数，其他比较有用的参数配置说明，满世界都是。完整配置文件放在最后。<br />
其实除了SQLBackend和SQLConnectInfo两个参数之外，剩下的一些参数在配置其他数据库时也会用到<br />
我在配置这些数据库相关参数的时候，走了很多弯路，查了很多文档，记下来也给自己脑子备个份。</p>
<blockquote><p>#首先来说这俩，定义proftpd以什么身份来运行，跟apache里的是一个意思<br />
#我是习惯了apache定义为www用户和www组，配置proftpd也就这样了<br />
#以什么身份运行，我个人感觉没啥特别意义，关键是虚拟用户对实体用户的映射！<br />
<span style="color: #ff6600;">User                    www<br />
Group                   www</span><br />
#sqlite2跟3差别较大，各软件平台对其支持也是分开来的，比如PHP<br />
#这里就是指明，使用sqlite3<br />
<span style="color: #ff6600;">SQLBackend sqlite3</span><br />
#数据库文件的绝对路径，一定要绝对<br />
<span style="color: #ff6600;">SQLConnectInfo /home/www/ftpd.db</span><br />
#数据库内虚拟用户的密码认证方式<br />
#我认为Backend的意思就是数据库自己的认证方式，比如mysql的password方案<br />
#该方案可以指定多种，使用空格隔开，按照先后，依次try<br />
#下面这句的意思就是“先用sqlite自己的认证方式(我用的明文，其他解决方案没研究)<br />
#如果不行，再使用crypt(3)的方案”，实际配置文件里我只要了一个Backend<br />
<span style="color: #ff6600;">SQLAuthTypes Backend Crypt</span><br />
#自定义存放用户信息的表和字段<br />
#下面这句的意思就是<br />
#users表 里的 字段：用户名 密码 系统映射uid 系统映射gid 主目录 shell路径<br />
#切记：表和字段的名字可以随便起(跟实际数据库中的表和字段相对应)，但顺序不可乱<br />
#按照我对英文howto的理解，前4个字段名是必须要设置的，后两个如果自己用不上<br />
#必须使用NULL来填补，这样mod_sql模块就不会去检索这俩字段了<br />
<span style="color: #ff6600;">SQLUserInfo users user_name user_passwd uid gid home_dir NULL</span><br />
#如果主目录字段名设置为NULL，那么这里这个就必须要定义<br />
#这个是用来定义那些没有“主目录定义的用户”的主目录，有点绕口:P<br />
<span style="color: #ff6600;">#SQLDefaultHomedir &#8220;/tmp&#8221;</span><br />
#这个参数设置为off的意思，是不让proftpd去检查该FTP用户映射到系统里的用户的shell<br />
#就是说，有没有shell，我都让你登陆。特别是上面的字段，将shell路径这个设置为了NULL<br />
<span style="color: #ff6600;">RequireValidShell off</span><br />
#组信息，没啥意思，就这么放着吧，意思跟上面那个SQLUserInfo一样<br />
#表名 组名 组id 成员<br />
<span style="color: #ff6600;">SQLGroupInfo groups group_name gid members</span><br />
#这里是用户身份认证的程度，只验证user，连带group啥的都验证<br />
#图简单，我这里只验证user这一层<br />
<span style="color: #ff6600;">SQLAuthenticate users</span><br />
#设置ProFTPD允许登陆的最小UID，这个UID是映射到linux系统内实际用户的UID，小于这个值将不允许登陆<br />
#这个值如果不设置，系统默认的是999，在很多国内的文章里，uid和gid都是设置5000多<br />
#所以即使不管这个值，也不会有问题，可是如果你跟我一样，映射用户的uid和gid都小于999了，就要注意它了<br />
#我的www用户的uid和gid都是504，在这里，卡了我有一个多小时，TNND<br />
<span style="color: #ff6600;">SQLMinUserUID 500</span><br />
#这两个的意思，是所有未在数据库中定义uid和gid的用户的默认uid及gid<br />
<span style="color: #ff6600;">SQLDefaultUID 504</span><br />
<span style="color: #ff6600;">SQLDefaultGID 504</span></p></blockquote>
<p>我的完整的proftpd.conf文件</p>
<blockquote><p><a href="http://rui7905.googlecode.com/svn/trunk/proftpd_sqlite3" target="_blank">http://rui7905.googlecode.com/svn/trunk/proftpd_sqlite3</a></p></blockquote>
<p><strong>3，建立数据库及用户表</strong><br />
#sqlite3 /home/www/ftpd.db 数据库就建好了，简单吧~<br />
其实理论上，这个文件的路径，是放在哪里都可以的。我配置完这个平台后，又用php写了一个简单的管理平台<br />
为了方便我的apache运行用户www读写数据库，就放在了www的主目录下。。<br />
在sqlite3环境下，用下面这个语句建立数据表</p>
<blockquote><p>CREATE TABLE &#8220;users&#8221; (&#8221;user_name&#8221; varchar(20), &#8220;user_passwd&#8221; varchar(50), &#8220;uid&#8221; int(11) NOT NULL  DEFAULT 504, &#8220;gid&#8221; int(11) NOT NULL  DEFAULT 504, &#8220;home_dir&#8221; varchar(200), &#8220;shell&#8221; varchar(200))</p></blockquote>
<p>下面创建一个新用户：</p>
<blockquote><p>INSERT INTO &#8220;users&#8221; VALUES(&#8217;test&#8217;,'test&#8217;,504,504,&#8217;/home/www/ftp/test&#8217;,NULL);</p></blockquote>
<p>表的uid和gid的默认值都设置为了504，即www用户在系统内的uid和gid的值。新添加字段时，这两个字段我也设置了。www用户和组在我系统内是早就建好的，uid和gid分别都是504。通过这两个字段的值，就完成了proftpd内的虚拟用户跟系统内实体用户的映射。具体到自己，请根据实际情况来设置这两个字段的默认值，及新添加记录的值。<br />
<strong>4，最后</strong><br />
到现在，整个配置应该是完成了，使用这个命令来启动ProFTPD:</p>
<blockquote><p>/usr/local/proftpd/sbin/proftpd -c /usr/local/proftpd/etc/proftpd.conf &amp;</p></blockquote>
<p>参考资料：<br />
ProFTPD Howto:SQL and mod_sql:<br />
<a title="ProFTPD Howto:SQL and mod_sql" href="http://www.proftpd.org/docs/howto/SQL.html" target="_blank">http://www.proftpd.org/docs/howto/SQL.html</a><br />
ProFTPD module mod_sql:<br />
<a title="ProFTPD module mod_sql" href="http://www.proftpd.org/docs/contrib/mod_sql.html" target="_blank">http://www.proftpd.org/docs/contrib/mod_sql.html</a><br />
ProFTPD module mod_sql_sqlite:<br />
<a title="ProFTPD module mod_sql_sqlite" href="http://www.proftpd.org/docs/contrib/mod_sql_sqlite.html">http://www.proftpd.org/docs/contrib/mod_sql_sqlite.html</a><br />
Configuration Directive List:<br />
<a title="Configuration Directive List" href="http://www.proftpd.org/docs/directives/linked/by-name.html" target="_blank">http://www.proftpd.org/docs/directives/linked/by-name.html</a><br />
Simple MySQL Authentication:<br />
<a title="Simple MySQL Authentication" href="http://www.proftpd.org/docs/configs/mysql_simple.conf" target="_blank">http://www.proftpd.org/docs/configs/mysql_simple.conf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/182.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>nginx 和 subversion</title>
		<link>http://kevin.9511.net/archives/179.html</link>
		<comments>http://kevin.9511.net/archives/179.html#comments</comments>
		<pubDate>Tue, 31 Mar 2009 18:42:34 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/179.html</guid>
		<description><![CDATA[实在厌倦了apache的臃肿，打算彻底投奔nginx的怀抱了。
编译，安装，迁移，一切都很顺利 ，最后一步在迁移svn的时候卡住了。
把nginx作为subversion的前端webserver居然目前没有解决方案……
搞了一个晚上，最终还是采取了proxy的办法，把发向nginx的svn请求转到apache上去了 ，哎。
为啥nginx没有这方面的解决方案，也大概查了个水落石出。因为这方面中文资料实在是少，让我费了颇多的周折，
现在就明明白白的说一下吧。
在nginx.net的Mailing list里，nginx的作者Igor Sysoev说了，支持SVN需要有三个东西
 1) full WebDAV support,
2) DeltaV support,
3) SVN repo format support.
而在nginx里的NginxHttpDavModule，仅仅对以上三项中的第一项WebDAV有了初步的支持(目前来看Igor Sysoev并没有升级的想法)，对于几个高级的WebDAV操作（比如OPTIONS、PROPFIND）并不支持，而这些操作，恰恰是SVN所必须的。而剩下的两项，更是一点支持都没。
所以，就目前来说，想单纯的nginx+subversion，基本上是不可能的。
在刚开始研究这个问题的时候，并不知道除了WebDAV还必须要有其他两个东西。所以满世界找nginx上WebDAV的解决方案，以为搞定这个，就万事大吉了。别说，还真让我在一个老外的博客上给找着一个。这家伙的方法很巧妙，他用通过查阅WebDAV的RFC文档，将绝大多数NginxHttpDavModule不支持的操作用PHP代码实现了，并且通过配置nginx，根据header信息把这些请求重定向到了这个PHP程序。这是这篇博客的地址，有志于自己动手解决这个问题的人，可以参考一下：）
最后感叹一下，为什么计算机方面的问题，总是能在国外的网站和MaillingList找到答案呢？是中国人都不会么？还是这些问题只有我这一个中国人遇到了？
]]></description>
			<content:encoded><![CDATA[<p>实在厌倦了apache的臃肿，打算彻底投奔nginx的怀抱了。<br />
编译，安装，迁移，一切都很顺利 ，最后一步在迁移svn的时候卡住了。<br />
把nginx作为subversion的前端webserver居然目前没有解决方案……</p>
<p>搞了一个晚上，最终还是采取了proxy的办法，把发向nginx的svn请求转到apache上去了 ，哎。<br />
为啥nginx没有这方面的解决方案，也大概查了个水落石出。因为这方面中文资料实在是少，让我费了颇多的周折，<br />
现在就明明白白的说一下吧。</p>
<p>在nginx.net的<a href="http://marc.info/?l=nginx" title="MARC archive" target="_blank">Mailing list</a>里，nginx的作者Igor Sysoev说了，支持SVN需要有三个东西</p>
<blockquote><p> 1) full WebDAV support,<br />
2) DeltaV support,<br />
3) SVN repo format support.</p></blockquote>
<p>而在nginx里的NginxHttpDavModule，仅仅对以上三项中的第一项WebDAV有了初步的支持(目前来看Igor Sysoev并没有升级的想法)，对于几个高级的WebDAV操作（比如OPTIONS、PROPFIND）并不支持，而这些操作，恰恰是SVN所必须的。而剩下的两项，更是一点支持都没。</p>
<p><strong>所以，就目前来说，想单纯的nginx+subversion，基本上是不可能的。</strong></p>
<p>在刚开始研究这个问题的时候，并不知道除了WebDAV还必须要有其他两个东西。所以满世界找nginx上WebDAV的解决方案，以为搞定这个，就万事大吉了。别说，还真让我在一个老外的博客上给找着一个。这家伙的方法很巧妙，他用通过查阅<a href="http://www.ietf.org/rfc/rfc2518.txt" title="RFC2518">WebDAV的RFC文档</a>，将绝大多数NginxHttpDavModule不支持的操作用PHP代码实现了，并且通过配置nginx，根据header信息把这些请求重定向到了这个PHP程序。<a href="http://blog.agoragames.com/2009/03/20/webdav-nginx-play-nice/">这是这篇博客的地址</a>，有志于自己动手解决这个问题的人，可以参考一下：）</p>
<p>最后感叹一下，为什么计算机方面的问题，总是能在国外的网站和MaillingList找到答案呢？是中国人都不会么？还是这些问题只有我这一个中国人遇到了？</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/179.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Install subversion-1.5.2 on Linux</title>
		<link>http://kevin.9511.net/archives/178.html</link>
		<comments>http://kevin.9511.net/archives/178.html#comments</comments>
		<pubDate>Tue, 31 Mar 2009 06:14:04 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/178.html</guid>
		<description><![CDATA[1，Install Apache,APR and APR-util(http://apr.apache.org/)
 #tar -zxf apr-1.3.3.tar.gz
#cd apr-1.3.3
#./configure
#make
#make install
 #tar -zxf apr-util-1.3.4.tar.gz
#cd apr-util-1.3.4
#./configure &#8211;with-apr=/usr/local/apr/
#make
#make install
编译apache，加如下参数
 &#8211;enable-dav &#8211;with-apr=/usr/local/apr/bin/apr-1-config &#8211;with-apr-util=/usr/local/apr/bin/apu-1-config
2. Install Neon(http://www.webdav.org/neon/)
neon is an HTTP and WebDAV client library, with a C interface.
 #tar -zxf neon-0.28.3.tar.gz
#cd neon-0.28.3
#./configure &#8211;prefix=/usr/local/neon
#make
#make install
3. Install Subversion (http://subversion.tigris.org/)
 #tar -zxf subversion-1.5.2.tar.gz
#cd subversion-1.5.2
#./configure &#8211;prefix=/usr/local/subversion &#8211;with-apxs=/usr/local/apache2/bin/apxs &#8211;with-apr=/usr/local/apr &#8211;with-apr-util=/usr/local/apr &#8211;with-neon=/usr/local/neon
#make
#make install
编译过程中，发生如下错误
/usr/bin/ld: cannot find -lexpat
collect2: ld returned [...]]]></description>
			<content:encoded><![CDATA[<p><strong>1，Install Apache,APR and APR-util</strong>(http://apr.apache.org/)</p>
<blockquote><p> #tar -zxf apr-1.3.3.tar.gz<br />
#cd apr-1.3.3<br />
#./configure<br />
#make<br />
#make install</p></blockquote>
<blockquote><p> #tar -zxf apr-util-1.3.4.tar.gz<br />
#cd apr-util-1.3.4<br />
#./configure &#8211;with-apr=/usr/local/apr/<br />
#make<br />
#make install</p></blockquote>
<p>编译apache，加如下参数</p>
<blockquote><p> &#8211;enable-dav &#8211;with-apr=/usr/local/apr/bin/apr-1-config &#8211;with-apr-util=/usr/local/apr/bin/apu-1-config</p></blockquote>
<p><strong>2. Install Neon</strong>(http://www.webdav.org/neon/)<br />
neon is an HTTP and WebDAV client library, with a C interface.</p>
<blockquote><p> #tar -zxf neon-0.28.3.tar.gz<br />
#cd neon-0.28.3<br />
#./configure &#8211;prefix=/usr/local/neon<br />
#make<br />
#make install</p></blockquote>
<p><strong>3. Install Subversion</strong> (http://subversion.tigris.org/)</p>
<blockquote><p> #tar -zxf subversion-1.5.2.tar.gz<br />
#cd subversion-1.5.2<br />
#./configure &#8211;prefix=/usr/local/subversion &#8211;with-apxs=/usr/local/apache2/bin/apxs &#8211;with-apr=/usr/local/apr &#8211;with-apr-util=/usr/local/apr &#8211;with-neon=/usr/local/neon<br />
#make<br />
#make install</p></blockquote>
<p>编译过程中，发生如下错误</p>
<blockquote><p>/usr/bin/ld: cannot find -lexpat<br />
collect2: ld returned 1 exit status</p></blockquote>
<p>确认libexpat已经被载入</p>
<blockquote><p># ldconfig -p|grep expat<br />
libexpat.so.0 (libc6) =&gt; /usr/lib/libexpat.so.0</p></blockquote>
<p>做个链接，并重载libs，最后检查一下</p>
<blockquote><p>#cd /usr/lib<br />
#ln -s libexpat.so.0.5.0 libexpat.so<br />
#ldconfig<br />
#ldconfig -p|grep expat<br />
libexpat.so.0 (libc6) =&gt; /usr/lib/libexpat.so.0<br />
libexpat.so (libc6) =&gt; /usr/lib/libexpat.so</p></blockquote>
<p>继续编译，通过，OY<br />
<strong>4. 配置</strong><br />
打开apache的httpd.conf文件，查找下面两行内容，如果存在，则表示subversion已经安装成功</p>
<blockquote><p>LoadModule dav_svn_module     modules/mod_dav_svn.so<br />
LoadModule authz_svn_module   modules/mod_authz_svn.so</p></blockquote>
<p>建立代码仓库及配置文件</p>
<blockquote><p>#cd /usr/local/subversion/<br />
#mkdir repos<br />
#mkdir www<br />
#touch auth<br />
#cd repos<br />
#svnadmin create myproject</p></blockquote>
<p>通过apache的htpasswd工具创建用户，并按提示输入密码</p>
<blockquote><p>#cd ..<br />
#/usr/local/apache2/bin/htpasswd -c /usr/local/subversion/passwd kevin</p></blockquote>
<p>编辑auth文件，写入以下内容，赋予此用户对于myproject的读写权限（例子很简单，更复杂的权限配置，请自己去查官方文档或google搜索“SVN权限”）</p>
<blockquote><p> [/]<br />
* = rw</p>
<p>[/svn]<br />
* = rw</p>
<p>[/svn/myproject]<br />
lirui=rw</p></blockquote>
<p>配置apache，设置svn的工作目录</p>
<blockquote><p> &lt;Location /svn&gt;<br />
DAV svn<br />
SVNParentPath /usr/local/subversion/repos<br />
AuthType Basic<br />
AuthName &#8220;Subversion repository&#8221;<br />
AuthUserFile /usr/local/subversion/passwd<br />
AuthzSVNAccessFile /usr/local/subversion/auth<br />
Require valid-user<br />
&lt;/Location&gt;</p></blockquote>
<p>重启apache</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/178.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>总结：ldconfig及 LD_LIBRARY_PATH</title>
		<link>http://kevin.9511.net/archives/177.html</link>
		<comments>http://kevin.9511.net/archives/177.html#comments</comments>
		<pubDate>Mon, 30 Mar 2009 21:56:53 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[ldconfig]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/177.html</guid>
		<description><![CDATA[为了装个nginx，在一个裸机上折腾了一宿。
也不知道是机器慢，还是的确如此，编译gcc花了快一个小时。。。很是吐血。
结果编译安装完成后，去编译其他东西，结果发现了找不到编译器的提示。。。
东查西找，左蒙右猜，终于把问题搞定了，问题就出在这个 LD_LIBRARY_PATH 上面
从别处摘抄总结一下。
 1. 往/lib和/usr/lib里面加东西，是不用修改/etc/ld.so.conf的，但是完了之后要调一下ldconfig，不然这个library会找不到
2. 想往上面两个目录以外加东西的时候，一定要修改/etc/ld.so.conf，然后再调用ldconfig，不然也会找不到
比如安装了一个mysql到/usr/local/mysql，mysql有一大堆library在/usr/local/mysql/lib下面，这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib，保存过后ldconfig一下，新的library才能在程序运行时被找到。
3. 如果想在这两个目录以外放lib，但是又不想在/etc/ld.so.conf中加东西（或者是没有权限加东西）。那也可以，就是export一个全局变量LD_LIBRARY_PATH，然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案，在没有权限或临时需要的时候使用。
4. ldconfig做的这些东西都与运行程序时有关，跟编译时一点关系都没有。编译的时候还是该加-L就得加，不要混淆了。
5. 总之，就是不管做了什么关于library的变动后，最好都ldconfig一下，不然会出现一些意想不到的结果。不会花太多的时间，但是会省很多的事。
LD_LIBRARY_PATH 的意思：告诉loader在哪些目录中可以找到共享库。可以设置多个搜索目录，这些目录之间用冒号分隔开。在linux下，还提供了另外一种方式来完成同样的功能，你可以把这些目录加到/etc/ld.so.conf中，或则在/etc/ld.so.conf.d里创建一个文件，把目录加到这个文件里。当然，这是系统范围内全局有效的，而环境变量只对当前shell有效。按照惯例，除非你用上述方式指明，loader是不会在当前目录下去找共享库的，正如shell不会在当前目前找可执行文件一样。
]]></description>
			<content:encoded><![CDATA[<p>为了装个nginx，在一个裸机上折腾了一宿。</p>
<p>也不知道是机器慢，还是的确如此，编译gcc花了快一个小时。。。很是吐血。</p>
<p>结果编译安装完成后，去编译其他东西，结果发现了找不到编译器的提示。。。</p>
<p>东查西找，左蒙右猜，终于把问题搞定了，问题就出在这个 LD_LIBRARY_PATH 上面</p>
<p>从别处摘抄总结一下。</p>
<blockquote><p> 1. 往/lib和/usr/lib里面加东西，是不用修改/etc/ld.so.conf的，但是完了之后要调一下ldconfig，不然这个library会找不到</p>
<p>2. 想往上面两个目录以外加东西的时候，一定要修改/etc/ld.so.conf，然后再调用ldconfig，不然也会找不到<br />
比如安装了一个mysql到/usr/local/mysql，mysql有一大堆library在/usr/local/mysql/lib下面，这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib，保存过后ldconfig一下，新的library才能在程序运行时被找到。</p>
<p>3. 如果想在这两个目录以外放lib，但是又不想在/etc/ld.so.conf中加东西（或者是没有权限加东西）。那也可以，就是export一个全局变量LD_LIBRARY_PATH，然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案，在没有权限或临时需要的时候使用。</p>
<p>4. ldconfig做的这些东西都与运行程序时有关，跟编译时一点关系都没有。编译的时候还是该加-L就得加，不要混淆了。</p>
<p>5. 总之，就是不管做了什么关于library的变动后，最好都ldconfig一下，不然会出现一些意想不到的结果。不会花太多的时间，但是会省很多的事。</p></blockquote>
<p>LD_LIBRARY_PATH 的意思：告诉loader在哪些目录中可以找到共享库。可以设置多个搜索目录，这些目录之间用冒号分隔开。在linux下，还提供了另外一种方式来完成同样的功能，你可以把这些目录加到/etc/ld.so.conf中，或则在/etc/ld.so.conf.d里创建一个文件，把目录加到这个文件里。当然，这是系统范围内全局有效的，而环境变量只对当前shell有效。按照惯例，除非你用上述方式指明，loader是不会在当前目录下去找共享库的，正如shell不会在当前目前找可执行文件一样。</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/177.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>linux下用tcpdump命令截获soap信息</title>
		<link>http://kevin.9511.net/archives/174.html</link>
		<comments>http://kevin.9511.net/archives/174.html#comments</comments>
		<pubDate>Mon, 23 Mar 2009 10:43:53 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tcpdump]]></category>
		<category><![CDATA[抓包]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/174.html</guid>
		<description><![CDATA[this is probably the easiest way to monitor SOAP messages.
simply use
#tcpdump -i eth0 -A -s 1024 port 80 &#124; tee dump.log
to log all the packet sent to port 80 to dump.log
]]></description>
			<content:encoded><![CDATA[<p>this is probably the easiest way to monitor SOAP messages.</p>
<p>simply use</p>
<p>#tcpdump -i eth0 -A -s 1024 port 80 | tee dump.log</p>
<p>to log all the packet sent to port 80 to dump.log</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/174.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转载]Mysql 数据库字符集</title>
		<link>http://kevin.9511.net/archives/173.html</link>
		<comments>http://kevin.9511.net/archives/173.html#comments</comments>
		<pubDate>Sun, 15 Mar 2009 18:52:20 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[字符集]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/173.html</guid>
		<description><![CDATA[MySQL 4.1开始，对多语言的支持有了很大变化 (这导致了问题的出现)。尽管大部分的地方 (包括个人使用和主机提供商)，MySQL 3、4.0 仍然占主导地位；但 MySQL 4.1 乃至5.0是 MySQL 官方推荐的数据库，已经有主机提供商开始提供并将会越来越多；因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集，成功的蒙蔽了许多 PHP 程序的开发者和用户，掩盖了在中文等语言环境下会出现的问题。
MySQL 4.1开始把多国语言字符集分的更加详细，所以导致数据库迁移，或则dz论坛升级到4.0后（dz4.0开始使用gbk或utf-8编码）出现乱码问题。
MySQL 4.1的字符集支持(Character Set Support)有两个方面：字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次: 服务器(server)，数据库(database)，数据表(table)和连接(connection)。
查看系统的字符集和排序方式的设定可以通过下面的两条命令：
QUOTE:
mysql&#62; SHOW VARIABLES LIKE &#8216;character_set_%&#8217;;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; Variable_name &#124; Value &#124;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; character_set_client &#124; latin1 &#124;
&#124; character_set_connection &#124; latin1 &#124;
&#124; character_set_database &#124; latin1 &#124;
&#124; character_set_results &#124; latin1 &#124;
&#124; character_set_server &#124; latin1 &#124;
&#124; character_set_system &#124; utf8 &#124;
&#124; [...]]]></description>
			<content:encoded><![CDATA[<p><span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry">MySQL 4.1开始，对多语言的支持有了很大变化 (这导致了问题的出现)。尽管大部分的地方 (包括个人使用和主机提供商)，MySQL 3、4.0 仍然占主导地位；但 MySQL 4.1 乃至5.0是 MySQL 官方推荐的数据库，已经有主机提供商开始提供并将会越来越多；因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集，成功的蒙蔽了许多 PHP 程序的开发者和用户，掩盖了在中文等语言环境下会出现的问题。</span></p>
<p>MySQL 4.1开始把多国语言字符集分的更加详细，所以导致数据库迁移，或则dz论坛升级到4.0后（dz4.0开始使用gbk或utf-8编码）出现乱码问题。</p>
<p>MySQL 4.1的字符集支持(Character Set Support)有两个方面：字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次: 服务器(server)，数据库(database)，数据表(table)和连接(connection)。</p>
<p>查看系统的字符集和排序方式的设定可以通过下面的两条命令：<br />
QUOTE:<br />
mysql&gt; SHOW VARIABLES LIKE &#8216;character_set_%&#8217;;<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| Variable_name | Value |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| character_set_client | latin1 |<br />
| character_set_connection | latin1 |<br />
| character_set_database | latin1 |<br />
| character_set_results | latin1 |<br />
| character_set_server | latin1 |<br />
| character_set_system | utf8 |<br />
| character_sets_dir | /usr/share/mysql/charsets/ |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
7 rows in set (0.00 sec) <span></span></p>
<p>mysql&gt; SHOW VARIABLES LIKE &#8216;collation_%&#8217;;<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| Variable_name | Value |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| collation_connection | latin1_swedish_ci |<br />
| collation_database | latin1_swedish_ci |<br />
| collation_server | latin1_swedish_ci |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
3 rows in set (0.00 sec)</p>
<p>MySQL 4.1 对于字符集的指定可以细化到一台机器上安装的 MySQL，其中的一个数据库，其中的一张表，其中的一栏，应该用什么字符集。但是，传统的 Web 程序在创建数据库和数据表时并没有使用那么复杂的配置，它们用的是默认的配置，那么，默认的配置从何而来呢？</p>
<p>编译 MySQL 时，指定了一个默认的字符集，这个字符集是 latin1；<br />
安装 MySQL 时，可以在配置文件 (my.ini) 中指定一个默认的的字符集，如果没指定，这个值继承自编译时指定的；<br />
启动 mysqld 时，可以在命令行参数中指定一个默认的的字符集，如果没指定，这个值继承自配置文件中的；<br />
此时 character_set_server 被设定为这个默认的字符集；<br />
当创建一个新的数据库时，除非明确指定，这个数据库的字符集被缺省设定为 character_set_server；<br />
当选定了一个数据库时，character_set_database 被设定为这个数据库默认的字符集；<br />
在这个数据库里创建一张表时，表默认的字符集被设定为 character_set_database，也就是这个数据库默认的字符集；<br />
当在表内设置一栏时，除非明确指定，否则此栏缺省的字符集就是表默认的字符集；<br />
这个字符集就是数据库中实际存储数据采用的字符集，mysqldump 出来的内容就是这个字符集下的；<br />
当我们按照原来的方式通过PHP存取MySQL数据库时，就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询，你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。<br />
想要进行“正确”的存储和得到“正确”的结果，最方便的是在所有query开始之前执行一下： <span></span></p>
<p>SET NAMES &#8216;gbk&#8217;;<br />
其中gbk是数据库字符集。</p>
<p>它相当于下面的三句指令：<br />
SET character_set_client = gbk;<br />
SET character_set_results = gbk;<br />
SET character_set_connection = gbk;</p>
<p>4.1和5.0默认使用的是latin1字符集(木头:妈的,老外真霸道,妄想让全世界都是使用瑞典字符集吗)<br />
如果我们只想使用gbk字符集存储和获取数据,<br />
我们在编译mysql 4.1和 5.0的时候，需要注意在my.ini或者my.cnf中添加两处参数<br />
[mysqld]<br />
default-character-set=utf8</p>
<p>#settings for clients (connection, results, clients)<br />
[mysql]<br />
default-character-set=utf8</p>
<p>下面我们来说主题，如何转换数据库字符集</p>
<p>更改存储字符集<br />
主要的思想就是把数据库的字符集有latin1改为gbk，big5,或者utf8; 以下操作必须拥有主机权限。假设当前操作的数据库名为：database</p>
<p>导出<br />
首先需要把数据导为mysql4.0的格式，具体的命令如下：<br />
mysqldump -uroot -p &#8211;default-character-set=latin1 &#8211;set-charset=gbk &#8211;skip-opt databse &gt; d4.sql</p>
<p>&#8211;default-characte-set 以前数据库的字符集，这个一般情况下都是latin1的，<br />
&#8211;set-charset 导出的数据的字符集，这个可以设置为gbk，utf8,或者big5<br />
导入<br />
首先使用下面语句新建一个GBK字符集的数据库（test）</p>
<p>CREATE DATABASE `d4` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;<br />
然后把刚才导出的数据导入到当前的数据库中就ok了。</p>
<p>mysql -uroot -p &#8211;default-character-set=gbk -f d4&lt;d4.sql<br />
通过以上的导出和导入就把数据库的字符集改为正确的存储方式了。</p>
<p>其中d4为新建库的名称，d4.sql为导出文件的名字</p>
<p>但是这种方法，发现数据库数据存储量无端变大30%，真是郁闷</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/173.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP5下安装sqlite模块的小问题</title>
		<link>http://kevin.9511.net/archives/169.html</link>
		<comments>http://kevin.9511.net/archives/169.html#comments</comments>
		<pubDate>Sun, 12 Oct 2008 21:43:23 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/169.html</guid>
		<description><![CDATA[今天在用pecl为PHP5编译安装sqlite模块的时候，遇到了下面这个错误而编译不过去
sqlite.c:56: error: &#8216;BYREF_NONE&#8217; undeclared here (not in a function)
GOOGLE一番，原来这是个从2006年7月就存在的BUG。虽然官方在pecl.php.net的关于此bug的详情页里说已经修复了，但不止一个人在1年甚至2年后依然表示错误依旧～！看来老外干活也会偷懒啊，出了sqlite3的模块，老的sqlite模块就不维护了，哎～～
在那个页面里，也有人提供了自己修复此BUG的方法：
1，来到PHP安装目录内的bin目录下
cd /usr/local/php-5.2.3/bin
2，下载这个模块的源码
pecl download sqlite
3，解压并开始编译
$ tar zxvf SQLite-1.0.3.tgz
$ cd SQLite-1.0.3
$ ../phpize
$ ./configure &#8211;with-php-config=/usr/local/php-5.2.3/bin/php-config
$ make
4，在make的过程如报告以上错误则编辑sqlite.c文件，将下面这行注释掉
/* static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; */
然后将下面这三行
function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, arg3_force_ref)
PHP_FE(sqlite_popen, arg3_force_ref)
改为:
function_entry sqlite_functions[] = {
PHP_FE(sqlite_open, third_arg_force_ref)
PHP_FE(sqlite_popen, third_arg_force_ref)
5，重新编译
$ make
$ make install
将编译生成的sqlite.so文件，复制到extension_dir指定的目录中，编辑php.ini文件，加入如下一行
extension=sqlite.so
重启web服务后即可
]]></description>
			<content:encoded><![CDATA[<p>今天在用pecl为PHP5编译安装sqlite模块的时候，遇到了下面这个错误而编译不过去</p>
<blockquote><p>sqlite.c:56: error: &#8216;BYREF_NONE&#8217; undeclared here (not in a function)</p></blockquote>
<p>GOOGLE一番，原来这是个从2006年7月就存在的BUG。虽然官方在<a href="http://pecl.php.net/bugs/bug.php?id=8181" target="_blank">pecl.php.net的关于此bug的详情页</a>里说已经修复了，但不止一个人在1年甚至2年后依然表示错误依旧～！看来老外干活也会偷懒啊，出了sqlite3的模块，老的sqlite模块就不维护了，哎～～</p>
<p>在那个页面里，也有人提供了自己修复此BUG的方法：<br />
1，来到PHP安装目录内的bin目录下</p>
<blockquote><p>cd /usr/local/php-5.2.3/bin</p></blockquote>
<p>2，下载这个模块的源码</p>
<blockquote><p>pecl download sqlite</p></blockquote>
<p>3，解压并开始编译</p>
<blockquote><p>$ tar zxvf SQLite-1.0.3.tgz<br />
$ cd SQLite-1.0.3<br />
$ ../phpize<br />
$ ./configure &#8211;with-php-config=/usr/local/php-5.2.3/bin/php-config<br />
$ make</p></blockquote>
<p>4，在make的过程如报告以上错误则编辑sqlite.c文件，将下面这行注释掉</p>
<blockquote><p>/* static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; */</p></blockquote>
<p>然后将下面这三行</p>
<blockquote><p>function_entry sqlite_functions[] = {<br />
PHP_FE(sqlite_open, arg3_force_ref)<br />
PHP_FE(sqlite_popen, arg3_force_ref)</p></blockquote>
<p>改为:</p>
<blockquote><p>function_entry sqlite_functions[] = {<br />
PHP_FE(sqlite_open, third_arg_force_ref)<br />
PHP_FE(sqlite_popen, third_arg_force_ref)</p></blockquote>
<p>5，重新编译</p>
<blockquote><p>$ make<br />
$ make install</p></blockquote>
<p>将编译生成的sqlite.so文件，复制到extension_dir指定的目录中，编辑php.ini文件，加入如下一行</p>
<blockquote><p>extension=sqlite.so</p></blockquote>
<p>重启web服务后即可</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/169.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HowTo: Install Nginx and php-fpm on Linux</title>
		<link>http://kevin.9511.net/archives/166.html</link>
		<comments>http://kevin.9511.net/archives/166.html#comments</comments>
		<pubDate>Fri, 19 Sep 2008 07:15:19 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php-fpm]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/166.html</guid>
		<description><![CDATA[最近要为公司搭建新的开发环境，打算舍弃用了n年的apache，换换口味，装个nginx试试。
在网上找了很多文档，没有一个能让我顺利安装完成的。还是自己来整理整理吧……
1，Install Pcre
来这里获取Pcre的最新版本
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
#tar -zxf pcre-7.8.tar.gz
#cd pcre-7.8
#./configure
#make
#make install
2. Install Nginx(http://www.nginx.net/)
#tar -zxf nginx-0.6.32.tar.gz
#cd nginx-0.6.32
#./configure &#8211;prefix=/usr/local/nginx-0.6.32
#make
#make install
3. Install PHP with php-fpm (http://www.php.net/)
nginx是通过fastcgi来支持PHP的，使用php-fpm补丁是一个比较方便的管理fastcgi进程的解决方案。
比通过脚本或是lighttpd的spawn模块要简单的多。
下载好PHP后，来这里获取与PHP版本相对应的php-fpm补丁：http://php-fpm.anight.org/
#tar -zxf php-5.2.6.tar.gz
#cd php-5.2.6
#zcat ../php-5.2.6-fpm-0.5.8.diff.gz &#124; patch -p1  #为PHP打补丁
#./configure &#8211;prefix=/usr/local/php-5.2.6 &#8211;with-sqlite=shared &#8211;enable-fastcgi &#8211;enable-fpm
#make
#make install
 注：PHP的其他模块(如mysql、gd等)请按需自己配置
#cp php.ini-recommended /usr/local/php-5.2.6/lib/php.ini
修改php.ini
cgi.fix_pathinfo=1
4. Configuring
A. 配置nginx，在/usr/local/nginx-0.6.32/conf目录下新建名为php_fcgi.conf的文件，内容如下：
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
修改nginx.conf文件，在需要支持PHP的虚拟主机配置中，加入如下一行：
include php_fcgi.conf;
B. 配置php-fpm模块，编辑/usr/local/php-5.2.6/etc/php-fpm.conf文件
找到“Unix user of processes”和“Unix group of processes”两段，将前面注释去掉，并将值改为与nginx配置相同的用户和组。如下：
Unix user of processes
&#60;value [...]]]></description>
			<content:encoded><![CDATA[<p>最近要为公司搭建新的开发环境，打算舍弃用了n年的apache，换换口味，装个nginx试试。<br />
在网上找了很多文档，没有一个能让我顺利安装完成的。还是自己来整理整理吧……</p>
<p><strong>1，Install Pcre</strong></p>
<p>来这里获取Pcre的最新版本<br />
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/</p>
<blockquote><p>#tar -zxf pcre-7.8.tar.gz<br />
#cd pcre-7.8<br />
#./configure<br />
#make<br />
#make install</p></blockquote>
<p><strong>2. Install Nginx</strong>(http://www.nginx.net/)</p>
<blockquote><p>#tar -zxf nginx-0.6.32.tar.gz<br />
#cd nginx-0.6.32<br />
#./configure &#8211;prefix=/usr/local/nginx-0.6.32<br />
#make<br />
#make install</p></blockquote>
<p><strong>3. Install PHP with php-fpm</strong> (http://www.php.net/)</p>
<p>nginx是通过fastcgi来支持PHP的，使用php-fpm补丁是一个比较方便的管理fastcgi进程的解决方案。<br />
比通过脚本或是lighttpd的spawn模块要简单的多。</p>
<p>下载好PHP后，来这里获取与PHP版本相对应的php-fpm补丁：http://php-fpm.anight.org/</p>
<blockquote><p>#tar -zxf php-5.2.6.tar.gz<br />
#cd php-5.2.6<br />
#zcat ../php-5.2.6-fpm-0.5.8.diff.gz | patch -p1  <span style="color: #ff6600;">#为PHP打补丁</span><br />
#./configure &#8211;prefix=/usr/local/php-5.2.6 &#8211;with-sqlite=shared &#8211;enable-fastcgi &#8211;enable-fpm<br />
#make<br />
#make install<br />
<span style="color: #ff6600;"> 注：PHP的其他模块(如mysql、gd等)请按需自己配置</span></p>
<p>#cp php.ini-recommended /usr/local/php-5.2.6/lib/php.ini</p></blockquote>
<p>修改php.ini</p>
<blockquote><p>cgi.fix_pathinfo=1</p></blockquote>
<p><strong>4. Configuring</strong></p>
<p>A. 配置nginx，在/usr/local/nginx-0.6.32/conf目录下新建名为php_fcgi.conf的文件，内容如下：</p>
<blockquote><p>location ~ .php$ {<br />
fastcgi_pass 127.0.0.1:9000;<br />
fastcgi_index index.php;<br />
include fastcgi_params;<br />
<span style="color: #ff6600;">fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</span><br />
}</p></blockquote>
<p>修改nginx.conf文件，在需要支持PHP的虚拟主机配置中，加入如下一行：</p>
<blockquote><p>include php_fcgi.conf;</p></blockquote>
<p>B. 配置php-fpm模块，编辑/usr/local/php-5.2.6/etc/php-fpm.conf文件<br />
找到“Unix user of processes”和“Unix group of processes”两段，将前面注释去掉，并将值改为与nginx配置相同的用户和组。如下：</p>
<blockquote><p>Unix user of processes<br />
&lt;value name=&#8221;user&#8221;&gt;www&lt;/value&gt;</p>
<p>Unix group of processes<br />
&lt;value name=&#8221;group&#8221;&gt;www&lt;/value&gt;</p></blockquote>
<p><strong>5. Test and Over</strong></p>
<p>至此，所有安装配置的工作都已经完成。运行下面两行命令来启动nginx和php-fpm服务：</p>
<blockquote><p>/usr/local/php-5.2.6/sbin/php-fpm start<br />
/usr/local/nginx-0.6.32/sbin/nginx</p></blockquote>
<p>正确配置后，phpinfo() 页应如下显示：<br />
<img src="http://kevin.9511.net/wp-content/uploads/2008/09/phf.png" alt="phf.png" /><br />
CGI/FastCGI work as Server API<br />
<img src="http://kevin.9511.net/wp-content/uploads/2008/09/phf2.png" alt="phf2.png" /><a title="phf2.png" href="http://kevin.9511.net/wp-content/uploads/2008/09/phf2.png"><br />
</a></p>
<p>由于文件内容太长，nginx.conf和虚拟主机的配置文件的内容就不放上来了<br />
将这些乱七八糟的配置文件和php-fpm.conf一起打个包，放在这里提供下载吧</p>
<blockquote><p><a href="http://rui7905.googlecode.com/svn/trunk/nginx_php_fpm" target="_blank">http://rui7905.googlecode.com/svn/trunk/nginx_php_fpm</a></p></blockquote>
<p>在这一堆东西里，还有一个名为nginx.sh的启动控制脚本。<br />
当确认nginx和php-fpm均正确的配置并可以正常运行后，可以使用此脚本进行日常维护。</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/166.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>转载：优化PHP代码的40条建议</title>
		<link>http://kevin.9511.net/archives/158.html</link>
		<comments>http://kevin.9511.net/archives/158.html#comments</comments>
		<pubDate>Sat, 02 Feb 2008 12:44:21 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[优化]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/158.html</guid>
		<description><![CDATA[转载自http://www.yeeyan.com/
原作者: Reinhold Weber 原文  译者: davidkoree
1.如果一个方法可静态化，就对它做静态声明。速率可提升至4倍。
2.echo 比 print 快。
3.使用echo的多重参数（译注：指用逗号而不是句点）代替字符串连接。
4.在执行for循环之前确定最大循环数，不要每循环一次都计算最大值。
5.注销那些不用的变量尤其是大数组，以便释放内存。
6.尽量避免使用__get，__set，__autoload。
7.require_once()代价昂贵。
8.在包含文件时使用完整路径，解析操作系统路径所需的时间会更少。
9.如果你想知道脚本开始执行（译注：即服务器端收到客户端请求）的时刻，使用$_SERVER[‘REQUEST_TIME’]要好于time()。
10.函数代替正则表达式完成相同功能。
11.str_replace函数比preg_replace函数快，但strtr函数的效率是str_replace函数的四倍。
12.如果一个字符串替换函数，可接受数组或字符作为参数，并且参数长度不太长，那么可以考虑额外写一段替换代码，使得每次传递参数是一个字符，而不是只写一行代码接受数组作为查询和替换的参数。
13.使用选择分支语句（译注：即switch case）好于使用多个if，else if语句。
14.用@屏蔽错误消息的做法非常低效。
15.打开apache的mod_deflate模块。
16.数据库连接当使用完毕时应关掉。
17.$row[‘id’]的效率是$row[id]的7倍。
18.错误消息代价昂贵。
19.尽量不要在for循环中使用函数，比如for ($x=0; $x &#60; count($array); $x)每循环一次都会调用count()函数。
20.在方法中递增局部变量，速度是最快的。几乎与在函数中调用局部变量的速度相当。
21.递增一个全局变量要比递增一个局部变量慢2倍。
22.递增一个对象属性（如：$this-&#62;prop++）要比递增一个局部变量慢3倍。
23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。
24.仅定义一个局部变量而没在函数中调用它，同样会减慢速度（其程度相当于递增一个局部变量）。PHP大概会检查看是否存在全局变量。
25.方法调用看来与类中定义的方法的数量无关，因为我（在测试方法之前和之后都）添加了10个方法，但性能上没有变化。
26.派生类中的方法运行起来要快于在基类中定义的同样的方法。
27.调用带有一个参数的空函数，其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。
28.用单引号代替双引号来包含字符串，这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量，单引号则不会。当然，只有当你不需要在字符串中包含变量时才可以这么做。
29.输出多个字符串时，用逗号代替句点来分隔字符串，速度更快。注意：只有echo能这么做，它是一种可以把多个字符串当作参数的“函数”（译注：PHP手册中说echo是语言结构，不是真正的函数，故把函数加上了双引号）。
30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面，少用脚本。
31.除非脚本可以缓存，否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能，以免除编译开销。
32.尽量做缓存，可使用memcached。memcached是一款高性能的内存对象缓存系统，可用来加速动态Web应用程序，减轻数据库负载。对运算码 (OP code)的缓存很有用，使得脚本不必为每个请求做重新编译。
33. 当操作字符串并需要检验其长度是否满足某种要求时，你想当然地会使用strlen()函数。此函数执行起来相当快，因为它不做任何计算，只返回在zval 结构（C的内置数据结构，用于存储PHP变量）中存储的已知字符串长度。但是，由于strlen()是函数，多多少少会有些慢，因为函数调用会经过诸多步骤，如字母小写化（译注：指函数名小写化，PHP不区分函数名大小写）、哈希查找，会跟随被调用的函数一起执行。在某些情况下，你可以使用isset() 技巧加速执行你的代码。
（举例如下）
if (strlen($foo) &#60; 5) { echo &#8220;Foo is too short&#8221;; }
（与下面的技巧做比较）
if (!isset($foo{5})) { echo &#8220;Foo is too short&#8221;; }
调用isset()恰巧比strlen()快，因为与后者不同的是，isset()作为一种语言结构，意味着它的执行不需要函数查找和字母小写化。也就是说，实际上在检验字符串长度的顶层代码中你没有花太多开销。
34. 当执行变量$i的递增或递减时，$i++会比++$i慢一些。这种差异是PHP特有的，并不适用于其他语言，所以请不要修改你的C或Java代码并指望它们能立即变快，没用的。++$i更快是因为它只需要3条指令(opcodes)，$i++则需要4条指令。后置递增实际上会产生一个临时变量，这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种，正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意，因为并不是所有的指令优化器都会做同样的优化处理，并且存在大量没有装配指令优化器的互联网服务提供商（ISPs）和服务器。
35.并不是事必面向对象(OOP)，面向对象往往开销很大，每个方法和对象调用都会消耗很多内存。
36.并非要用类实现所有的数据结构，数组也很有用。
37.不要把方法细分得过多，仔细想想你真正打算重用的是哪些代码？
38.当你需要时，你总能把代码分解成方法。
39.尽量采用大量的PHP内置函数。
40.如果在代码中存在大量耗时的函数，你可以考虑用C扩展的方式实现它们。
41.评估检验(profile)你的代码。检验器会告诉你，代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序，评估检验总体上可以显示出代码的瓶颈。
42.mod_zip可作为Apache模块，用来即时压缩你的数据，并可让数据传输量降低80%。
43.另一篇优化PHP的精彩文章，由John Lim撰写。
]]></description>
			<content:encoded><![CDATA[<p>转载自<a href="http://www.yeeyan.com/" title="译言翻译" target="_blank">http://www.yeeyan.com/</a><br />
原作者: Reinhold Weber <a href="http://reinholdweber.com/?p=3" target="_blank">原文</a>  译者: <a href="http://www.yeeyan.com/space/show/davidkoree" target="_blank">davidkoree</a></p>
<p>1.如果一个方法可静态化，就对它做静态声明。速率可提升至4倍。</p>
<p>2.echo 比 print 快。</p>
<p>3.使用echo的多重参数（译注：指用逗号而不是句点）代替字符串连接。</p>
<p>4.在执行for循环之前确定最大循环数，不要每循环一次都计算最大值。</p>
<p>5.注销那些不用的变量尤其是大数组，以便释放内存。</p>
<p>6.尽量避免使用__get，__set，__autoload。</p>
<p>7.require_once()代价昂贵。</p>
<p>8.在包含文件时使用完整路径，解析操作系统路径所需的时间会更少。</p>
<p>9.如果你想知道脚本开始执行（译注：即服务器端收到客户端请求）的时刻，使用$_SERVER[‘REQUEST_TIME’]要好于time()。</p>
<p>10.函数代替正则表达式完成相同功能。</p>
<p>11.str_replace函数比preg_replace函数快，但strtr函数的效率是str_replace函数的四倍。</p>
<p>12.如果一个字符串替换函数，可接受数组或字符作为参数，并且参数长度不太长，那么可以考虑额外写一段替换代码，使得每次传递参数是一个字符，而不是只写一行代码接受数组作为查询和替换的参数。</p>
<p>13.使用选择分支语句（译注：即switch case）好于使用多个if，else if语句。</p>
<p>14.用@屏蔽错误消息的做法非常低效。</p>
<p>15.打开apache的mod_deflate模块。</p>
<p>16.数据库连接当使用完毕时应关掉。</p>
<p>17.$row[‘id’]的效率是$row[id]的7倍。</p>
<p>18.错误消息代价昂贵。</p>
<p>19.尽量不要在for循环中使用函数，比如for ($x=0; $x &lt; count($array); $x)每循环一次都会调用count()函数。</p>
<p>20.在方法中递增局部变量，速度是最快的。几乎与在函数中调用局部变量的速度相当。</p>
<p>21.递增一个全局变量要比递增一个局部变量慢2倍。</p>
<p>22.递增一个对象属性（如：$this-&gt;prop++）要比递增一个局部变量慢3倍。</p>
<p>23.递增一个未预定义的局部变量要比递增一个预定义的局部变量慢9至10倍。</p>
<p>24.仅定义一个局部变量而没在函数中调用它，同样会减慢速度（其程度相当于递增一个局部变量）。PHP大概会检查看是否存在全局变量。</p>
<p>25.方法调用看来与类中定义的方法的数量无关，因为我（在测试方法之前和之后都）添加了10个方法，但性能上没有变化。</p>
<p>26.派生类中的方法运行起来要快于在基类中定义的同样的方法。</p>
<p>27.调用带有一个参数的空函数，其花费的时间相当于执行7至8次的局部变量递增操作。类似的方法调用所花费的时间接近于15次的局部变量递增操作。</p>
<p>28.用单引号代替双引号来包含字符串，这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量，单引号则不会。当然，只有当你不需要在字符串中包含变量时才可以这么做。</p>
<p>29.输出多个字符串时，用逗号代替句点来分隔字符串，速度更快。注意：只有echo能这么做，它是一种可以把多个字符串当作参数的“函数”（译注：PHP手册中说echo是语言结构，不是真正的函数，故把函数加上了双引号）。</p>
<p>30.Apache解析一个PHP脚本的时间要比解析一个静态HTML页面慢2至10倍。尽量多用静态HTML页面，少用脚本。</p>
<p>31.除非脚本可以缓存，否则每次调用时都会重新编译一次。引入一套PHP缓存机制通常可以提升25%至100%的性能，以免除编译开销。</p>
<p>32.尽量做缓存，可使用memcached。memcached是一款高性能的内存对象缓存系统，可用来加速动态Web应用程序，减轻数据库负载。对运算码 (OP code)的缓存很有用，使得脚本不必为每个请求做重新编译。</p>
<p>33. 当操作字符串并需要检验其长度是否满足某种要求时，你想当然地会使用strlen()函数。此函数执行起来相当快，因为它不做任何计算，只返回在zval 结构（C的内置数据结构，用于存储PHP变量）中存储的已知字符串长度。但是，由于strlen()是函数，多多少少会有些慢，因为函数调用会经过诸多步骤，如字母小写化（译注：指函数名小写化，PHP不区分函数名大小写）、哈希查找，会跟随被调用的函数一起执行。在某些情况下，你可以使用isset() 技巧加速执行你的代码。</p>
<p>（举例如下）<br />
if (strlen($foo) &lt; 5) { echo &#8220;Foo is too short&#8221;; }<br />
（与下面的技巧做比较）<br />
if (!isset($foo{5})) { echo &#8220;Foo is too short&#8221;; }</p>
<p>调用isset()恰巧比strlen()快，因为与后者不同的是，isset()作为一种语言结构，意味着它的执行不需要函数查找和字母小写化。也就是说，实际上在检验字符串长度的顶层代码中你没有花太多开销。</p>
<p>34. 当执行变量$i的递增或递减时，$i++会比++$i慢一些。这种差异是PHP特有的，并不适用于其他语言，所以请不要修改你的C或Java代码并指望它们能立即变快，没用的。++$i更快是因为它只需要3条指令(opcodes)，$i++则需要4条指令。后置递增实际上会产生一个临时变量，这个临时变量随后被递增。而前置递增直接在原值上递增。这是最优化处理的一种，正如Zend的PHP优化器所作的那样。牢记这个优化处理不失为一个好主意，因为并不是所有的指令优化器都会做同样的优化处理，并且存在大量没有装配指令优化器的互联网服务提供商（ISPs）和服务器。</p>
<p>35.并不是事必面向对象(OOP)，面向对象往往开销很大，每个方法和对象调用都会消耗很多内存。</p>
<p>36.并非要用类实现所有的数据结构，数组也很有用。</p>
<p>37.不要把方法细分得过多，仔细想想你真正打算重用的是哪些代码？</p>
<p>38.当你需要时，你总能把代码分解成方法。</p>
<p>39.尽量采用大量的PHP内置函数。</p>
<p>40.如果在代码中存在大量耗时的函数，你可以考虑用C扩展的方式实现它们。</p>
<p>41.评估检验(profile)你的代码。检验器会告诉你，代码的哪些部分消耗了多少时间。Xdebug调试器包含了检验程序，评估检验总体上可以显示出代码的瓶颈。</p>
<p>42.mod_zip可作为Apache模块，用来即时压缩你的数据，并可让数据传输量降低80%。</p>
<p>43.<a href="http://phplens.com/lens/php-book/optimizing-debugging-php.php" target="_blank">另一篇</a>优化PHP的精彩文章，由John Lim撰写。</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/158.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP5跨服务器使用session时保存方式的变化</title>
		<link>http://kevin.9511.net/archives/147.html</link>
		<comments>http://kevin.9511.net/archives/147.html#comments</comments>
		<pubDate>Mon, 10 Sep 2007 18:40:18 +0000</pubDate>
		<dc:creator>kevin</dc:creator>
				<category><![CDATA[技术备案]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[session]]></category>

		<guid isPermaLink="false">http://kevin.9511.net/archives/147.html</guid>
		<description><![CDATA[因为公司的一个小项目，需要在跨服务器环境下使用session。默认配置，session是以文件形式保存在服务器端，所以无法跨服务器使用。当然，PHP也提供了跨服务器的解决方案：session_set_save_handler()。考虑到效率，决定不使用通常将session存在数据库中的方法，改用memcache来保存session。
在PHP手册中，关于session_set_save_handler()有一个警告
 As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. The object destructors can however use sessions.It is possible to call session_write_close() from the destructor to solve this chicken and egg problem.
意思是而从PHP5.0.5开始，write和close处理函数的调用，是在所有对象被destruct之后的，这样就无法在这两个方法中使用对象和错误捕获了。从php5.0.5开始，在定制session保存方式时，就必须得用到session_write_close()了。
简单写了个使用memcache保存session数据的类，改成其他方式保存也是很简单的事。不过如果存在数据库中，是需要对数据进行一些处理的。memSession.rar
在这里顺便提一下PHP.net网站上的手册。跟下载到本地的chm不同，网站的手册，每个函数说明页面的下面，基本都有一大堆的note。这些note，都是大家在使用这个函数时遇到问题后的解决方法，或者是更深一层应用的扩展。其中的亮点很多，有时候都晃眼。比如在这个session_set_save_handler函数下面的notes中，就有使用NFS，Mysql，LDAP等保存session的代码。在php.net上查手册，有时候看notes比看函数说明更能让人明白函数的用法。所以，玩PHP，对于自己陌生的函数，只要能上网，严重推荐上php.net查手册。
行了，广告做完，洗洗睡了。
]]></description>
			<content:encoded><![CDATA[<p>因为公司的一个小项目，需要在跨服务器环境下使用session。默认配置，session是以文件形式保存在服务器端，所以无法跨服务器使用。当然，PHP也提供了跨服务器的解决方案：<a href="http://cn.php.net/manual/en/function.session-set-save-handler.php" target="_blank">session_set_save_handler()</a>。考虑到效率，决定不使用通常将session存在数据库中的方法，改用<a href="http://blog.sitepart.net/19" target="_blank">memcache</a>来保存session。</p>
<p>在PHP手册中，关于session_set_save_handler()有一个警告</p>
<blockquote><p><font color="#ff6600"> As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. The object destructors can however use sessions.It is possible to call session_write_close() from the destructor to solve this chicken and egg problem.</font></p></blockquote>
<p>意思是而从PHP5.0.5开始，write和close处理函数的调用，是在所有对象被destruct之后的，这样就无法在这两个方法中使用对象和错误捕获了。从php5.0.5开始，在定制session保存方式时，就必须得用到session_write_close()了。</p>
<p>简单写了个使用memcache保存session数据的类，改成其他方式保存也是很简单的事。不过如果存在数据库中，是需要对数据进行一些处理的。<a href="/wp-content/uploads/2007/09/memSession.rar">memSession.rar</a></p>
<p>在这里顺便提一下PHP.net网站上的手册。跟下载到本地的chm不同，网站的手册，每个函数说明页面的下面，基本都有一大堆的note。这些note，都是大家在使用这个函数时遇到问题后的解决方法，或者是更深一层应用的扩展。其中的亮点很多，有时候都晃眼。比如在这个session_set_save_handler函数下面的notes中，就有使用NFS，Mysql，LDAP等保存session的代码。在php.net上查手册，有时候看notes比看函数说明更能让人明白函数的用法。所以，玩PHP，对于自己陌生的函数，只要能上网，严重推荐上<a href="http://www.php.net/manual/en/" target="_blank">php.net</a>查手册。</p>
<p>行了，广告做完，洗洗睡了。</p>
]]></content:encoded>
			<wfw:commentRss>http://kevin.9511.net/archives/147.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

