利用SVN更新网站

如果你有一个假设在公网上的SVN服务器,而你的网站所在的主机允许你使用SVN客户端,并且开放了php的exec函数,那么你有福了,你可以利用SVN作为中转,更新你的网站程序。

首先,也是前提,就是你的网站程序是用SVN管理的,那么只要你的网站主机能够访问SVN,就能够使用SVN的update功能来更新程序。

准备工作一:将网站程序加上svn的控制标记,由于SVN的控制信息都存在程序所在目录的.svn子目录中,所以需要找一个空目录,并且将网站现有程序checkout到这个目录里面来,注意是checkout而不是export,因为接下来要将最新的网站程序连同他里面包含的很多个.svn目录一同上传到服务器上去。为了不让.svn目录泄露机密,要在.htaccess文件或者是httpd.conf中设定如下规则,禁止对.svn目录的访问。

	<directory ~ "\.svn">
		Order Allow,Deny
		Deny from all
	</directory>

准备工作二:作一段小程序,调用服务器上的svn命令行命令,update网站程序,下面是一个写好了的简单例子。

	//setup update target path
	$target_ar['fwolf'] = 'd:\fwolf';
 
	//setup commandline
	$svn_cmd1 = 'd:\server\svn\bin\svn.exe update ';
	$svn_cmd2 = ' --username updatebot --password xxxxxx --no-auth-cache';
 
	//output html string
	$html = '';	
 
	//recieve get parameter
	$target = isset($_GET['target']) ? $_GET['target'] : '';
	if (empty($target) || !isset($target_ar[$target]))
	{
		$html = 'Target does not correct.';
	}
	else
	{
		//execute svn update command
		$cmd = $svn_cmd1 . $target_ar[$target] . $svn_cmd2;
		$ar = array();
		$status = 0;
		exec($cmd, $ar, $status);
		for ($i=0; $i < count($ar); $i++)
			$ar[$i] = htmlspecialchars($ar[$i]);
		$html .= 'Status: ' . $status . "<br />\r\n";
		$html .= implode('<br />' . "\r\n", $ar);
	}
	echo $html;

把这个程序放到服务器上能够访问到的地方,也可以在此基础上加上一些访问限制,那么只要访问这个程序/页面,服务器就会自动更新你的网站啦。

	Status: 0
	D H:\cvswork\svntest\update_from_svn.php
	Updated to revision 44.

这样,在利用SVN很好的管理网站程序的基础上,还实现了服务器程序的很方便的更新,一举两得!尤其是在程序上传不是十分方便的场合,用起来就更舒服了,我就是在更换了一个劣质防火墙,ftp无法正常使用的情况下想出这个怪招儿的:-)。

Update @ 2007-07-31

如果在windows主机上使用本方法,而svn服务器是采用了ssl的https://…地址,那么会遇到一点小麻烦,就是在执行svn update的时候,由于使用的是web的用户,在出现确认证书的提示信息时,用户是无法输入的:

Error validating server certificate for 'https://20070731.fwolf.com':
 - The certificate is not issued by a trusted authority. Use the
   fingerprint to validate the certificate manually!
Certificate information:
 - Hostname: 20070731.fwolf.com
 - Valid: from Jul 31 06:49:53 2007 GMT until Jul 28 06:49:53 2017 GMT
 - Issuer: Fwolf, US
 - Fingerprint: 38:43:0b:29:75:1t:ba:d8:29:8f:94:9a:10:42:a0:fe:ae:93:4d:91
(R)eject, accept (t)emporarily or accept (p)ermanently?

这时就只能用变通的方法了,首先在dos方式中使用svn up,svn会自动缓存身份验证以及ssl确认信息,这些信息保存在C:\Documents and Settings\Administrator\Application Data\Subversion目录下,然后把这个目录整体拷贝到C:\Documents and Settings\Default User\Application Data\Subversion就可以了,测试环境windows2003,并且试过复制到All Users的对应目录无效。

另外修改配置文件servers,添加ssl-trust-default-ca = yes的方式在windows下好像没有作用。

Update @ 2009-04-07

Git(ssh证书登录)也可以这样用,略有不同,我使用的客户端是msysgit

  • Admin用户使用桌面操作(Git Bash)时,.ssh目录位于C:\Documents and Settings\Administrator\下。
  • 直接使用C:\Program Files\Git\bin\ssh.exe当ssh客户端时,.ssh目录要放到C:\Program Files\Git\下,并且似乎忽略.ssh/config文件,私钥文件只认identity id_rsa id_dsa三个。
  • 系统服务比如Apache运行时,使用上面一条的设置,很是诡异。

