游戏人生

颂山川,吟古道,偏失半点笔墨;言世事,问苍生,更差一声长嗟。

vim对于大多数在Ubuntu下使用vim作为常用编辑器的同学来讲,他们遇到的第一个比较大的麻烦来自于vim与外部应用的复制粘贴。

当然,愿意选择ubuntu以及vim的同学肯定是google好手。不幸的是,各大论坛告诉你,你可以在命令模式下使用类似"*p或者"+p的命令将已经复制或剪切到系统剪切板的外部内容粘贴进来,也可以使用类似"*y或者"+y的命令将vim中的内容复制到系统剪切板中。很多同学照此操作解决了这个问题,然而也有一些同学则悲剧的发现,这个方法没有任何作用。

这一切都可以从vim帮助中找到答案。

无论是vim内部抑或外部的复制([y]ank)、删除([d]elete)、粘贴([p]ut),在vim中都是借助registers(寄存器)实现的,vim共有9类寄存器:

  1. 无名(unnamed)寄存器:"",缓存最后一次操作内容;
  2. 数字(numbered)寄存器:"0 - "9,缓存最近操作内容,复制与删除有别;
  3. 行内删除(small delete)寄存器:"-,缓存行内删除内容;
  4. 具名(named)寄存器:"a - "z"A - "Z,指定时可用;
  5. 只读(read-only)寄存器:":, "., "%, "#,分别缓存最近命令、最近插入文本、当前文件名、当前交替文件名;
  6. 表达式(expression)寄存器:"=,只读,用于执行表达式命令;
  7. 选择及拖拽(selection and drop)寄存器:"*, "+, "~,存取GUI选择文本,可用于与外部应用交互,使用前提为系统剪切板(clipboard)可用;
  8. 黑洞(black hole)寄存器:"_,不缓存操作内容(干净删除);
  9. 模式寄存器(last search pattern):"/,缓存最近的搜索模式。

上面的说明为简要概述,并不完全准确,详细说明须参考手册:

:help copy-move

无图形界面的vi或vim下可用的寄存器只包括{a-zA-Z0-9.%#:-"},显然,这里面没有包含上面提到的"*或者"+等选择及拖拽存器。

由此可见,实现vim与外部应用相互复制、粘贴的关键在于系统剪切板对于vim是否可用。查看vim剪切板是否可用的命令为vim --version,下面是我的系统下面的结果(我只保留了xterm_clipboard一项):

VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Apr 16 2010 12:47:47)
包含补丁: 1-330
编译者 buildd@
巨型版本 无图形界面。  可使用(+)与不可使用(-)的功能:
-xterm_clipboard

对于非GUI版本的vim,剪切板是不可用的,解决方案很简单,安装一下就是了:

sudo apt-get install gvim

下面是安装之后的结果:

VIM - Vi IMproved 7.2 (2008 Aug 9, compiled Apr 16 2010 12:40:58)
包含补丁: 1-330
编译者 buildd@
巨型版本 带 GTK2-GNOME 图形界面。
  可使用(+)与不可使用(-)的功能:
+xterm_clipboard

两年之前换手机的时候,舍不得买iphone,彼时android尚不成熟,我也不愿当小白鼠,便买了一部dopod s1,感觉挺鸡肋的一款智能机。倒不是因为windows mobile的系统差,而是作为一款智能机,s1 320*240的分辨率无法充分发挥阅读、网络功能,而且无法升级到wm 6.5,更加致命的是,国产行货没有wifi功能。

后来在用ipod touch的时候,480*320的分辨率明显把电子阅读、网络浏览的观感提升了很多,尤其是wifi功能更为必要。在使用pc时,浏览邮件或订阅往往是走马观花,甚至直接跳过。反而是在touch上浏览时,更加专注和方便。GF经常在成渝两地奔波,为弥补我的愧疚,touch便留给她使用。

如此一来,心里仿佛忽然空了一大截。当然我也不希望再买一个touch,反正手机已经用了两年多,换一个也在情理之中。多方比较了一下,希望在iphone和android手机上做选择,因为实在对windows mobile不感冒。使用touch的经验告诉我,虽然itunes应用很多,但apple对系统的控制让人感觉不很舒服,相比之下,android要开放的多。

