2009年8月12日星期三

使用hooks/update脚本控制git-push用户权限

使用hooks/update脚本控制git-push用户权限

作者:志磊先生 <talebook@gmail.com>

概述:
我们使用三个文件$GIT_DIR/hooks/update, $GIT_DIR/info/allowed_users,
$GIT_DIR/info/allowed_groups对GIT的push提交进行控制,进而来实现中心版本库服务器功能。


一、原理
根据相关文献[1],我们可以知道开发者client向版本库服务器push新版本的时候,会执行$GIT_DIR/hooks/中的相关脚本。其中,在每
个ref更新之前,假如$GIT_DIR/hooks/update脚本存在,并且可执行,则会以如下方式调用这个脚本:
$GIT_DIR/hooks/update refname sha1-old sha1-new
因此,可以使用特定脚本对每个client的更新进行过滤处理,以达到控制用户权限的目的。
文献[2]也对本文使用的方案作了简要叙述。

二、适用条件
1、总是使用fast-forward[3]快速提交。例如,从不会执行'git push origin +dev:master'[3]这类命令,并且不会跨
分支提交(如将abc分支提交到xyz分支)。
2、希望控制某些用户对某些分支的更新权利。
3、希望控制标签(tags)的创建/删除,只允许特定用户更新。

三、脚本内容
将以下脚本存储为$GIT_DIR/hook/update,并确定是可执行的。

-- >8 -- 脚本开始 -- >8 --

#!/bin/bash

#file: $GIT_DIR/hooks/update

umask 002

# If you are having trouble with this access control hook script
# you can try setting this to true. It will tell you exactly
# why a user is being allowed/denied access.

verbose=false

# Default shell globbing messes things up downstream
GLOBIGNORE=*

function grant {
$verbose && echo >&2 "-Grant- $1"
echo grant
exit 0
}

function deny {
$verbose && echo >&2 "-Deny- $1"
echo deny
exit 1
}

function info {
$verbose && echo >&2 "-Info- $1"
}

