2007年8月28日星期二

游戏里没有什么?

现在的游戏作的真好,几乎什么样的都有,几乎适合任何年纪的都有,但是,游戏和现实还是有不少的差距,那么,有哪些东西是在游戏中没有的呢?

生老病死,酸甜苦辣

没错,游戏中的生,就是你注册了个新账号,一贫如洗,赤手空拳;随着游戏时间的增加,年龄也会增长,甚至会变老、老死;也会中毒或生病,不过有药水或者疗伤大夫、术士;死亡,在游戏中可以是永久的,也可能只是损失一些 金钱或者经验。但是,在游戏中你能体会到自己在父母怀中咿哑学语的滋味么?能体验到老得只能喝粥的滋味了?能体会到糖尿病脑血栓的病痛么?死亡了,就无法开始新游戏或者注册新人物,有这样的游戏么?在游戏中你可以一天之内经历人一生之中会遇到的事情,但却无法感受需要你一生来经历的真实。

发明创造的乐趣

以前的游戏如轩辕剑可以炼妖,现在的游戏很多也可以合成装备,但这些不叫发明创造,充其量只是"发现"了游戏中的某个功能而已,所以不用沾沾自喜,当你成为全世界第一个合成某套装备的人的时候,殊不知这些功能早就是程序员测试过千百遍的了,都是在游戏策划方案中讨论过N次的。真正的发明创造是从无到有的,而不是一直藏在什么地方等着你挖出来而已。现在的科技,恐怕还无法在游戏中模拟真正的发明创造,否则大家不用建研究院了,都去打游戏得了。

人生的无奈,无法回头的选择,错误的代价

英文的game翻译成中文叫游戏,没有用读音直译,而是直接选用了中文中含义最接近的词语,真的是太合适了。小孩子也作"游戏"过家家,大人们也会玩"杀人游戏",游戏的本质就是虚拟,虚拟就是虚假,既然是虚假就可以从头来过,所以在游戏中你可以载入,也可以复活再去杀那把你干掉的怪物,但在人生中,有太多无奈的事情了,比如近视眼在无法手术治疗之前只能一辈子戴眼镜(已经比眼镜出现之前年代的人好多了),你也无法选择你的父母,在你作错任何事的一刹那,时间已经流逝,错误已成历史,你想重新注册一个不近视的"用户",想重新投胎到另外一片大陆,想载入进度回到错误之前,都是不可能的。

法律的制裁

说游戏中没有法律也许并不完全,游戏中不仅有规则、gm,也有会执法的npc,甚至会有玩家公会的公约,但是,我所知道的游戏中的最重的处罚恐怕就是杀档了,但恐怕没有任何一家公司会规定,因某某某玩家违反规则,终生禁止玩我的游戏吧?游戏中也有关禁闭,但同样那时间对于人生来说简直太小菜了,在现实的监狱中让青春失去简直是莫大的痛苦,而游戏中的监牢不仅时间短很多,而且玩家还可以聊天喝茶,甚至开着电脑上街买菜去。法律制裁的苍白化直接导致了"犯罪"的滋生,所以也不怪打斗类的游戏仍然占大多数,但如果养成习惯,分不清现实与虚拟,将会是灾难性的后果。

无法简化的细节

很早以前我就想过,自己玩过那么多的游戏,怎么就没有一款游戏中的主人公会去上厕所呢?游戏中虽然也有白天黑夜,但不用睡觉的人比比皆是,饿了也就是用鼠标抓起事物往嘴里一放了事。也难怪,如果游戏中还要洗衣服做饭,和现实一样了,谁还会去玩啊,可在生活中,你能避开这些琐事么?在游戏中你可以干掉敌人一艘飞船,得到NNNN金,在现实中你要捡半天垃圾,运到垃圾场,再写个报告,让上级确认你的功绩,太麻烦了,要真是有那么个"系统"来自动计算,好像也蛮好的啊,可这就属于异想天开了。。。对了,老掉牙的毁灭公爵duke3d里能上厕所小便,还加10点血呢:)。

如果在游戏中,你身处撒哈拉大沙漠中央,没有任何补给和援助,没招了吧,可这是你仍然能够关掉电脑,泡杯茶休息一会儿。而如果在现实中你出在这样的环境里,给你两个选择:1、游戏中,一桌大餐等着你;2、现实中,一壶清水。你会选择哪个呢?

游戏虽好,可真的不要贪玩哦~~

Source: http://www.fwolf.com/blog/post/351

旋转屏幕方向(失败)

我也想把显示器旋转成竖着的,也就是把分辨率1280×1024变成了1024×1280,Dell 1907FP转动屏幕很方便,但是ubuntu的显示却转不过来,我总不能歪着脑袋看吧。记得用windows xp tablepc版的时候,有内置的屏幕旋转功能,nvidia显卡设置工具也能实现,但在linux下我用的fglrx驱动,如何实现?