刚好这段时间,同事也在考虑换手机,我便极力怂恿他选择i9000。结果,把他说动之前,我自己先被说服了。下午下班之前下的单,转天上午就到了,这种效率也让我心情大好。

手机本身也没有令我失望,速度、操控、显示各方面都比较舒服。之前觉得android在模仿ios,使用之后发现,android系统自身亮点众多。在电源管理、应用程序、账户关联方面给我的印象最好。

目前发现的唯一缺点是联系人无法中文首字母索引,一个常见的解决方案是安装root explorer后,使用root替换一个共享库。经初步测试,i9000下替换系统文件失败。毕竟是第一次使用android,不希望给自己带来太多未定,也因此放弃了其他获取root的方法。反正android中文排序本身正常,无非是无法字母索引,把联系人姓前面加上中文首字母也无伤大雅,于是写了几十行代码,把问题解决了。

为了让这样的流水体现一点价值,把实现的过程记录一下。

== Step 1. 找一张汉字|拼音映射表 ==

这个比较简单,很容易google到,唯一需要注意的是,有些只提供7K+的常用字,最好是找比较完整的29K+汉字表。

== Step 2. 建立字典 ==

考虑到不同语言实现的通用性,我将汉字与拼音的映射存放在一个xml文件中:

<?xml version="1.0" encoding="utf-8"?>
<map>
  <m c="一" g="D2BB" p="yi" u="4E00"/><m c="丁" g="B6A1" p="ding" u="4E01"/>
  <m c="丂" g="8140" p="yu" u="4E02"/><m c="七" g="C6DF" p="qi" u="4E03"/>
  <m c="丄" g="8141" p="shang" u="4E04"/><m c="丅" g="8142" p="xia" u="4E05"/>
  <m c="丆" g="8143" p="myeon" u="4E06"/>
</map>

上面的文件不完整,本文最后提供了完整文件下载。c为汉字,g为GBK码,p为拼音,u为unicode。

== Step 3. 从gmail导出联系人列表 ==

将联系人列表保存在gmail中是一个不错的选择。悲剧的是,我在使用windows mobile的同步软件将手机上的联系人同步到outlook时,不慎将outlook同步到手机中,导致所有联系人丢失。这其中自然有我自己的原因,却也让我对windows更加失望。我只好基于公司通讯录创建新的联系人列表,并从outlook导入gmail,再从gmail导出csv到我的ubuntu。

== Step 4. 改写联系人姓名 ==

我直接从gmail导出的文件编码为utf-16,因为统一使用utf-8,所以需要转换一下。

下面是改写的完整代码:

# -*- coding: utf-8 -*-
# file : contact.py
# author : YuleFox (GMAIL.COM)
# url : http://www.yulefox.com/
# license : http://www.opensource.org/licenses/mit-license.php

import xml.dom.minidom as parser
import codecs, re

def loadDict(file):
    doc = parser.parse(file)
    root = doc.documentElement
    dict = {}
    for n in root.childNodes:
        str = n.getAttribute('p').upper()
        dict[n.getAttribute('c')] = str[0]
    return dict

def prefixName(file, dict):
    with codecs.open(file, 'r', 'utf8') as rf:
        with codecs.open('g.csv', 'w', 'utf8') as wf:
            r = re.compile(ur'^(?P<p>.*,.*,.*,)(?P<fn>[\u4e00-\u9fa5]+)(?P<r>.*$)')
            for l in rf:
                m = r.match(l)
                if m:
                    l = u'{0}{1}{0}{2}{3}\n'.format(dict[m.group('fn')],
                            m.group('p'),
                            m.group('fn'),
                            m.group('r'))
                wf.write(l)
            wf.close()
        rf.close()

if __name__ == '__main__':
    dict = loadDict('hanzi.xml')
    prefixName('google.csv', dict)

由于我是在ubuntu下操作(文件默认编码格式为utf-8),如果你是在windows下(文件默认编码格式为gbk),必须保证google.csv编码格式为utf-8。