说公钥文件只认固定的三个,是从这里猜到的:

	Program Files/Git$ grep identity share -R
	share/git-gui/lib/sshkey.tcl:   foreach name {~/.ssh/id_dsa.pub ~/.ssh/id_rsa.pub ~/.ssh/identity.pub} {

好像是写死了,并且我用config定义其他私钥它也不认。第一条中使用Git的时候没事,很正常。

同时,为了安全起见,apache里还要增加如下设置:

	<Directory ~ "\.(git|svn)">
		Order allow,deny
		Deny from all
		Satisfy All
	</Directory>

更改 WordPress 自动生成摘要的方式

WordPress 在搜索或列 Archives(按时间、按分类)的时候,在列表中是显示帖子摘要的。原来我觉得这样不好,就把列表中显示摘要改成了在列表中显示全部帖子,使用一段时间以后发现很不好。

首先列表会变得很臃肿,失去了列表的本身作用——方便用户寻找真正想要看的帖子,其次,在搜索引擎抓取页面的时候,把那些列表页面也抓了过去,但随着帖子的不断增多,列表的更新远快于搜索引擎缓存的更新,用户使用搜索引擎进来以后,在列表中就很难找到目标了。

这样在列表中只显示摘要的优势就体现出来了,首先页面很清爽,用户可以清楚的找到要查看的目标,然后搜索引擎抓取内容的时候,会更多的关注页面的 Permalink,用户也就会通过搜索直达目标帖子,方便了用户。

打开 WordPress 的wp-includes\functions-formatting.php,找到其中的 function wp_trim_excerpt(about line 741),将如下代码

		$excerpt_length = 55;
		$words = explode(' ', $text, $excerpt_length + 1);
		if (count($words) > $excerpt_length) {
			array_pop($words);
			array_push($words, '[...]');
			$text = implode(' ', $words);
		}

更改为

		$excerpt_length = 3;
		$words = explode("\n", $text, $excerpt_length + 1);
		if (count($words) > $excerpt_length) {
			array_pop($words);
			array_push($words, '<p />......<a href="' . get_permalink($post->ID) . '">[阅读全文]</a>');
			$text = implode("\n", $words);
		}

就可以了,WordPress 默认的生成摘要是用空格来判断的,就是取到55个空格结束,这适用于西方采用空格作为词间隔的语言,但中文是不分词的,所以我使用读取3行的方式,取前3行,对哪种语言都是适用的。

Update @ 2007-02-09

升级到 WordPress 2.1以后,这个修改的地点变为wp-includes/formatting.php,第780行左右。

Update @ 2007-02-26

编写了一个插件,不用再手工修改代码了。

Update @ 2009-08-25

Betty全面总结了几种中文摘要方式,形成了一个综合的适合中文的摘要插件,并且提交到了WordPress 官网,带有简单的配置后台,很不错。

搞定WordPress的Permalinks

WordPress的Permalinks还是比较好用的,只需要在Options->Permalinks里设置一个/post/%post_id%,基本就可以了,但它的Permalinks样式偶不喜欢,偶喜欢的样式是:

单篇文章

  • domain.tld/post/post_id

存档

  • domain.tld/archive/year
  • domain.tld/archive/year/month
  • domain.tld/archive/year/month/day (这个其实根本用不着)

分类

  • domain.tld/category/category_name

分页

  • domain.tld/page/page_number
  • domain.tld/archive/year/month/page/page_number
  • domain.tld/category/category_name/page/pagenumber

作者 其实也没啥用

  • domain.tld/author/author_name

feeds

  • domain.tld/feed
  • domain.tld/feed/rss

Permalink的样式固定以后,即使以后再更换其它的Blog系统,也按照这个样式来设定,加上把数据也导过去,基本上能够保证用户使用以前的链接也能正常访问新系统的内容。

WordPress生成Permalink的程序主要在wp-includes\classes.php里,有一个WP_Rewrite类。

如果要修改存档的Permalink,只要找到function get_date_permastruct()部分,在靠后的位置有一句

$this->date_structure = $front . $date_endian;

在它前面加上一句

$front = '/archive/';

就可以了,其余的也类似:

$this->front = '/author/';
$this->author_structure = $this->front . $this->author_base . '/%author%';
$this->category_structure .= '%category%';
//下面这一句是增加的
$this->category_structure = '/category/%category%';

然后再修改.htaccess文件,修改相应的规则就可以了,由于只是简单的替换了一下前面的固定单词,所以很好修改的。如果没有.htaccess文件,在Options里设置一下Permalinks就会自动生成了。