google一下,发现无外乎两种解决方式,一种是固定的,要修改xorg.conf,在Device段增加一句Option "Rotate" "CW",其中CW是顺时针90度,也可以是UD顺时针180度或CCW顺时针270度,还有一说是增加一句Option "RandRRotation" "true" ;另外一种是用xrandr命令来转,比如xrandr -o left

不过,很沮丧的结果,上述方法我试验都不成功,显卡为ATI Radeon X600。一下是搜到的一些结果:

Source: http://www.fwolf.com/blog/post/350

2007年8月10日星期五

mod_fcgid出现500错误的解决

MT上的php5是用mod_fcgid方式运行的,但运行一段时间之后,有时候会莫名其妙的出现500错误,也看不出是哪个php程序错误,不过html文件倒能正常解析,查看用户的 $HOME/statistics/logs/error_log文件,会发现大量这样的内容:
[Fri Aug 10 01:00:43 2007] [error] [client 202.108.23.76] Premature end of scrip
t headers: index.php
[Fri Aug 10 01:01:20 2007] [error] [client 60.191.82.228] Premature end of scrip
t headers: index.php

而在系统的log文件/var/log/apache/error_log中,是这样的错误:

[Fri Aug 10 01:03:05 2007] [notice] mod_fcgid: process /var/www/vhosts/fwolf.com
/httpdocs/blog/index.php(21666) exit(communication error), terminated by calling
exit(), return code: 120

G到一些资料,第一类错误是脚本执行被中断,没有返回完整的http header;第二类错误是cgi程序的执行被强行中止。根本原因是fastcgi会自动kill掉一些发呆的、长时间没有响应的进程(要不它比较快,比较省内存啊),但是fastcgi的默认idle时间设置过于苛刻( 官方文档中每个选项都有默认的时间值),所以有些处理比较慢、需要调用外部资源的程序就有可能被误杀,所以先略微调整一下,继续观察:

     IdleTimeout 600     ProcessLifeTime 3600     MaxProcessCount 100     DefaultMinClassProcessCount 3     DefaultMaxClassProcessCount 20     IPCConnectTimeout 30     IPCCommTimeout 600     MaxRequestsPerProcess 500  
  • IdleTimeout 发呆时限
  • ProcessLifeTime 一个进程的最长生命周期,过期之后无条件kill
  • MaxProcessCount 最大进程个数
  • DefaultMinClassProcessCount 每个程序启动的最小进程个数
  • DefaultMaxClassProcessCount 每个程序启动的最大进程个数
  • IPCConnectTimeout 程序响应超时时间
  • IPCCommTimeout 与程序通讯的最长时间,上面的错误有可能就是这个值设置过小造成的
  • MaxRequestsPerProcess 每个进程最多完成处理个数,达成后自杀,因为PHP最多只处理500次请求。不过这个是mod_fcgid 1.11版本添加的,我们主机上暂时不支持。

上述选项的确切作用我也不是十分清楚,先用着这个设置,再根据情况调整。

参考:

Source: http://www.fwolf.com/blog/post/349

[MT]主机上安装svn客户端

有了svn,就可以方便的获取一些程序的源码了,所以我要在MT主机上安装,注意只是客户端,并非架设svn服务器。

svn目前的最新版是1.4.4,我参考shunz的Apache+Subversion安装笔记,从 http://www.axint.net/apache/apr/binaries/rpm/i386/下载了apr-1.2.8-1.i386.rpmapr-util-1.2.8-1.i386.rpm(新版svn需要apr版本0.9.7以上,而且是必需),可是rpm -U apr*.rpm的时候系统却提示依赖性错误:

warning: apr-1.2.8-1.i386.rpm: V3 DSA signature: NOKEY, key ID 751d7f27
error: Failed dependencies:
libpq.so.3 is needed by apr-util-1.2.8-1.i386
libapr-0.so.0 is needed by (installed) httpd-2.0.52-32.3.ent.centos4.i386
libapr-0.so.0 is needed by (installed) mod_perl-1.99_16-4.5.i386
libapr-0.so.0 is needed by (installed) subversion-1.1.4-2.ent.i386
libapr-0.so.0 is needed by (installed) subversion-perl-1.1.4-2.ent.i386
apr = 0.9.4-24.5.c4.2 is needed by (installed) apr-devel-0.9.4-24.5.c4.2.i386
libaprutil-0.so.0 is needed by (installed) httpd-2.0.52-32.3.ent.centos4.i386
libaprutil-0.so.0 is needed by (installed) mod_perl-1.99_16-4.5.i386
libaprutil-0.so.0 is needed by (installed) subversion-1.1.4-2.ent.i386
libaprutil-0.so.0 is needed by (installed) subversion-perl-1.1.4-2.ent.i386
apr-util = 0.9.4-21 is needed by (installed) apr-util-devel-0.9.4-21.i386