== Step 5. 同步 ==

将改写后的g.csv导入gmail,同步android上的账户即可。

下载:hanzi.xml

多方比较之后,决定选用python框架django做web开发,选用python而不是php或者asp之类的原因主要是三点:

  • 操作系统喜好决定了我不会选择asp。相比windows,更喜欢linux;
  • php的类C语法打动了我,兼之历史悠久,与mysql的结合也很好,只是我总觉得php离我心中的编程感觉远了点;
  • python缩进在有代码洁癖的我看来很优雅,而且python用途更广泛。

这一次使用nginx+django的过程中,解决了之前的一些问题:比如关于URI(尤其是静态文件的URI)解析的问题。按照django官方文档的说法:Django itself doesn’t serve static (media) files, such as images, style sheets, or video. It leaves that job to whichever Web server you choose. django只针对开发过程提供django.views.static.serve()视图,产品配置则须由web server完成。这个问题包括使用django的admin应用需要面对的admin的media URI解析问题,期间又对nginx配置熟悉了一些。

另一个问题正是关于nginx的,这次把django、php、trac都放在一个虚拟主机下,非常有创意,但绝非有意为之的一个结果是:django和php虽然都使用nginx+fastcgi,但django使用socket方式,而php使用host方式;trac则使用nginx对apache作反向代理。如此混搭的方式,与其说是为了实验各种实现,不如说我尚未找到统一的方案,尤其是针对trac的nginx+fastcgi socket的配置方案。

第三个问题是针对开发和产品采用不同配置带来的问题。这篇文章通过判断当前主机的名称决定使用哪种配置。方法简单有效,只是当开发主机与产品主机相同时需要动动脑筋;相比之下,我觉得这篇文章介绍的方法更加通用。

由于涉及项目具体配置,有必要对本文提到的项目名称和目录进行说明,参考时请注意作相应修改:

  • 项目名称:fox
  • 项目位置:/home/yulefox/fox
  • 开发用配置文件:/home/yulefox/fox/settings/development.py
  • 产品用配置文件:/home/yulefox/fox/settings/production.py

项目fox创建时,django在项目目录/home/yulefox/fox下生成对应的配置文件settings.py。为了能够针对开发及产品使用不同的配置文件并便于管理,我们将其移至新建目录settings下并重命名为development.py,并在该目录中创建名为__init__.py的空文件以保证该目录可作为包使用。此时当我们使用python manager.py runserver命令运行开发服务器时,得到以下结果:

            Validating models...
            0 errors found

            Django version 1.2, using settings 'fox.settings'
            Development server is running at http://127.0.0.1:8000/
            Quit the server with CONTROL-C.

我们注意到,django并没有使用我们修改后的配置fox.settings.development。这是由于项目中的manager.py导入的配置没有改变,将manager.py中的settings替换为settings.development后,再次运行得到以下结果:

            Validating models...
            0 errors found

            Django version 1.2, using settings 'settings.development'
            Development server is running at http://127.0.0.1:8000/
            Quit the server with CONTROL-C.

结果证实修改生效,不幸的是,这并不是终点,因为当我们打开http://127.0.0.1:8000/时,我们看到了以下错误信息:

            ImportError at /

            No module named fox.urls

容易想见,这应该正是因为修改配置文件目录的问题,我们可以通过在python manager.py shell中输出sys.path的结果来印证这一点,输出中包含了项目目录/home/yulefox/fox而非项目的父目录/home/yulefox,显然,项目fox中不再有一个名为fox.urls的model,python为我们提供了一个名为PYTHONPATH的环境变量,我们可以通过设置该环境变量因应配置文件目录的变化:export PYTHONPATH=/home/yulefox

另外,我们可以无需修改manager.py和使用python manager.py runserver解决本文提到的配置问题。django提供了环境变量DJANGO_SETTINGS_MODULE以设置所使用的配置文件,如本文中:export DJANGO_SETTINGS_MODULE=fox.settings.development。这种情况下,我们需要使用django-admin.py runserver启动服务器。