# Implement generic branch and tag policies.
# - Tags should not be updated once created.
# - Branches should only be fast-forwarded unless their pattern starts with
'+'
case "$1" in
refs/tags/*)
git rev-parse --verify -q "$1" &&
deny >/dev/null "You can't overwrite an existing tag"
;;
refs/heads/*)
# No rebasing or rewinding
if expr "$2" : '0*$' >/dev/null; then
info "The branch '$1' is new..."
else
# updating -- make sure it is a fast forward
mb=$(git-merge-base "$2" "$3")
case "$mb,$2" in
"$2,$mb") info "Update is fast-forward" ;;
*) noff=y; info "This is not a fast-forward update.";;
esac
fi
;;
*)
deny >/dev/null \
"Branch is not under refs/heads or refs/tags. What are you trying to do?"
;;
esac

# Implement per-branch controls based on username
allowed_users_file=$GIT_DIR/info/allowed-users
username=$(id -u -n)
info "The user is: '$username'"

if test -f "$allowed_users_file"
then
rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
while read heads user_patterns
do
# does this rule apply to us?
head_pattern=${heads#+}
matchlen=$(expr "$1" : "${head_pattern#+}")
test "$matchlen" = ${#1} || continue

# if non-ff, $heads must be with the '+' prefix
test -n "$noff" &&
test "$head_pattern" = "$heads" && continue

info "Found matching head pattern: '$head_pattern'"
for user_pattern in $user_patterns; do
info "Checking user: '$username' against pattern: '$user_pattern'"
matchlen=$(expr "$username" : "$user_pattern")
if test "$matchlen" = "${#username}"
then
grant "Allowing user: '$username' with pattern: '$user_pattern'"
fi
done
deny "The user is not in the access list for this branch"
done
)
case "$rc" in
grant) grant >/dev/null "Granting access based on $allowed_users_file" ;;
deny) deny >/dev/null "Denying access based on $allowed_users_file" ;;
*) ;;
esac
fi

allowed_groups_file=$GIT_DIR/info/allowed-groups
groups=$(id -G -n)
info "The user belongs to the following groups:"
info "'$groups'"

if test -f "$allowed_groups_file"
then
rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
while read heads group_patterns
do
# does this rule apply to us?
head_pattern=${heads#+}
matchlen=$(expr "$1" : "${head_pattern#+}")
test "$matchlen" = ${#1} || continue

# if non-ff, $heads must be with the '+' prefix
test -n "$noff" &&
test "$head_pattern" = "$heads" && continue

info "Found matching head pattern: '$head_pattern'"
for group_pattern in $group_patterns; do
for groupname in $groups; do
info "Checking group: '$groupname' against pattern:
'$group_pattern'"
matchlen=$(expr "$groupname" : "$group_pattern")
if test "$matchlen" = "${#groupname}"
then
grant "Allowing group: '$groupname' with pattern:
'$group_pattern'"
fi
done
done
deny "None of the user's groups are in the access list for this branch"
done
)
case "$rc" in
grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;;
deny) deny >/dev/null "Denying access based on $allowed_groups_file" ;;
*) ;;
esac
fi

deny >/dev/null "There are no more rules to check. Denying access"

-- >8 -- 脚本结束 -- >8 --

四、配置文件
1、文件配置指南
这个脚本从两个文件中读取配置文件:
$GIT_DIR/info/allowed_users
$GIT_DIR/info/allowed_groups
这两个文件描述了那些用户/用户组对于分支/标签具有更新权限,并且使用相同的格式:
refs/heads/master junio jack
+refs/heads/pu junio
refs/heads/cogito$ pasky
refs/heads/bw/.* linus
refs/heads/tmp/.* .*
refs/tags/v[0-9].* junio
字符的匹配使用正则表达式规则,有多用户时请使用空格将用户名隔开。分支/标签的匹配是按顺序由上至下进行的,请确保出现交集
时,将大范围的匹配规则放置于下方。
对于如上示例,jack将能够更新'master'分支;junio能够更新'master'和'pu',并且创建相关的标签;linus则能够创建/更新
bw/abc, bw/xyz等分支;而任何人都可以创建/更新 tmp/xxx分支。
而pu分支的行首的'+'号,则代表了junio能够对pu分支进行non-fast-forward

2、系统配置指南
多数情况下,我们需要建立一个用户组(起名为 git ),并且将相关的开发者账户添加为该组成员。
当我们导出一个公共版本库后,将git目录的所有者设置为boss:git,其中'boss'是项目负责人的账户名。并且设置组用户有写权限,这
样就能够让同组的开发者对这个目录有写入/更新权利。以命令的形式来描述,则如下:
$ pwd
/home/project.git
$ cd ..
$ chown boss:git project.git -R
$ chmod g+w project.git -R


五、实例
1、配置信息
$ pwd
/home/cvs.git
$ ls -l
总计 52K
drwxrwxr-x 2 tale git 4.0K 08-12 00:03 branches/
-rw-rw-r-- 1 tale git 5 08-12 00:03 COMMIT_EDITMSG
-rw-rw-r-- 1 tale git 92 08-12 00:03 config
-rw-rw-r-- 1 tale git 73 08-12 00:03 description
-rw-rw-r-- 1 tale git 23 08-12 00:03 HEAD
drwxrwxr-x 2 tale git 4.0K 08-12 15:48 hooks/
-rw-rw-r-- 1 tale git 320 08-12 00:03 index
drwxrwxr-x 2 tale git 4.0K 08-12 15:47 info/
drwxrwxr-x 3 tale git 4.0K 08-12 00:03 logs/
drwxrwxr-x 52 tale git 4.0K 08-12 15:38 objects/
drwxrwxr-x 4 tale git 4.0K 08-12 00:03 refs/

# 确保相关的账户已经添加进git组
$ grep git /etc/group
git:x:200:tale,wang,xiao

# 确保这个脚本是本文中提供的脚本,并且具有可执行权限
$ ls -l hooks/update
-r-xrwxr-x 1 tale git 3.8K 08-12 15:48 hooks/update*

# 查看一下当前的用户权限分配
$ cat info/allowed-users
+refs/heads/wang wang tale
+refs/heads/xiao xiao
+refs/heads/tale tale xiao
+refs/heads/master tale
+refs/heads/.* tale
+refs/tags/.* tale


2、某客户端的操作
# 先看看目前是哪个用户(显然,是一个无关的用户)
$id
uid=0(root) gid=0(root) groups=0(root)

# 我们使用wang用户与服务器交流
$git clone wang@222.20.103.115:/home/cvs.git
Initialized empty Git repository in /root/cvs/.git/
wang@222.20.103.115's password:
Receiving objects: 100% (40/40), done.
remote: Counting objects: 40, done.
remote: Compressing objects: 100% (29/29), done.
remote: Total 40 (delta 9), reused 0 (delta 0)
Resolving deltas: 100% (9/9), done.

# 目前的开发进度如下:
$cd cvs/
$git show-branch -a
* [master] root 2
! [origin/HEAD] root 2
! [origin/master] root 2
! [origin/tale] Merge branch 'master' into tale
! [origin/wang] root 2
! [origin/wang2] test
------
*++ + [master] root 2
*++ + [master^] jfakfjklasjf
--- - [master~2] Merge branch 'master' into wang
*++ + [master~3] terer
*++ + [master~4] wang
- [origin/tale] Merge branch 'master' into tale
*++++ [master~2^2] 123
*++++ [master~5] ter
*+++++ [origin/wang2] test

# 从客户本人的分支上开始工作
$git checkout -b local-branch origin/wang
Branch local-branch set up to track remote branch wang from origin.
Switched to a new branch 'local-branch'
22:05:55 cvs $echo "nice to meet you" > nice
22:06:14 cvs $git add nice
22:07:02 cvs $git commit -a -m "nice to meet you"
[local-branch cd9da06] nice to meet you
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 nice

# 将工作进度提交到服务器上
$git push origin local-branch:wang
wang@222.20.103.115's password:
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 297 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To wang@222.20.103.115:/home/cvs.git
27b7142..cd9da06 local-branch -> wang

# 假如提交到别人的分支上,则会提示失败
$git push origin local-branch:wang2
wang@222.20.103.115's password:
Total 0 (delta 0), reused 0 (delta 0)
error: hooks/update exited with error code 1
error: hook declined to update refs/heads/wang2
To wang@222.20.103.115:/home/cvs.git
! [remote rejected] local-branch -> wang2 (hook declined)
error: failed to push some refs to 'wang@222.20.103.115:/home/cvs.git'

六、总结
hooks/update脚本能够提供简陋的用户控制,满足小团队的开发需求。但是,它也有一个很大的缺点:所有控制的用户均是服务器上真
实存在的用户。这会导致两个问题,其一是这些用户可能会登录服务器、并且可能会出现误操作等,造成数据损失(可以将用户的登录
shell设置为/bin/git-shell来解决);其二是随着团队规模的增大,需要在服务器上建立大量的用户。
针对以上缺点,可以使用其他的开源方案(如gitosis[4])作为解决办法。

参考:
[1]Junio C Hamano and Carl Baldwin, control access to branches.
http://www.kernel.org/pub/software/scm/git/docs/howto/update-hook-
example.txt

[2]Git 中文教程 - 管理版本库 - CVS 模式
http://www.linuxsir.org/main/doc/git/gittutorcn.htm
[3]Git manual book: git-push (1)

[4]在 Gentoo 上部署 Git + Gitosis 服务器的笔记
http://py.thonic.org/2008/05/19/git-gitosis-gentoo/

2009年8月11日星期二

祸不单行

即将离校,打算提前将学费冲进银行卡里。
可上周竟然发现常用的银行卡竟然在关键时刻给我掉磁了!于是得花两个星期补办。
昨天翻箱倒柜,找出了学费账户的存折。里面竟然干干净净,一个支取条目都没有,显然是从来就没用过。去中国银行的柜台,竟然被告知
这个存折的信息不对,账号信息无故多了几个零,需要向上级部门反映,还建议我先别往账户里存钱,免得出现问题。
可、我还得回家啊!到时候能不能在开学之前赶来学校都是个问题,这才想着把学费先存进去。。。。
呜呜,看来我得想办法尽早赶来学校了。。。
现在真的体会到什么叫做"祸不单行"了。

archlinux中的无限网卡设置(rc.conf模式)

ARCHLINUX中的无限网卡解决办法很简洁。
首先是网卡的识别问题,参考wiki即可搞定。
其次是无限网络的连接问题,使用WICD更是方便快捷。

可是,倘若我想使用手动模式,或者文本的配置模式(rc.conf),那该如何呢??
我的无线网卡识别为wlan0,网络是开放的,essid是'cap',参考wiki,则应当如下写:

wlan0="wlan0 192.168.1.222 netmask 255.255.255.0 broadcast 192.168.1.255"
wlan_wlan0="wlan0 essid cap"
INTERFACES=(eth0 wlan0)

可是重启网络,却是出现如下问题:

$ sudo /etc/rc.d/network restart
:: Stopping Network [DONE]
:: Starting Network [BUSY]
> Could not associate wlan0 - try increasing WIRELESS_TIMEOUT and check
network is WEP or has no security
SIOCADDRT: No such process
[FAIL]

经过尝试,原来是iwconfig的参数需要添加'ap auto'。于是,现在变成:

wlan0="wlan0 192.168.1.222 netmask 255.255.255.0 broadcast 192.168.1.255"
wlan_wlan0="wlan0 essid cap"
INTERFACES=(eth0 wlan0)

重启解决。


PS:
1、对于部分仍然不能解决的朋友,请再给wlan_wlan0添加参数' txpower auto'。
2、假如手动输入命令能够连接,而network脚本死活也连不上,可以尝试修改/etc/rc.d/network,
在第40行(即/usr/sbin/iwconfig $iwcfg之前),添加一句
/sbin/ifconfig $1 up

2009年6月13日星期六

设计自己的分区方案

引子
通常,由于文件系统效率问题(reiserFS适合处理巨量小文件,XFS适合处理巨量大文件)、文件安全性问题(/home目录数据绝不可丢失,其他目录则随便,反正可以重装),可能会把部分重要目录作为一个单独的分区进行管理。


前备知识
在决定将哪些目录划分为单独分区前,我们来看看根目录下各个文件夹的含义:
。。。。
其中,/bin, /sbin存储基本程序; /dev, /sys, /proc被内核使用,不是一般的文件;/lib, /usr, /opt存放绝大多数程序;/etc保存全局的程序配置;/boot 保存系统启动文件;/media, /mnt通常作为挂载点,是空目录;/var,/srv,/tmp则保存几分钟/小时就变、杂碎的文件;/root, /home则保存用户的数据。
对于个人电脑,由于不关注系统程序的稳定性(允许花上几小时重装、甚至隔几月就重装),关注点只保留在用户数据和性能上,故适合将/, /home, /var作为独立的分区配置不同的文件系统。/boot也有可能被作为一个单独的分区(适合于N个liunx发行版共存的情况);/etc也可以作为一个独立分区,以便重装时方便恢复配置。以我个人为例,我将/, /boot, /home, /var作为了独立的分区。


文件系统类型
让我们来确定各个分区的文件系统类型。
对于/boot,考虑到你的系统引导程序需要能够支持并读取这个分区的数据,并却/boot目录的内容常常是几个星期才变动一次,可以ext2/ext3,注意的是,grub目前(2009/6/10)尚未有支持ext4的版本,故不推荐使用ext4文件系统。
对于/var,考虑到里面的数据会剧烈变动(大量的I/O操作),并且多数为巨量的小文件,故reiserFS最适合作为这个分区文件系统类型。
对于/home,考虑的这些数据文件大小均有,且随意性较大(既有不少几K的文本,也有不少几G的电影),故而不适合使用reiserFS和XFS这些为处理巨量特定大小文件而设计的文件系统,采用通常一些的ext3,ext4等均可。注意避免使用不带日志的文件系统类型(如ext2),否则不小心断电你就哭去吧!
对于根目录/,如果你不把/boot独立作一个分区,那么就得额外考虑系统引导的问题,避免使用ext4等文件系统类型;除此以外,尽量使用XFS文件系统,因为根目录的文件通常不大(没有达到百M级别),XFS没有优势;最后,请根据个人的喜好而选择文件系统类型。


分区大小
确定了目录-分区方案后,来着手研究各个目录(即将来的各个分区)的分配空间大小,以达到空间利用最大效率。
倘若系统已经是独立分区的情况了,使用df命令来快速了解各目录使用情况:
20:08:52 ~ $df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/sda1 9.2G 6.3G 2.5G 72% /
none 1004M 0 1004M 0% /dev/shm
/dev/sda5 1.2G 36M 1.1G 4% /boot
/dev/sda6 3.0G 1.2G 1.8G 40% /var
/dev/sda7 178G 125G 44G 75% /home
如果系统依然是一个分区作为整个系统分区,使用du来统计文件夹的占用大小(记得使用root权限):
20:28:34 / # du --max-depth=1 -h
34M ./boot
5.4G ./usr
8.1M ./etc
5.5M ./bin
15M ./sbin
443M ./opt
1.2G ./var
125G ./home
132G .
(省掉了一些无关目录的大小信息)
注意我的系统已经是使用了许久的日常工作系统,该装的软件都已经装了,各个文件夹大小已经达到了其目标值。故,在此例子中,我可以使用这些值作为参考,设计出我的分区方案。
对于/boot,实际使用了34M,考虑我以后安装其他系统,将这个值提高至10倍(依然还很小,呵呵),故使用340M分区大小。
对于/var,实际使用了1.2G, 增加50%作为备用(空闲的文件系统通常较快),取整,故分配2G。
对于根目录/,主要是/usr目录占用得太多,约5.4G,增加50%作为备用(考虑到以后可能还要装其他大型程序如OpenOffice),故分配8G。
剩下的空间全部分给/home。


结论
故,在我这个空间月190G的系统中,最终的分配结果如下:
目录 大小 类型 备注
/ 8G ext4 为了尝鲜
/boot 340M ext3 为了能让根目录使用EXT4分区,故将/boot独立出来
/home 180G ext3 历史遗留问题,以前就是这个文件系统
/var 2G reiserFS 处理巨量小文件有极大优势


对于一个40G的系统,则可以使用如下的分配方案:
目录 大小 类型 备注
/ 7G ext4 依然要考虑安装巨型程序的问题
/boot 340M ext3 为了能让根目录使用EXT4分区,故将/boot独立出来
/home 31G ext3 历史遗留问题,以前就是这个文件系统
/var 1.5G reiserFS 常常清理的话,/var目录的空间也能剩一些


其他
对于那些极端个性化(比如全能型系统(KDE,GNOME一并装)、精简性系统(连XORG也没有)),只能参考以上的思路自己慢慢设计分区方案了。


参考
Linux各种文件系统(ext3,ReiserFS,jfs,xfs)的性能
http://hi.baidu.com/xuzhi1977/blog/item/c5869758dfafbade9d82040a.html


2009年5月22日星期五

一个简单C单元测试脚本

花絮
今天打算动手重写mystar。于是看了一会儿代码,决定先改写readConfigFromFile函数。于是花了若干时间,写了170行左右代码。恰好前一段时间
看《修改代码的艺术》时,学会了不少单元测试的方法,于是打算拿刚写的这些代码试试手(这些代码的独立性很高,正适合单元测试)。然后又是一番捣鼓,手动写了一个测试
程序。有捣鼓了一个晚上,写了一个自动单元测试脚本UnitTest,命名为ut。
先来看看我的情况吧:


代码略例
刚写了的代码中包含两个文件,分别是option.h和option.c,部分内容如下:
//option.h
#ifndef OPTION_H
#define OPTION_H
extern char * strip(char * str);
extern char * strlow(char * str);
//。。。。此处省略一堆代码

一个简单C单元测试脚本

花絮
今天打算动手重写mystar。于是看了一会儿代码,决定先改写readConfigFromFile函数。于是花了若干时间,写了170行左右代码。恰好前一段时间看《修改代码的艺术》时,学会了不少单元测试的方法,于是打算拿刚写的这些代码试试手(这些代码的独立性很高,正适合单元测试)。然后又是一番捣鼓,手动写了一个测试程序。有捣鼓了一个晚上,写了一个自动单元测试脚本UnitTest,命名为ut。
先来看看我的情况吧:


代码略例
刚写了的代码中包含两个文件,分别是option.h和option.c,部分内容如下:
//option.h
#ifndef OPTION_H
#define OPTION_H
extern char * strip(char * str);
extern char * strlow(char * str);
//。。。。此处省略一堆代码

2009年5月2日星期六

影评《Eternal Sunshine of the Spotless Mind》:那些旧时光,都是花儿

  昨晚恰在白云黄鹤上看到了一篇文章,记下了她记忆中与他之间琐碎又零星的故事回忆。纵使已经逝去5年,两人已天南海北,可是那些旧时光,却都是花儿。
  恰巧今天观看这部电影,视角切换到了男方,可依然是那些回忆起来无比普通细碎却让人不忍忘却的故事。于是把她的文章题目拿于此作为此评论的题目。
  
  原本看到这部电影的名字《美丽心灵的永恒阳光》时,我并没有想到它会是一部会让人感怀忧伤的片子。那个让我误以为是阳光激励片的名字随着电影的开幕、Joel的轻声喘息而不复存在。故事于是在Joel的轻声述说中,在一个阴沉的冬季、在情人节的这天开始。
  
  说实话,直到倒叙Joel的清除记忆经历开始了一段后,我才弄清故事的叙述方式(想起了《记忆碎片》那种诡异的叙事风格)。Joel这个忧郁内向沉稳的帅哥,突发奇想去Montauk,然后在反省自我的光棍生活时碰见了一个身穿桔黄的女子Clem。Clem异常纯朴好动且仿佛不受浊世俗规的约束,敢想敢做地跟Joel聊起了天,直抒胸臆说不喜欢Joel只会用Nice来形容,甚至直接了当地说"I'm gonna marry you。"可把Joel这个遇事习惯掩藏在本子和画本中的孩子吓呆了(我也是)。仿佛一见钟情,他们如相恋多年般迅速熟悉起来。
  
  可实际上,他们确实相恋多年。
  
  镜头的突然切换,出现在我们面前的却是Joel那张纯净的脸,可清澈的眼睛却是强忍着才不会被泪水溢出来。Joel慌乱、不安,让刚刚营造的美好气氛顿时消散,镜头里的明媚阳关已经变作黑夜里的丝丝细雨。发生了什么事?无数人询问。原来已经进入了故事的倒序,开始讲述Clem因为与Joel拌嘴而冲动地去了"忘情诊所"消除记忆,Joel无法接受Clem对他做出的形如陌人的样子,痛苦挣扎中也决定去"忘情诊所"消除记忆。可当Joel开始进行清除时,才蓦然发新,那些曾经,那些旧时光,都是花儿。
  我还记得,那次在市场时你说喜欢小孩,我担心你没准备好做妈妈,我们因此拌嘴;
  我还记得,那次我们温馨地躺在床上,你说希望更加了解我,喜欢和我多说话,让我别孤僻,要更加intimacy;
  我还记得,那次我们在中餐馆,我都已经能够说出你的骂人口头禅了,可我依然喜欢你安静吃饭的样子,喜欢帮你捋起那不安分的发丝;
  我还记得,那次你穿着橙色的运动服,仿佛一个熟透的橘子,于是"柑橘"成了你的昵称;
  我还记得,你说你小时候很怕别人说你丑,还给一个洋娃娃起名叫Clem,总希望她变得漂亮;
  我还记得,我们曾并肩躺在结冰的查尔斯河上,天气很冷,但我却想要就此永远和你躺下去;
  我还记得,我们曾在海边的雪地里玩耍,身上全是细碎的雪花,涛涛浪声也无法淹没你的欢声笑语;
  我还记得,我们第一次相见,就在海边聚会时,你主动过来"搭讪",我们从此相识。
  
  无数细碎珍贵的回忆,如粒粒珍珠般晶莹动人,一如你Clem变幻的发型,不定的发色,散射这七彩的光芒。Joel不愿忘却,但却无可奈何。
  于是花儿凋谢,旧时光烟消云散。
  
  然而深深相爱的两个人不会因此就分开的,冥冥中他们还记念着对方,还会去以前常去的地方,等待着另一个人。这又让我想起了Joel追求Clem时的对话话——
  Clem:I had you pegged, didn't I?(我让你记住我了吧?)
  Joel: You had the whole human race pegged.(你让全人类都记住你了。)
  
  于是这句话终究会如一句魔咒,引领这Joel和Clem重新走在一起。
  

2009年4月23日星期四

一个小发现:Flecsh阅读易度指数

在Kword写选修课的论文时,突然发现了有这样一个统计指数。其结果是120。好奇,于是google之,在wikipedia上
得知这是一个专门判断E文文章可读性的指数,简单的分级如下:
90.0–100.0 easily understandable by an average 11-year old student
60.0–70.0 easily understandable by 13- to 15-year old students
0.0–30.0 best understood by college graduates
虽然我的论文写的是中文,倘若这个指数有效,那么我的文章大约连小学生读起来都津津有味了吧。。。嘿嘿

2009年3月28日星期六

影评《情书》:永不失去的年少爱恋

  《情书》主要讲述的是博子与藤井MM之间的事。往复不停的信件逐渐勾勒出了藤井GG的形象。被恶搞时的愤怒,
出车祸后的不屈,窗前读书时的沉静,两人独处时的温馨。博子与藤井MM的形象都是有大段的剧情来描述的,慢慢而
清晰;可是作为两个人不断讨论的藤井GG虽有剧份,确少有言语。大约视角是从两位女方出发的,无论是心里那个男生
的话也许已不清晰,抑或是恋爱的男生总是涩于言语,但那些唯美的场景、无法言明的表情却已刻入心里。
  博子的羞涩与淑静,与中学时代的藤井MM如出一辙。单纯的中学时光让两个因为同名而苦恼的藤井渐渐走到了一
起。虽是不情愿地一起在图书馆工作,但充满书香的静谧的图书室却成为了两个学生情愫暗生的温床。最记那穿着蓝色
校服的男生,倚靠在明媚的窗台前静静看书,脸庞似带着微笑,又似发着淡淡的光,让恰巧抬头望见的少女一阵失神。
翻飞的白色窗帘不停飘动,男生的身影若影若现,似乎一眨眼他就会消失于阳关之中。我想当时的藤井MM肯定是动心
了。她望了一阵后觉很很满足很温馨,才悄悄地偏下头继续整理书籍。
  还有一个场景也是让我难以忘怀。那是藤井MM发现卷子发错了,在车棚里呆呆的等了一个下午,然后藤井GG与她
夜下幽会。说成幽会可能大家不赞同,不过从藤井GG的角度来看,却会发现:他之所以要在黑漆漆的车棚对答案,之所
以对她的抱怨微笑不理,实际上确实为了能让自己找到借口与她独处(尤其是这样夜黑风高百分百每人抓到说闲话的时
候),为了能够和她多说说话(平时不是自己紧张、就是她太淑静,唉)。少年的心思总是简单的,甚至有点可笑;然
而一张薄薄的卷子确画下了那时少年眼中美丽的她。
  可惜自始自终,他却依然不敢直接说出那些话。甚至于再后来爱上了博子、想永远与博子在一起时,手里捧着戒指
确依旧不敢说一个字。仿佛,那些字句是魔咒,需要莫大的勇气;仿佛,那些字句是禁语,你的一个"不"字,就会让明
媚的阳关从此消弥。幸好最后博子忍不住了,反而逼婚了(笑)。。。
  藤井树GG的形象就是由这些支离破碎的回忆拼起来的。然而他的言行却是现实中的中学男生(当年)的缩影。两人
独处时就会不知说什么好,只好问问今天学了什么方程;会在借书卡上不断写上你的名字,让你看见却又掩耳盗铃般说
不是你想的那样;问到有没有女朋友时,会心里狂跳强自镇定冷漠地说"没有",在你出乎意料过来当月老牵红线时怒火
突生;把各种不敢说的话画下来,夹在被评为"没人看"的《追忆似水流年》中。所以若干年后藤井MM发现这封独特的
《情书》时只能不知所措、无可奈何。。。
  记得《此间的少年》中,乔峰的从康敏处得到的英语书里夹着一张书签,背面有着娟秀字迹的六个大字——"大猪头
大猪头"。也许藤井MM最后想说的就是这六个字吧。
  猪头!猪头。曾经暗生情愫却不敢表达的少男少女们,都是大猪头。

2009年3月16日星期一

答某同学信兼小评笔记本gateway(捷威)

【 在 HUSTIE 的来信中提到: 】
: 同学,问一下,买gateway整体感觉怎么样啊
:
: 我想买这个牌子的 啊
:

我的本本是T-6834C,我只能针对我这部本本来品论。。。

感觉很不错。整机的稳定性很好,(好像)从没出现过蓝屏之类的崩溃;显卡是ATI raedon 2400 xt, 不过确是DDR3的
显存,不像别的厂商那样缩水,玩游戏的效果很好(可惜我不怎么玩游戏);外围设备完备,蓝牙、无线、SD卡,电视
接口都有。唯一缺点可能是不够轻(但也不算重)。

特别说说散热问题。据说Gateway多数机子是红铜散热,我这款机主要是CPU比较强,而且我也是经常运行巨耗CPU的程
序,常常CPU占用100%。不过也没出现烫手之类的问题,只是左手托盘处(里面是硬盘)感觉温热。比不起Think Pad
之类的冰冷感觉,不过依然不错。只是不知道到了夏天会怎么样。

前几天上gateway的坛子(http://bbs.gatewayfans.com/),发现他们在探讨雪花屏时间(也不清楚是什么时候的帖
子,不太注意),反正我的屏幕是很好的,所以就不在意。如果你购买,希望你了解一下这方面情况。

总结一下,gateway还是值得购买的。

PS:我的机子是去年年底12月买的,在广埠屯的银嘉花了近6000大洋,回来google发现,竟然有人以5500大洋买到手,
真是XXXXX。。。。不过也安慰自己,至少不算亏,价格适中吧。。。如果你买,多砍砍!

2009年3月1日星期日

google的一个翻译机器人真有意思

18:35:01

我爱你爱的所有东西
18:35:11
zh2en@bot.talk.google.com
I hate you love all things

2009年2月28日星期六

64位好!KDE4更稳定了。。。




Archlinux,前天刚装的。
笔记本Gateway T6834-c, CPU=T8100,MEM=2G,ATI RADEON 2400
-----------
话说当时小试了一下EXT4,结果initrd镜像中竟然不包含ext4驱动,结果辛苦把文件cp出来(我当时咋不用tar呢?后
悔),不慎出错,然后赶忙rm。。。结果上G的数据(不包含10+G的iso,歌曲之类的)毁于一旦。。。连ext3grep也只能
找回几个文件。。。唉
-----------
今天仔细体验了一把X86_64系统之优。(多数配置文件直接从i686系统cp过来,没仔细调整,仅供列位看官参考)
kernel的启动不必多说,速度没啥加快(我还自定义了一番initrd镜像,加入了usb,结果每次都要等待usb设备
settle。。。,慢不可言!);
启动服务但是大大减速了,尤其以Udev,smartd,hal为最,失去了archlinux轻巧、快速的特点。。。
桌面系统我用的是KDE4.2。
启动5部曲中,依然是第一个图标(小硬盘图标)出现后特慢,等了6s。。。?(万恶的configUpdate,急寻把它禁掉之
方法)其次是最后一个图标(K图标)出现后又是一番苦等,可能等了10s。。。




也许X64_64系统唯一令我欣慰的是,KDE4运行的稳定性加强了。这其中也许有编译参数的作用吧?还没尝试过编译这
种大型软件,不了解。截图请看:
第一个4宫格桌面的是刚打开opera,CPU占用突发提升(右下角的CPU检测表)。之前已经打开了N个程
序,PDFx2,dolphin,kwrite,kmail,amule,konsole,kwrite,CPU占用一直在10%左右。以前常见的因特效而CPU隔半
小时激增一次的现象也没有了。。。
第二个是我正在写这篇帖子的截图。CPU占用也很稳定,Opera这个吃CPU大户的出现让CPU占用稳定到了40%。为什么
我这么强调"稳定"?估计各位很少体验到CPU占用率不时激增然后系统暴卡、来来回回折腾你每天10几次,人生就特别郁
闷了。。。




关于x86_64系统,现在大约还不算主流吧?软件的移植(或者编译)是个问题。在我的Archlinux发行版
上,wine,virtualbox等软件都还没有x86_64的官方包。另外,对于32位程序的兼容性方面,静态编译的程序(如
mystar)自然是没问题,其他的动态链接版就不怎么和谐了。。。




总的来说,一切都在不断完善,64位必然是主流(不太可能直接跳到128位吧?呵呵),值得推荐。。。




http://byhh.net/f/Linux/1235788894/stable.jpeg
http://byhh.net/f/Linux/1235788966/with_opera.jpeg


2009年2月27日星期五

再次奋战 Amule

其实也不是什么大作战了。

似乎在上一年的时候,曾经花了很长时间捣鼓Amule,试图解决其各种稀奇古怪的问题。

首当其冲的就是ed2k链接的关联问题。

乍一看,似乎这也不是什么问题。因为有一个叫/usr/bin/ed2k的程序在那里等着,只要执行以下命令即可
$/usr/bined2k ED2K-URL
然而,如果执行以下的命令,则会提示错误:
所犯的

[tale@Lystem ~]$ ed2k ed2k://|file|[米尔克].Milk.REPACK.DVDSCR.XviD-BiGFAGS.cd1.avi|734877696|49b8792774052f0a7291f26cc8c7bce1|/
bash: [米尔克].Milk.REPACK.DVDSCR.XviD-BiGFAGS.cd1.avi: command not found
bash: 734877696: command not found
bash: 49b8792774052f0a7291f26cc8c7bce1: command not found
bash: /: is a directory
Usage: file [-bcikLhnNrsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] file...
file -C -m magicfiles
Try `file --help' for more information.
Bad parameter value:
ed2k://

不要以为是/usr/bin/ed2k程序的问题。这其实是Shell环境的问题(由其中的bash提示之错误可发现这一点)。给参数加上双引号,防止shell对斜杠之类的符号进行转义,我们可发现:

[tale@Lystem ~]$ ed2k "ed2k://|file|[米尔克].Milk.REPACK.DVDSCR.XviD-BiGFAGS.cd1.avi|734877696|49b8792774052f0a7291f26cc8c7bce1|/"
Link successfully queued.

此时,我的amule上也提示新加了相应的下载。可见,ed2k的调用其实很简单。(对比M$下的迅雷链接,唉。。。)
不过,要在opera中关联ed2k链接,却是有小波折。修改工具->首选项->高级->程序,可以为ed2k链接添加一个外部处理程序。如果直接填上/usr/bin/ed2k,确是会让amule添加包含乱码中文的下载。联系到刚才shell对特殊字符的转义,你是否想到问题的关键之处?
如果你认为问题出现于参数(即要下载的ed2k链接)的传递处理,那么你就落入窠臼了。实际情况确是,opera传递的参数的编码问题出现了异常。选择 工具->首选项->高级->国际,取消"用UTF-8给国际语言编址"。此时,程序关联依然填写/usr/bin/ed2k,点击一个ed2k的下载链接试试,成功!

第二个问题是,amule与KDE4桌面的兼容问题。


我已经不知道发生了多少次,amule在我点击系统托盘的时候狂闪。注意,不是那个小小图标闪,而是整个程序界面闪,进而造成我的桌面的闪。有时候等个1分钟,能正常下来;多数情况是,我无法忍受,于是捣鼓命令,kill掉它。
现在,我已经采用WEB界面来管理amule。
具体设置我不再叙述,只是在设置里面启动远程web管理而已。
然后,给系统增加一个自动运行


amuled -f


哈哈,opera中就可以看到了!


此刻起,世界和谐了。。。

2009年2月12日星期四

听说2.14情人节前夕征女友很容易

也不知是不是如此。

可惜也没胆试。hoho

--
有约不来过夜半,闲敲棋子落灯花。

2009年2月1日星期日

购买了一款国产共享软件,也算为中国的软件事业做贡献!

名字叫做"易通电脑锁",除了有一些不太完善,一些BUG外,很满意。。。
 

--
有约不来过夜半,闲敲棋子落灯花。

2009年1月31日星期六

也算一个热闹年

其实就这20多天的假期之所作所为来看,;今年的寒假绝对算是一个"宅"得非常的假期。每天睡了吃,吃了看书(手机上的小说,唉),看完又睡。因为没有特别担心的事情,期末的考试结果也查强人意。人懒了,于是就宅。

今天是年初五,算一算这五天其实有三天是在家里呆着。真的是寂寞的很。

不过昨天,安琪他们力邀我们聚会,中午匆匆忙忙在东静家蹭完饭(其实我出门前已经除了一些了),谁知道下午两点到达安琪处他们竟然还没有开始饭局。。。于是又得吃。。。

10多个老同学,四个是女的,除了安琪外,都是待字闺中。而安琪,去年找到了如意郎君,国庆时节隆重举行的婚礼(许多同学朋友去了,我没去,可惜),没想到今年已经生了一个大胖小子!小屁男似乎才6个月,脸异常的园,与他老爸很相像。名字似乎是叫德礼,教他喊我叔叔,可惜教不会。。。

大概一直晃悠到4点吧,才各自分别。伟龙跟着我,想去我那里上网下载他追捧依旧的电台节目"一些事一些情"。

回到家还没开始,宇科竟来了。无奈,伟龙只好悻悻关掉才登陆的系统,跟着我们几个去四处召集人手,呼啸赶往宇科处聚聚。

提一下,宇科家的小子似乎比安琪的乖宝宝大半年,去年聚会的时候慧惠同学就已经挺着大肚子了。小孩子疑惑地看着我们打扑克,而我,神秘而伟大的人物,在四人信牌赛中比分一再创新高,引领时代潮流!(其实分数高代表这输的厉害,不过偶是故意的)。晚饭时大伙又拼酒,不必多言。

回来的时候天很黑,四处都很宁静。夜空很晴朗,星星很亮。忽然感觉这样的日子挺安心的。

PS:贴一张王哥的帅照,初六去他家蹭饭。。。


--
有约不来过夜半,闲敲棋子落灯花。

2009年1月29日星期四

Re: 与 wo@jiwai.de 聊天

今天转战四五处,拼杀啤酒无数