(rpm和redhat系列不熟悉)看了半天才搞懂,rpm -U是升级,而系统中的现有apr 0.9.4版本被其他软件比如apache、mod_perl等依赖,升级过去可能就破坏依赖性关系了。如果rpm -i的话应该是安装新版本,不知道centos上不同的软件版本能否共存,考虑到合租服务器的稳定性,还是决定按照MT客服的建议,安装svn的旧版本1.3.2:

wget http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz  gunzip subversion-1.3.2.tar.gz tar -xvf subversion-1.3.2.tar cd subversion-1.3.2 ./configure && make && make install 

顺利完成,也可以下载其他形式的源码包,然后再配置svn到用户的chroot环境当中,大家就都能用了。

配置svn到chroot环境的时候需要的包很多,ldd就行,另外如果想checkout https形式的仓库,还要配置/dev下的随机数生成器:

# mknod /var/www/vhosts/chroot/dev/urandom c 1 9

不然会出错:

SSL negotiation failed: SSL disabled due to lack of entropy

基本可用了,不过checkout含有中文名称文件的仓库时,又会遇到如下错误:

svn: Can't recode string

基本可以确定是svn无法转换字符集的原因(参考),再进一步查找原因,发现竟然是centos的系统默认字符集不是utf8的,于是更改 /etc/sysconfig/i18n,设定为如下内容:

LANG="en_US.UTF-8"
SUPPORTED="en_US.UTF-8:en_US:en"
SYSFONT="latarcyrheb-sun16"
#LANG="C"

重启服务器,root用户可以使用中文了,普通用户还不行,需要把/usr/lib/locale/en_US.utf8/配置到chroot环境中去,然后在普通用户的$HOME目录下的.bashrc或者.bash_profile文件中加入一句export LANG=en_US.UTF-8,重新登录后就可以啦,UTF8万岁!

仍然剩余一个诡异的问题,root用户无法使用https形式的仓库:

svn: SSL is not supported

注意普通用户是可以使用的,怎么回事?用whereis发现服务器上有两个svn文件:

# whereis svn
svn: /usr/bin/svn /usr/local/bin/svn /usr/share/man/man1/svn.1.gz

分别查看其版本:

# /usr/bin/svn --version
svn, version 1.1.4 (r13838)
compiled Aug 21 2005, 20:56:55
...
* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
- handles 'http' schema
- handles 'https' schema

# /usr/local/bin/svn --version
svn, version 1.3.2 (r19776)
compiled Aug 9 2007, 16:51:43
...
* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
- handles 'http' scheme

合着我编译了半天都是徒劳啊,服务器上早就有了svn了,我明明记得是没有啊,难道是客服在装编译套件developer's tools package时给装上了?可看了那个包列表里也没有啊?依然诡异,忙活半天还少编译了个SSL选项进来。

也许是MT客服给装编译套件的时候,为了自己用着方便,顺手放过来一个svn?谁还有新租的DV 3.0主机麻烦确认一下好了。

参考(部分是安装svn服务器的):

关于svn字符集错误以及centos字符集问题的参考:

带SSL编译svn的一些资料:

Source: http://www.fwolf.com/blog/post/348

2007年8月9日星期四

在Ubuntu上加装Trac

原本机器上就架着svn服务器,但以前是从windows平台下转过来的,所以配套的轻型项目管理工具一直是在用 Mantis,相比之下,trac和svn的结合程度更高一些,所以装一个试用一下。

相关软件版本:Ubuntu 7.04, Apache 2.2.3, Python 2.5.1, Trac 0.10.4。

安装trac,创建仓库

安装trac

首先通过apt安装trac,由于trac需要python的一些包,所以根据本机python环境的不同,可能还需要安装一些附加的包,我的机器上是自动安装了如下软件包:

python-clearsilver python-setuptools python-subversion trac

默认的,trac的程序文件是安装在/usr/share/trac目录下,包括很多默认的样式、模板也都在这个目录下。

创建env目录

trac需要创建env目录,用于存储trac生成的页面、配置文件等,也就是存储"内容"的地方,把程序和程序生成的数据文件分开是个好习惯。在trac中,这个目录被称为environment

A Trac environment is the backend storage where Trac stores information like wiki pages,
tickets, reports, settings, etc. An environment is basically a directory that contains a
human-readable configuration file and various other files and directories.

我创建的是/big2/trac/svntest的目录,对应svn里面的svntest仓库:

$ trac-admin /big2/trac/svntest initenv
Creating a new Trac environment at /big2/trac/svntest

Trac will first ask a few questions about your environment
in order to initalize and prepare the project database.

Please enter the name of your project.
This name will be used in page titles and descriptions.

Project Name [My Project]> SvnTest

Please specify the connection string for the database to use.
By default, a local SQLite database is created in the environment
directory. It is also possible to use an already existing
PostgreSQL database (check the Trac documentation for the exact
connection string syntax).

Database connection string [sqlite:db/trac.db]>

Please specify the type of version control system,
By default, it will be svn.

If you don't want to use Trac with version control integration,
choose the default here and don't specify a repository directory.
in the next question.

Repository type [svn]>