上面介绍的开发配置方式同样适用于产品配置方式,我们只需在settings包中添加并配置production.py即可。在Apache中,我们可以直接在虚拟主机配置文件中使用SetEnv DJANGO_SETTINGS_MODULE fox.settings.production完成对环境变量的配置;而在Nginx中,如果使用fastcgi,则可以使用manage.py runfcgi --pythonpath=/home/yulefox/fox --settings=fox.settings.production来完成配置;wcgi等实现方式需要读者自行完成。

刚接触Linux时,短暂试用vim之后,出于对其操作中模式理念的陌生,最后转投Emacs门下。随着各种插件的增多,Emacs被我打造成一个不折不扣的IDE,其启动速度也降到和Visual Studio相当,逐渐令我难以接受。于是再次选择vim。

周围很多同事在使用Google Reader阅读各种资讯。每天花半个小时左右的时间接受各种知识对于自我提升有一定的帮助。为了提高时间利用率,推荐大家使用GR自带的快捷键。在GR中按’?'键可以查看快捷键列表,见下图:

google_reader_geek

熟悉vim的同学对于GR提供的快捷键应该有天生的好感,看来,Google的同学还是使用vim的多啊。

一直奢望有一天可以完全不借助鼠标浏览网页,曾经以为这是个幻想,没想到在我比较喜欢的FireFox上有这样一款插件:vimperator,不仅可以抛开鼠标,而且操作方式与vim相同。是的,又是vim,不是Emacs……

世界杯之月,即使像我这样的伪球迷也为之鼓而呼。当然,一个月没有更新并不是因为世界杯,也不是电脑罢工两周,最主要的原因是之前在使用django + ajax时遇到了一些困难,这些困难到现在也没有完全解决,一些工作离我预期的效果还差很多。但但为了不让属于自己的六月显得虚度,还是要象征性的更新一篇。何况,这个月还是有一些值得记录的事情:

  1. 自己又结结实实的长大/老了一岁;
  2. 我的学生时代结束一年之后,女朋友也毕业了;
  3. 女朋友在毕业之前终于确定了自己的工作。

之前在搭建web服务器的时侯,都是使用眼下主流的apache。这次在机器升级(两次升级都以失败告终,所以准确的说,是重装)到ubuntu 10.04之后,打算赶个时髦,用nginx做服务器,由于对nginx和fastcgi都不熟,搞了两个晚上,到现在还只是配置php成功,trac还没有搞定。

中间几次想放弃,继续投奔apache,并且把主要精力先放在内容实现上。最后还是决定享受这段自虐,就当是对服务器熟悉的一个过程。无论是服务器还是脚本,除参考别人的经验外,自己的实践是少不了的。如果是为了方便的话,apache虽显臃肿,但由于历史悠久,文档丰富,支持者众,用起来最方便;如果想折腾的话,怎么着都是你自己受罪,就无所谓了。

总结了一下,对于初次尝试nginx(尤其是对这一块不甚了解)的同学来讲,还是从最简单的静态页面支持开始,逐渐深入掌握其它服务器配置,想一步到位的搞定所有问题几乎是不现实的,一步步的做反倒是最快的方法。在这一点上,我刚开始的时候就有点冒进,以为自己对apache搭建虚拟主机有了点经验,上手nginx也会很简单,前面搞了几个小时都可耻的失败了,撞墙后从头再来:

o localhost默认欢迎页面;

o 局域网IP和虚拟主机默认欢迎页面;

o 虚拟主机指定文档目录(支持静态页面);

o 虚拟主机php服务器配置。

现在还有trac、svn等问题未解决,所以在平稳过渡到nginx之前,还是继续使用apache作web server。使用nginx对apache进行反向代理,apache改用8080端口,nginx使用默认80端口。


最后附上一份虚拟主机配置:

#! /usr/bin/perl

server {
    listen       80;
    server_name  km.fox.com;
    root         /home/fox/yulefox/km;
    index        index.html;

    location / {
        proxy_pass      http://192.168.1.100:8080;
        proxy_redirect  default;
    }
}