Please specify the absolute path to the version control
repository, or leave it blank to use Trac without a repository.
You can also set the repository location later.

Path to repository [/path/to/repos]> https://somewhere.fwolf.com/svn/svntest Please enter location of Trac page templates. Default is the location of the site-wide templates installed with Trac. Templates directory [/usr/share/trac/templates]> Creating and Initializing Project Installing default wiki pages /usr/share/trac/wiki-default/RecentChanges => RecentChanges
/usr/share/trac/wiki-default/CamelCase => CamelCase
/usr/share/trac/wiki-default/InterMapTxt => InterMapTxt
/usr/share/trac/wiki-default/InterTrac => InterTrac
/usr/share/trac/wiki-default/InterWiki => InterWiki
/usr/share/trac/wiki-default/TitleIndex => TitleIndex
/usr/share/trac/wiki-default/SandBox => SandBox
/usr/share/trac/wiki-default/TracInterfaceCustomization => TracInterfaceCustomization
/usr/share/trac/wiki-default/TracAccessibility => TracAccessibility
/usr/share/trac/wiki-default/TracAdmin => TracAdmin
/usr/share/trac/wiki-default/TracBackup => TracBackup
/usr/share/trac/wiki-default/TracBrowser => TracBrowser
/usr/share/trac/wiki-default/TracCgi => TracCgi
/usr/share/trac/wiki-default/TracChangeset => TracChangeset
/usr/share/trac/wiki-default/TracEnvironment => TracEnvironment
/usr/share/trac/wiki-default/TracFastCgi => TracFastCgi
/usr/share/trac/wiki-default/TracGuide => TracGuide
/usr/share/trac/wiki-default/TracImport => TracImport
/usr/share/trac/wiki-default/TracIni => TracIni
/usr/share/trac/wiki-default/TracInstall => TracInstall
/usr/share/trac/wiki-default/TracModPython => TracModPython
/usr/share/trac/wiki-default/TracLinks => TracLinks
/usr/share/trac/wiki-default/TracLogging => TracLogging
/usr/share/trac/wiki-default/TracTicketsCustomFields => TracTicketsCustomFields
/usr/share/trac/wiki-default/TracNotification => TracNotification
/usr/share/trac/wiki-default/TracPermissions => TracPermissions
/usr/share/trac/wiki-default/TracPlugins => TracPlugins
/usr/share/trac/wiki-default/TracQuery => TracQuery
/usr/share/trac/wiki-default/TracReports => TracReports
/usr/share/trac/wiki-default/TracRevisionLog => TracRevisionLog
/usr/share/trac/wiki-default/TracRoadmap => TracRoadmap
/usr/share/trac/wiki-default/TracRss => TracRss
/usr/share/trac/wiki-default/TracSearch => TracSearch
/usr/share/trac/wiki-default/TracStandalone => TracStandalone
/usr/share/trac/wiki-default/TracSupport => TracSupport
/usr/share/trac/wiki-default/TracSyntaxColoring => TracSyntaxColoring
/usr/share/trac/wiki-default/TracTickets => TracTickets
/usr/share/trac/wiki-default/WikiRestructuredText => WikiRestructuredText
/usr/share/trac/wiki-default/TracTimeline => TracTimeline
/usr/share/trac/wiki-default/TracUnicode => TracUnicode
/usr/share/trac/wiki-default/TracUpgrade => TracUpgrade
/usr/share/trac/wiki-default/TracWiki => TracWiki
/usr/share/trac/wiki-default/WikiDeletePage => WikiDeletePage
/usr/share/trac/wiki-default/WikiFormatting => WikiFormatting
/usr/share/trac/wiki-default/WikiHtml => WikiHtml
/usr/share/trac/wiki-default/WikiMacros => WikiMacros
/usr/share/trac/wiki-default/WikiNewPage => WikiNewPage
/usr/share/trac/wiki-default/WikiPageNames => WikiPageNames
/usr/share/trac/wiki-default/WikiProcessors => WikiProcessors
/usr/share/trac/wiki-default/WikiRestructuredTextLinks => WikiRestructuredTextLinks
/usr/share/trac/wiki-default/WikiStart => WikiStart

Warning:

You should install the SVN bindings

---------------------------------------------------------------------
Project environment for 'SvnTest' created.

You may now configure the environment by editing the file:

/big2/trac/svntest/conf/trac.ini

If you'd like to take this new project environment for a test drive,
try running the Trac standalone web server `tracd`:

tracd --port 8000 /big2/trac/svntest

Then point your browser to http://localhost:8000/svntest.
There you can also browse the documentation for your installed
version of Trac, including information on further setup (such as
deploying Trac to a real web server).

The latest documentation can also always be found on the project
website:

http://trac.edgewall.org/ Congratulations!