server {
    listen       80;
    server_name  www.fox.com;

    location / {
        root   /home/fox/yulefox/web;
        index  index.php;
    }

    location ~ \.php$ {
        include        /etc/nginx/fastcgi_params;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME /home/fox/yulefox/web$fastcgi_script_name;
    }
}

WeBwArE

2005年在重庆结识一位西南政法大学的朋友,该生擅长篆刻,当年曾央其制得一枚闲章(见下图)。

01

受其熏陶,自己也曾先后刻了几枚印章,经常用的只是2005年底刻的一枚藏书章,那几把刻刀这次去北京的时侯也送了朋友,几方印石还躺在抽屉里(见下图)。

02

4月份的时候,机缘遇合,又得这位朋友一枚藏书章,两人都知道同在成都,两年间却也没有聚过,借这个机会见面小聚一回(见下图)。

03

我对于篆刻虽然略知皮毛,从这两枚印章中还是能够看出朋友刀法相比从前更加娴熟流畅,富于变化。

看来要把手里的泡沫印泥丢掉了,也换一盒朱砂的,看看再买把刻刀,空了再写写字,刻刻章,过过健康的生活。


五一回家一趟,在北京逗留了几天,住在回龙观大盛那里。和在京的同学聚了几次,阔别五年,大家都变得更加成熟,言谈间虽多了些许恭维,真诚却不减分毫。

参观了fallhunter的创业公司,祝兄弟成功!

回到老家发现家里的发展超过了我的想像,想到自己在外漂泊家人的挂念,甚至动了回家的念头。


看好html5,继续看好webware。

svn备份是一项比较重要的工作,这里主要用到两个工具:svnadmin(1)crontab(1)svnadmin用于对svn版本库进行管理,crontab则用于管理周期事务。

方法比较简单,首先创建一个脚本,内容如下:

#!/bin/sh

project="svn"
svnroot="/var"
backdir="/home/fox/svnbackup"
date=`date +%m%d%Y`
dumpfile=$date.$project.tar.gz
log="svnbak.log"
logtime=``
SVNADMIN=/usr/bin/svnadmin

# all actions can be done under $backdir
cd $backdir

echo " ----------------- BACKUP START ----------------- " >> $log

# omit request in the same day
if [ -f $dumpfile ]
then
echo `date +"%m-%d-%y %H:%M:%S"`" backupfile [$dumpfile] has exist!" >> $log
# backup repos with `svnadmin hotcopy'
else
$SVNADMIN hotcopy $svnroot/$project $project --clean-logs
echo `date +"%m-%d-%y %H:%M:%S"`" backup [$project] done into [$backdir]" >> $log
# compress backup data
tar czvf $dumpfile $project > /dev/null
echo `date +"%m-%d-%y %H:%M:%S"`" compress [$dumpfile] finished" >> $log
# remove temp project dir
rm -rf $project
fi

# remove old dump file [at most 10 copies store here]
olddump=$(date +%m%d%Y --date='10 days ago').$project.tar.gz

if [ -f $olddump ]
then
rm -f $olddump >> $log 2>&1
echo `date +"%m-%d-%y %H:%M:%S"`" [$olddump] delete success!" >> $log
else
echo `date +"%m-%d-%y %H:%M:%S"`" [$olddump] not exist!" >> $log
fi
echo " ----------------- BACKUP ENDED ----------------- " >> $log

这个脚本完成的主要工作是先用svnadmin hotcopy命令备份代码仓库到指定目录,用tar打包保存;另一项工作是会删除10天前(因为我选择的是每天备份,你可以根据需要制定自己的方案)的副本。

简单测试通过后,就可以添加到crontab了,第一次使用crontab -e命令时需要选择编辑器,编辑格式非常简单:

$ crontab -e
no crontab for fox - using an empty one

Select an editor.  To change later, run 'select-editor'.
1. /bin/ed
2. /bin/nano        <---- easiest
3. /usr/bin/emacs23
4. /usr/bin/vim.tiny

Choose 1-4 [2]: 3

>>>> 下面是编辑的内容
# m h  dom mon dow   command
0 23 *   *   *     /home/fox/cron/svnbackup.sh

>>>> 保存退出,自动加入事务列表
crontab: installing new crontab

>>>> 查看当前事务
$ crontab -l
# m h  dom mon dow   command
0 23 *   *   *     /home/fox/cron/svnbackup.sh

笔记本上之前装的双系统(Vista + Ubuntu 9.10),在刚拿到机器的时候,把Vista从home换成ultimate,之前OEM的序列号竟然有效,所以就一直开着Windows Update,前段时间终于遭遇了传说中的黑屏。想想算了,自从使用Ubuntu,慢慢觉得使用盗版软件是一件可耻的事情,也就不想再去激活Vista了(当然也不会去买正版),不用就是了。

所以这次Ubuntu 10.04升级失败之后,决定不再要双系统,只装10.04(这次之所以急于安装10.04,是因为10.04开始支持iPhone和iPodTouch了)。我对恢复系统没有十足的把握,本来想好是要备份的,一冲动,只把自己需要的东西转到老婆的电脑上,没有备份/etc/var/usr下面的内容。于是这两天没做什么事情,开始重复噩梦:

==== evince中文支持问题 ====

evince是Ubuntu下默认的pdf阅读器,对于没有内嵌中文字体的pdf文件,evince无法显示。evince使用Poppler作为pdf渲染库,因此需要安装Poppler编码库poppler-data以支持中文显示:

apt-get install poppler-data

==== emacs中文输入问题 ====

Ubuntu中文输入从9.10开始默认使用ibus,安装新的输入法倒是比较简单,但默认的输入法切换使用Ctrl+Space。emacs23内置中文支持,但中文输入还是使用ibus更习惯一些。emacs下Ctrl+Space作为Mark Set快捷。

查了一下,是locale的问题,因为装的是英文环境,默认变量均为en_US.utf8,其中LC_CTYPE定义系统的字符处理编码,在/etc/environment(这是Ubuntu下的环境配置,个人的~/.bashrc文件中也可以)中添加LC_CTYPE="zh_CN.utf8",并在/var/lib/locales/supported.d/zh-hans中加入下面几行:

zh_CN.UTF-8 UTF-8
zh_SG.UTF-8 UTF-8
zh_HK.UTF-8 UTF-8
zh_TW.UTF-8 UTF-8
zh_CN.GB2312 GB2312
zh_CN.GBK GBK
zh_CN.GB18030 GB18030

执行sudo locale-gen,将在/usr/lib/locale/下生成对应的环境编码数据。

==== 本文重点1:安装trac ====

使用了几个月,感觉trac+svn也成了我的个人知识管理(KM)的一个标配。之前没有记录下自己的安装过程,这次重装的时候,顺便理一下整个重装过程(参考TracInstall)。

如果没有特别需求的话,不用svn最新的版本,下载稳定版本的Trac就可以了。

trac使用python(Ubuntu 10.04的python版本为2.6.5)开发,使用easy_install安装,如果没有:

wget http://peak.telecommunity.com/dist/ez_setup.py
sudo python ez_setup.py

可以直接使用下面的命令安装trac、SQLite、Genshi:

sudo easy_install Trac

Searching for Trac
Best match: Trac 0.11.7
Processing Trac-0.11.7-py2.6.egg

还可以选用MySQL、PostgreSQL作db,对于个人来说,SQLite够用了,就一个文件,很方便。

创建trac项目(在~/yulefox下创建名为km的项目),除指定项目名称和代码仓库位置外,其它我都使用了默认配置,所有配置都可以在项目目录下的conf/trac.ini中修改:

trac-admin ~/yulefox/km initenv
Creating a new Trac environment at /home/fox/yulefox/km
...
项目名称:Project Name [My Project]> FoxKM
数据库:Database connection string [sqlite:db/trac.db]>
代码版本管理工具:Repository type [svn]>
代码仓库位置:Path to repository [/path/to/repos]>/home/fox/yulefox/svn
Creating and Initializing Project
...
---------------------------------------------------------------------
Project environment for 'FoxKM' created.
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 /home/fox/yulefox/km