提示信息比较多,真正需要用户输入的就那么几项:

  • Project Name [My Project]> SvnTest 项目名称,帮助辨识而已。
  • Database connection string [sqlite:db/trac.db]> 数据库的连接串,使用的默认值(直接回车即可)。
  • Repository type [svn]> 仓库类型,使用默认值(svn),trac也可以连cvs等其他类型的仓库么?
  • Path to repository [/path/to/repos]> https://somewhere.fwolf.com/svn/svntest 仓库地址, 风轻扬说只能连本机的仓库地址,可我输入的http仓库地址好像也能用。的确是只能用本机的路径,http形式的仓库地址会提示错误:

    TracError: https:/office.fwolf.com/svn/svntest does not appear to be a Subversion repository.

    直接修改配置文件/big2/trac/svntest/conf/trac.ini就可以了,里面的[trac]段,repository_dir设置为本机的svn仓库文件地址,比如/big2/svn/svntest,不用重启服务就生效了。

  • Templates directory [/usr/share/trac/templates]> 模板地址,用默认。

简单运行

至此,trac已经可以运行和访问了,不过类似本机的svn服务器,首先需要手工开启服务:

$ tracd --port 8000 /big2/trac/svntest

然后就能用地址http://localhost:8000/svntest访问了,如果错输为 http://localhost:8000/,它还会提示用户当前有哪些项目可用(Available Projects)并给出链接地址。

把trac配置到apache上

每次都要手工启用trac服务肯定是麻烦的,所以还是像svn那样配置到apache上用着才方便,有几种方式可选:cgi方式和mod_python方式,另外还有fastcgi方式,不过fastcgi我不熟悉,就不介绍了,相关资料可以参考 官方文档Trac with FastCGI

CGI方式

cgi程序设定