Then point your browser to http://localhost:8000/km.
...
Congratulations!

看到Congratulations!我就放心了:),按照上面说的方式就可以测试一下了,不过我们显然希望用apachenginx现在挺时髦的,不知道trac会不会支持nginx)搭建一个合适的Web Server。

Trac提供对CGI、FastCGUI、mod_python的支持(新加对mod_wsgi的支持),我对这一块并不是很熟悉,一般使用Apache + mod_python配置。

配置主机

我在自己的机器上使用fox.com作为虚拟主机名,反正我也不会去访问FOX,就用它了:D。我指定的IP是127.0.1.1,因为我只想在本地访问,你可以指定其他可用的IP:

# Adds virtual hosts to /etc/hosts

$ sudo emacs /etc/hosts
127.0.1.1   fox.com
127.0.1.1   www.fox.com
127.0.1.1   km.fox.com

创建虚拟主机配置:

# Adds one site named 'fox.com'
$ sudo emacs /etc/apache2/sites-available/fox.com

NameVirtualHost 127.0.1.1:80

ServerAdmin Fox
ServerName km.fox.com

DocumentRoot "/home/fox/yulefox/km"
# trac

SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /home/fox/yulefox/km
PythonOption TracUriRoot /

# trac login

Require valid-user
AuthType Basic
AuthName "TracLogin"
AuthUserFile /etc/home/fox/yulefox/km.passwd

启用虚拟主机配置:

sudo apt-get install libapache2-mod-python libapache2-mod-python-doc
sudo a2ensite fox.com
sudo /etc/init.d/apache2 reload

有可能会得到下面的提示:

apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName

需要在/etc/apache2/conf.d/目录下创建名为fqdn的文件,并添加配置的服务器:

ServerName fox.com

此时再reload Apache就清净了,访问一下http://km.fox.com/,提示:

TracError: The user www-data requires read _and_ write permissions to the database file /home/fox/yulefox/km/db/trac.db and the directory it is located in.

原来是访问权限的问题:

$ sudo chown -R www-data /home/fox/yulefox/km/
$ ls -l yulefox/km
total 44
drwxr-xr-x  9 www-data fox 4096 2010-04-11 16:25 ./
drwxr-xr-x 14 fox      fox 4096 2010-04-11 16:25 ../
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 attachments/
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 conf/
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 db/
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 htdocs/
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 log/
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 plugins/
-rw-r--r--  1 www-data fox   98 2010-04-11 16:25 README
drwxr-xr-x  2 www-data fox 4096 2010-04-11 16:25 templates/
-rw-r--r--  1 www-data fox   27 2010-04-11 16:25 VERSION

搞定!

==== 本文重点2:恢复trac备份 ====

之前的trac我是备份了的,恢复起来也很方便:直接把备份的文件夹内容copy到上面的km中即可:D。关于trac使用的细节和更多丰富功能的插件,本地文档或者官方网站上面都介绍的非常详细,这也是我喜欢使用它的一个原因。

时隔2年,Canonical的第3个LTS(Long Term Support,长期支持)版本Ubuntu 10.04(Lucid Lynx)即将(4月29日)正式发布。

ubuntu 10.04 LTS

LinuxPlanet的最新报告,10.04尚未正式发布,Ubuntu当前用户已达1200万。

使用Ubuntu刚半年,感觉还是比较好。10.04 beta1刚出,就把家里的本子从9.10在线升级10.04 beta1,不幸的是——升级失败:标题栏无法显示,很多快捷键和功能无法使用(Alt+F2、Alt+F7、Alt+F8)。而我又找不到出错的原因,只好考虑把系统备份之后重装。

之前还没有备份过系统,查了一下,关键是几个地方:

* 整理需要备份的内容并确认这些内容的对应的目录和文件;

* 用tar、dpkg等工具备份这些目录和文件及安装的应用列表。

* 整理需要备份的内容并确认这些内容的对应的目录和文件

对于个人用户(非商业应用或服务器应用),需要备份的内容主要包括:

* 个人数据:文档、书籍、代码、图片、音乐、视频、个人配置等,这些内容一般保存在/home下用户目录中;

* 应用程序:安装的一些应用程序及其对应配置:依照文件系统层次标准FHS,/usr中存放的应该是可共享的只读数据,因此除了/usr下的应用、数据、手册、源码等以外,还有这些应用(web、mail、ftp等)的可写配置及数据库等,一般位于/etc、/var中;/opt用于保存外部应用程序安装包,这些数据视需要也可以备份。

有些内容(如大多数应用程序)不一定需要备份,只要你的网络足够好,reinstall的时间也不会长,还有一个原因就是,一些应用更新的速度比较快,备份的意义不大,尤其是在系统升级或更换其他系统的时候,但个人数据和一些应用的配置、数据库等就不是网络好能替代的了。

可以参考一下这篇文章:Backup Basics and Different types of backup

总结一下,需要备份的目录主要是:

/boot
/etc
/home
/opt
/root
/srv
/var/lib/mysql
/usr/local
/var/www
/var/www

* 用tar、dpkg等工具备份这些目录和文件及安装的应用列表

一种简单、直观的方式:

tar cvpzf backup.tgz / –exclude=/backup.tgz –exclude=/dev –exclude=/lost+found –exclude=/media –exclude=/mnt –exclude=/proc –exclude=/sys

如果需要定期备份,可以写入shell,借助/etc/crontab实现自动备份。

对于来自Windows的懒人来说,这些算是比较麻烦的了,ubuntu下安装sbackup工具可以替代上述工作:

sudo apt-get install sbackup

详情见:Backup and Restore Your Ubuntu System using Sbackup

dpkg主要用于备份和恢复安装的所有应用程序:

* 备份

dpkg –get-selections | grep -v dnstall > ~/softlist

* 恢复

sudo dpkg –set-selections < ~/softlist


话说10.04 beta2今天已经发布,这个周末,有的搞。

django

现在已经无法确切地说出最早接触python的时间和动机了,但有几件事或许可以交待出接触python的一些想法,能够折射出自己在一些东西上的后知后觉:

08年10月底,在和网易的两位朋友(Soft也在)聊起脚本语言,了解到python在网易的一些工作室应用比较广泛,主要应该是用到脚本和UI开发吧。当时自己对python没有什么概念,也没动过接触一下的念头。

pygame

09年11月,在跟同事AHC聊天的时侯第一次见识了python(确切地说是pygame),时隔一年,我还是对python没有什么概念,所以也就没有形成什么印象。

09年07月认识了yospaly(只是网上交流过一两次),他应该算是开源软件(或者是自由软件?)的拥趸吧,知道他对django感兴趣,那是我第一次看到这个名字,也没有去深入了解。

django

后来,就常在FallHunter的blog里面见到这个词。自己对互联网仅限于使用,也没想过做开发,所以还是没有去关注。

09年12月,再一次因为服务器的问题搬家的时候,开始对这样折腾blog感到疲倦,想有个安稳的地儿,也想玩点自己的东西。

09年12月,在使用SVN管理代码之后,开始用trac(目前看来,效果还不算坏,之前试图通过googlegroup做交流算是失败),注意到trac是基于python开发的。

突然之间,自己的神经受到了触动,前前后后,这才将python与web联系起来,就想自己也可以做点东西自娱自乐。

刚开始的时候,了解了一些python语法,在读django的文档的时候,还是有些囫囵吞枣,想想还是需要系统的学习一下python,这个过程中想写点东西,因为对web开发知之甚少,所以还是没有继续完成计划的django应用,就绕回到pygame来了。


在接触新的语言或SDK时,最大的问题是参考文档的问题,所幸,大多数语言和SDK都有详尽的文档或手册。但是python的docstrings还是像其缩进语法那样,给我留下了非常深刻的印象。或许,这就是传说中的pythonic?

喜欢python的Easter Egg,尤其是import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren’t special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one– and preferably only one –obvious way to do it.
Although that way may not be obvious at first unless you’re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it’s a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea — let’s do more of those!