虽然cgi方式比其他方法要慢一些,还是介绍一下。首先就是在apache中配置cgi的执行程序,这里我采用比较简单的ScriptAlias方式,也可以吧trac.cgi复制到apache的cgi-bin目录下,或者ln过去(不过cgi-bin目录要开放FollowSymLinks选项才行:

ScriptAlias /trac /usr/share/trac/cgi-bin/trac.cgi

光能执行cgi程序还不够,trac还主要知道一些环境变量才能工作,主要是environment目录的位置,不然会提示错误:

EnvironmentError: The environment options "TRAC_ENV" or "TRAC_ENV_PARENT_DIR" or the mod_python options "TracEnv" or "TracEnvParentDir" are missing. Trac requires one of these options to locate the Trac environment(s). 

根据trac用法的不同,这个环境变量的设置有两种方式,一种是trac只用于一个项目,那么只需要定义一个TRAC_ENV,指定env目录的地址即可;另外一种情况是trac用于多个项目,通常所有的env目录都是在同一个目录之下,所以定义TRAC_ENV_PARENT_DIR,指定env目录的上级目录:

     # Select one of below Env according your usage of trac     # Trac is for single environment     #SetEnv TRAC_ENV "/big2/trac/svntest"     # Trac is for multi environment     SetEnv TRAC_ENV_PARENT_DIR "/big2/trac"  

这里我采用的是多env方式。

运行于apache下是env目录的权限(mod_python方式也适用,不再累述)

注意在cgi或者mod_python方式下,env目录的owner需要设置为web服务器的用户,在ubuntu上一般是www-data,不然会没有访问权限:

svntest: Error
(The user www-data requires read _and_ write permission to the database file /big2/trac/svntest/db/trac.db and the directory it is located in.)

mod_python方式

安装python支持

mod_python方式不仅比cgi方式速度更快,而且可以借助apache的强大功能实现一些tracd(简单运行方式)无法实现的功能,也是我个人比较喜欢的方式。python基本上是所有linux平台下的必备软件,接下来就是要安装apache的python模块libapache2-mod-python,然后在apache的conf文件中装载python模块,在ubuntu或者debian中则有更方便的做法:

a2enmod mod_python

想测试python是否正常支持的话,可以配一个Location测试一下:

     SetHandler mod_python     PythonInterpreter main_interpreter     PythonHandler mod_python.testhandler  

虽然不懂python,但只要能出现正常的信息页(类似phpinfo页)就说明python安装正常了。

配置env目录

和cgi方式类似,也分单项目和多项目的形式,并且多项目也是用环境变量TracEnvParentDir来实现的,注意这个TracEnvParentDir是python的设置(option),和cgi的环境变量TRAC_ENV_PARENT_DIR名称不同。单env目录的的配置如下:

     SetHandler mod_python     PythonInterpreter main_interpreter     PythonHandler trac.web.modpython_frontend     PythonOption TracEnv /big2/trac/svntest     PythonOption TracUriRoot /trac/svntest  

文档中说TracUriRoot在某些情况下不是必需的,除非你看到如下错误信息:

404 Not Found (No handler matched request to %s)

多env目录的配置如下,使用了TracEnvParentDir:

     SetHandler mod_python     PythonInterpreter main_interpreter     PythonHandler trac.web.modpython_frontend     PythonOption TracEnvParentDir /big2/trac     PythonOption TracUriRoot /trac  

这样配置,如果访问http://domain.com/trac,会列出现有env目录列表,如果想禁止这个列表,可以用LocationMatch替代Location:

 

这样env列表页就无法显示了。

其他

静态文件映射出来让apache处理

静态文件脱离cgi或python的处理,由apache直接负责会对速度有一些提升,用apache的别名把他们直接指向到实际文件路径就可以了,由于执行的顺序问题,需要注意Alias必须放在ScriptAlias的前面,就像这样:

Alias /trac/svntest/chrome/common /usr/share/trac/htdocs
ScriptAlias /trac /usr/share/trac/cgi-bin/trac.cgi

看一看页面引用的css地址:/trac/svntest/chrome/common/css/trac.css,可以看到图像的地址在Alias的处理范围之内(注意本例Alias地址中包含了仓库名称)。如果有多个env目录,逐一创建Alias很麻烦,可以在每个env目录的trac.ini文件[trac]段htdocs_location中设定一个公用的资源文件地址,比如:

[trac]
htdocs_location = /trac-htdocs

这样在apache中也只需要设定一个Alias就可以了:

Alias /trac-htdocs /usr/share/trac/htdocs

这样我们的css地址就变成了/trac-htdocs/css/trac.css。不过logo图像和icon图片的地址好像不受htdocs_location控制,转换不过来。

身份验证

trac的身份验证仍然是通过apache的机制,比如我们常用的、最简单的mod_auth_basic,比如一下配置:

     AuthType Basic     AuthName "Fwolf's Trac"     AuthUserFile /big2/svn/svnpasswd     Require valid-user  

在这里我直接使用了svn的passwd文件,用户就不用记多个密码了。这样设置只是在用户登录的时候验证身份,如果想让用户一进入trac就需要验证身份,把LocationMatch改成这样就行了:

 

不过logout好像就不能用了。另外这样配置trac的用户登录信息是存储在浏览器中的,在需要的时候会自动被调用,所以logout以后,如果不关闭浏览器就重新login,不用再输入密码就直接验证成功了。

如果想定制某些用户能访问某些env,trac好像没有这方面的权限控制功能(wiki的开放性贯彻的真彻底,不过在某些场合下确实需要),依然可以通过apache来实现:

     ...     require user user1 user2 

trac只是能够使用通过apache验证的用户名罢了。

关于中文的一些问题

如果源码或上传文件内容乱码,可以看看conf/trac.ini里[trac]段选项default_charset,如果你svn仓库里的文件和上传文件编码类型都是utf-8的话,把这个设置为utf-8即可。

参考:

Source: http://www.fwolf.com/blog/post/345

用sed替换跨行内容

sed是*nix下方便的行编辑工具,经常用来替换文件的内容,sed一般都是处理单行的,但通过它的一些内建功能,也能实现跨行替换(即要替换的内容有多行内容)。

解决方法主要来自网上搜到的一篇文章,但文中的大侠并没有解释得特别清楚,我对照着其他两个更晦涩的例子(),结合man搞懂了之后,记录于此。

假设我们的目标文件test内容是这样的:

file content
aabbcc<<>>
ddeeff

现在需要把[[[…]]]这一段替换为"COMMENT"(为了说明的必要,没有用容易和正则相混淆的字符比如//*{}[]等来举例子),那么sed语法应当是:

:begin
/<<>>/ {
/>>>/! {
$! {
N;
b begin
}
}
s/<<<.*>>>/COMMENT/;
}

上述语句存储在test.sed中,那么执行的方式和结果就是:

$ sed -f test.sed test
file content
aabbccCOMMENT
ddeeff

把正则直接写到命令里面也可以,用";"来分隔命令即可:

$ sed -e ":begin; /<<>>/ { />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
file content
aabbccCOMMENT
ddeeff

注意右花括号之后也要加上分号";",如果再加上-i参数就可以直接把改动写到原文件中去了。

怎么样?看懂了么?我来详细说明吧,看那个多行命令的test.sed文件的内容:

  • 首先花括号{}代表命令块的开始,类似c的语法,后面就不再说了。

  • :begin,这是一个标号,man中叫做label,也就是跳转标记,供b和t命令用,本例中使用了b命令。

  • /<<>>/,这是一个地址范围(Addresses),后面{}中的命令只对地址范围之间的内容使用。其中逗号前面的部分是开始地址,逗号后面是结束地址,都是正则表达式。由于sed是"流"式"行"处理,所以结束地址是可以省略的,即如果地址的结束范围不存在,那么将一直处理到文件结尾。本例中使用这个地址范围主要是缩小处理的数据量,因为虽然后面用N命令把对一行的处理扩展为了多行,但如果从文件开头一直N扩展到<<

    $ sed -e ":begin; { />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
    or
    $ sed -e "{:begin; />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test

  • />>>/!>>>是要替换内容的结束标记,带上!就是说当一行处理完毕之后,如果没有发现结束标记。。。

  • $!$在正则中表示字符串结尾,在sed中代表文件的最后一行,本句和上一句结合起来的意思就是:如果在本行没有发现结束标记,并且当前扫描过的行并不是文件的最后一行。

  • N;,把下一行的内容追加(append)到缓冲区(pattern)之后,在我们的例子中,在处理aabbcc<<这一行的内容时,就会执行到这里,然后把下一行的内容comment part 2>>>一起放入缓冲区,相当于"合并"成了一行(sed的缓冲区中默认都只会包含一行的内容)。

  • b begin,由于仍然没有找到结束标记<<<(注意上一条说的缓冲区还没有被处理),所以在这里跳回到标号begin,重新开始命令。如果开始和结束标记之间间隔了多行,那么就会有多次跳转发生。

  • s/<<<.*>>>/COMMENT/;,终于,/>>>/!不再匹配成功,也就是我们已经找到了结束标记,那么用s命令来进行替换。如果开始和结束标记在一行的话,就会越过上面那些复杂的处理,直接执行到这里了。

介绍完毕,收工。

Source: http://www.fwolf.com/blog/post/346

升级MT dv 3.0主机到php5

MT主机dv 3.0上的php默认是4,现在已经是php5时代了,不知道MT什么时候默认给配php5,现阶段官方的方式仍然是由用户自行升级,详细步骤见 kb中的Upgrade to PHP5 on (dv) 3.0 Dedicated Virtual Servers

推荐使用suexec方式,这样每个用户执行cgi使用的都是自己的身份,即安全也便于管理。suexec要求的前提条件有三个,就是用户的主机设置开启如下三个选项:

  • PHP支持打开,安全模式safe_mode关闭。
  • CGI支持打开。
  • FastCGI支持打开。

具体步骤说起来也是很简单的,首先把/opt/php51下的php5执行文件拷贝到用户目录下,并设置相应权限:

cp /opt/php51/cgi-bin/php5 /var/www/vhosts//bin/
cd /var/www/vhosts//
chown -R :psacln bin/

其中是用户的域名,是用户的ssh/ftp用户名,然后编辑/var/www/vhosts//conf/vhost.conf文件,添加如下内容:

AddHandler fcgid-script .php .php5
SuexecUserGroup psacln
/httpdocs>
FCGIWrapper /var/www/vhosts//bin/php5 .php
FCGIWrapper /var/www/vhosts//bin/php5 .php5
Options ExecCGI
allow from all

如果是https站点,除了httpdocs换成httpsdocs之外,配置文件名称为vhost_ssl.conf。最后启用设置:

/usr/local/psa/admin/sbin/websrvmng -a -v

就可以了,我们主机上现在的php5版本是5.1.4,还是不够新:)。

为了方便操作,自己写了个小脚本:

#! /bin/bash
# Automatic enable php5 support for mediatemple user(via suexec).

# Pre-prepare in plesk:
# php support is checked, safe_mod 'on' is UNCHECKED
# cgi support is checked.
# fastcgi support is checked.

# Check username, must run with root
WHOAMI=`whoami`
if [ ! $WHOAMI == 'root' ]; then
echo "This script must run with root."
exit 1
fi

# Check parameters
if [ $# -lt 2 ];then
echo "Usage: `basename $0` ssh_user domain"
exit 1
fi
USER=$1
DOMAIN=$2

# If given a wrong domain, exit
if [ ! -d /var/www/vhosts/$DOMAIN ]; then
echo "Domain doesn't exists."
exit 1
fi

# Copy php5 files
cp /opt/php51/cgi-bin/php5 /var/www/vhosts/$DOMAIN/bin/
cd /var/www/vhosts/$DOMAIN/
chown -R $USER:psacln bin/
cd conf

BEGIN="###_87b4e7fc -- Add by enable_php script, DON'T modify this section --"
END="# -- Enable_php modify section end -- 87b4e7fc_###"

# If vhost.conf doesn't exists, create it with default content
if [ -z vhost.conf ]; then
echo "\
$BEGIN\
$END\
" >> vhost.conf
else
MARK=`grep "###_87b4e7fc" vhost.conf|wc -l`
if [ $MARK -eq 0 ]; then
# If vhost.conf exists & not mark, add replace mark
echo "\
$BEGIN\
$END\
" >> vhost.conf
fi
fi
# Vhost_ssl.conf
if [ -z vhost_ssl.conf ]; then
echo "\
$BEGIN\
$END\
" >> vhost_ssl.conf
else
MARK=`grep "###_87b4e7fc" vhost_ssl.conf|wc -l`
if [ $MARK -eq 0 ]; then
# If vhost.conf exists & not mark, add replace mark
echo "\
$BEGIN\
$END\
" >> vhost_ssl.conf
fi
fi

STR="$BEGIN\n\
AddHandler fcgid-script .php .php5\n\
SuexecUserGroup $USER psacln\n\
\n\
FCGIWrapper \/var\/www\/vhosts\/$DOMAIN\/bin\/php5 .php\n\
FCGIWrapper \/var\/www\/vhosts\/$DOMAIN\/bin\/php5 .php5\n\
Options \+ExecCGI\n\
allow from all\n\
<\/Directory>\n\
\n\
FCGIWrapper \/var\/www\/vhosts\/$DOMAIN\/bin\/php5 .php\n\
FCGIWrapper \/var\/www\/vhosts\/$DOMAIN\/bin\/php5 .php5\n\
Options \+ExecCGI\n\
allow from all\n\
<\/Directory>\n\
# some configure options\n\
# another line\n\
$END"

# Backup original configure
cp vhost.conf vhost.conf.`date +"%Y%m%d-%H%M%S"`
cp vhost_ssl.conf vhost_ssl.conf.`date +"%Y%m%d-%H%M%S"`

# Write configure information
sed -i -e ":begin; /###_87b4e7fc/,/87b4e7fc_###/ { /87b4e7fc_###/! { $! { N; b begin }; }; s/###_87b4e7fc.*87b4e7fc_###/$STR/g };" vhost.conf
sed -i -e ":begin; /###_87b4e7fc/,/87b4e7fc_###/ { /87b4e7fc_###/! { $! { N; b begin }; }; s/###_87b4e7fc.*87b4e7fc_###/$STR/g };" vhost_ssl.conf

# Active new configure
/usr/local/psa/admin/sbin/websrvmng -a -v

使用方法,用root用户执行:

enable_php5  

不支持subdomain的设置,其中sed替换多行内容的用法,可以参考我写的另外一篇文章用sed替换跨行内容

conf/vhost.conf这个文件存在之后,并不会自动被apache调用,执行/usr/local/psa/admin/sbin/websrvmng -a -v可以自动在conf/httpd.include文件中include vhost.conf了。而conf/httpd.include这个文件是由plesk维护的,用户不要直接修改它,会被plesk覆盖掉。

另外由于使用的是suexec方式执行,所以上传目录、cache等以前需要设置apache用户有可写权限的文件,现在要把owner设置为:psacln才行,和用户的其他文件权限一样就可以了,是不是管理起来更方便一些?

看了一下phpinfo,自动加载了位于/opt/php51/lib/php5/extensions/下的如下模块:

curl.so  gd.so        mysql.so    pdo.so        sockets.so  zlib.so
dom.so iconv.so mysqli.so pdo_mysql.so sqlite.so
ftp.so mbstring.so openssl.so posix.so xsl.so

基本上常用的都有了,但不知道/opt/php51这个目录下的内容MT什么时候给更新,还是说需要用户自己更新?

参考

Source: http://www.fwolf.com/blog/post/347

2007年8月2日星期四

Hosts用法两则

Hosts文件是好东西,还是跨平台的,不仅可以方便局域网名称的映射、加快域名解析速度,甚至还能让你访问某些无法解析域名的网站。今天我又琢磨出这个文件的另外两种用法。

利用Hosts文件隐藏公网地址

我有一个放在公网上的地址,用apache提供的web服务,但是我并不想让它公开,而是只允许我自己用;如果架在本机,那我出门或者回家就用不了了,同理只允许ip段的访问也不方便;用一个比较"深"的地址来访问也不是什么好办法,别说spider肯定能抓到,从这里点出去的链接,referer就把你给出卖了。

解决的思路就是,利用Hosts文件作出一个只有我自己能用的"域名",当我使用这个域名访问的时候,由于本机的Hosts文件,它会解析到正确的地址,而别人或者蜘蛛或者从referer链接回来的访问,都会由于无法解析dns而失败。

当然这种做法只是一个小把戏而已,如果别人也知道域名和ip就不保密了,所以仍然需要结合其他限制访问方式使用。另外,对于只知道ip的访问,我们还是有办法的,将apache的conf如下设置:

NameVirtualHost *

DocumentRoot /var/www/apache2-default/
ServerName w3c.com DocumentRoot /path/to/some/file/ ServerName autobots.fwolf.com

这样如果不知道autobots.fwolf.com这个秘密地址,就是知道ip也进不来。另外如果把 autobots.fwolf.com这个域名再作个解析,就会更有意思了。

Hosts文件结合apache的VirtualHost创建易于调试的开发环境

这就比上面的简单多了,一般搭建项目调试环境的时候,如果管理不慎,会把服务器的设置搞得一塌糊涂,另外多项目并存的情况下,需要的环境、配置各不相同,有的还需要必须在网站根目录下运行,这种情况下,就可以用Hosts文件结合apache的virtualhost让一台开发服务器变身为多台。创意参考自虚拟主机的做法。

首先还是用hosts文件定义出别名来,比如computer1、computer2都指向一台服务器,但是这两个地址就像是在用两台电脑一样了;然后再在apache中用name方式的virtualhost定义project1、project2(每个project单独使用一个配置文件更方便,每个virtualhost还能够定制相应的环境)。

现在,知道该怎么使用了吧?要不怎么说hosts文件是个好东西呢。

Source: http://www.fwolf.com/blog/post/344