Archive: ‘programming’ Category

工作为了什么

13 comments November 27th, 2010

我承认我是一个低俗的人,我像别人一样的高考,像别人一样的为了保研而争取拿那些没有嚼头的高分,像别人一样想着挣钱了买好车买房子娶漂亮极品的媳妇,当然也像别人一样拼命工作,因为我们的低俗导致了我们为了低俗的事做了更低俗的事。
我要解释一下,因为我表达能力有限,有时候多多少少在这字里行间中会使得很多人理解有所偏差,所以我得解释。我说的这个工作是指潜意识不喜欢做或者是!喜欢做的事情,之所以做这个工作不是你愿意的,不是你想做的,不是你内心中的那种可以为工作废寝忘食却依然享受在乐趣之中的工作,可能你之所以做这种工作是迫于生计,迫于压力,迫于各种舆论,总之你会有你的理由和苦衷,但是你永远不会有”歇斯底里”的快乐。(在我这,hysteria是褒义的,多少人能有这种疯狂的感觉呢)。
前阵子和板牛聊过一些关于毕业、工作之类的事情,我个人感觉现在很多大学生的思维模式和想法都是惊人的相似的,“工作两年,然后跳个巢,或者咱可以自己出去创业、单干呗”,这正常么?这tm太正常不过了,不这么想的我跟你说,你八成是有问题的,因为不这么想的就两种人:“牛逼”的和“傻逼”的;牛逼人会坚持自己的理想,任评风吹雨打,“我愿化身石桥,任伍佰年风吹雨打……”,这种人我只能说超然于外,笑看潮起潮落,而心如止水;另一类人就不用说啥了,混一辈子不知道自己干啥,不知道自己想干啥,不知道应该干啥,得了,这种人我只能说白瞎了,那么多粮食。
罗里罗唆这么多话,其实我就想知道我们的工作为了什么,还没有走入工作岗位的各位大神,想想你以后工作为了什么,正在工作前线的同胞们,想想你现在工作为了什么,毕竟人不能不问一己良知、不问一己私欲而昏昏度日,那样与猪狗又有何分别。
print '-' x 80 if you could intepret perl :D
前几日用G1的时候,发现G1这个键盘真是有点不爽,没有tab键啊!输入个命令费死劲了,所以就想:连个外置键盘吧,这多爽啊,打字速度飞一般的感觉。对面坐着小龙同学马上给我泼了盆冷水“插上不能用吧,你得有驱动啊”,我里个擦,我又傻逼了,把这个最基本的都忘了。没搞过kernel & driver,这可让我咋整。。。
然后,我就去看看有没有人干过这事啊,其实不用想也知道肯定有人这么想过,谁?那群geeks呗。由于我朝的GFW,导致很多的资源不能及时的更新,所以google出来的链接几乎都被盾掉,当然你得先能google再说,强大的GFW还能检测到你关键字是不是敏感的,orz……让我们这搞nlp的人情何以堪,你丫这么牛逼怎么不能干点正事。(baidu? 百度的结果你应该晓得,在国内摆渡拉的客,基本上都是自己人。)
所以我只能找个梯子,爬到墙上,跳出去;院子里的出了烂的食物还有什么能吃的呢?我本以为我是个良民,但是当我意识到做久了良民就会变成愚民的时候,我决定做个“伪良民”,肉体上我们可以且应当服从党国,至少精神上我们应该是自由的。
然后,我又一次上了twitter,然后发现了所谓微博这个东西还真是浪费时间的东西,可能我们都太“孤独了“,只能在这个东西上寻找精神的慰藉,或者我们的“暴露癖”太严重了。在不会分散注意力影响其他事情的情况下,这个东西还是不错的,个人感受。
捅咕了一周,我的G1能识别外置键盘外置硬盘了,但是我不会access……然后知道了android & debian in G1 together这么个东西,后来发现我的1G micro sd card显然是不够用的;算下来鼓捣这1周花了100多rmb了,既然通货膨胀了,钱就不是钱了,为何不花呢。
要是我能使外置键盘在我的G1上work了,我想我会写个总结性的东西,毕竟一路走来不容易。
我比较喜欢天国王朝里巴里安说的一句话,送给大家:”大丈夫,当造福苍生“。

记下最近二三事

5 comments November 16th, 2010

从后往前说吧。
刚刚发现.subversion/config中~是不能被解析成/home/xxx/的,原来配置svn好使总是有警告说xxx文件找不到,没在意;现在才知道确实是找不到啊,原来能连接是因为我的private key都放在.ssh/下,ssh自己会搜索这个路径下的key,所以说呢,我又犯了一次2。
也是刚才,发现我的adsense中Page impressions总共才4000多,收入$2.5…曾几何时我还梦想着收回成本呢。
再之前的这两天,断断续续的改程序,跑程序,体会就是无论多么小的系统,设计都是很重要的;
我的程序功能很简单,弄一堆候选词,抓网页,看这些词是不是在网络词典里出现;
最开始设计成了碎文件的存储,总是担心要是文件系统的node用光了怎么办,没实际算过。。。所以又改成数据库方式存储,这么干缺点是太慢了,数据规模变大了,数据库存取很慢;最后又改成了碎文件存储。。。而且我还要寄希望于这些个“词典”不要“屏蔽”我,毕竟慢慢的用代理偷偷摸摸抓也是抓,明目张胆赤裸裸的疯狂抓也是抓。
另外一点,我的感悟就是代码与数据的分离也是很重要的;
版本控制也是重要的,一个好的习惯是:checkout -> commit…checkout -> commit. 而我的做法是copy -> edit…copy -> edit。
最往前几天,帮助锋哥写了些hash函数,测试这些函数的优劣。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
u_int elfHash(const char *str) {
	u_int code = 0;
	u_int ans = 0;
 
	while(*str) {
		code = (code<<4) + (*str++);
		if((ans = (code & 0xf0000000)) != 0) {
			code ^= (ans >> 24);
			code ^= ans;
		}
	}
	return code & 0x7fffffff;
}
u_int nrHash(const char *str) {
	u_int code = 0;
	while(*str) {
		code *= 16777619;
		code ^= (u_int) *(unsigned char*)str;
		++str;
	}
	return code;
}
u_int stlHash(const char *str) {
	/*
	inline size_t __stl_hash_string(const char* __s)
	{
	  unsigned long __h = 0; 
	  for ( ; *__s; ++__s)
		__h = 5*__h + *__s;
 
	  return size_t(__h);
	}
	*/
	return __stl_hash_string(str);
}

实际上这些hash函数都差不多,其思想也是相似的;我的实践经验发现:模数底M对结果影响很大,M取得很大与很小hash效果都不好;最后比较好的结果是M取8-10w之间的素数。我猜测sgi的hash_set有可能也是这么干的。
再往前几天,hbx同学某天晚上说我怎么变高了,我倒是希望变高,不过这是不可能的,我都什么岁数的人了,要是还能长,那么500w也离我不远了。
再之前几天,我实在想不起来具体都干什么了,就记着写程序了。有一天随便看了看一本什么数据存储查询的书,书上介绍了huffman编码压缩,算术编码压缩方法;就想起来曾经在acmClub时候,最开始就是学的这个,呵呵,真怀念啊。然后,花了点时间写了个压缩解压缩的程序,虽然压缩比很差,但是思路还是很清晰的;btw: wordpress添加downloads真麻烦,而且中文编码也有问题。
回想这些天,除了写写代码,配置这个那个,还真没干什么了。也许,所谓的什么个性化推荐才是我们应该走的道路,毕竟我们还是所谓的研究生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <queue>
#include <cassert>
#include <cstring>
 
using namespace std;
typedef unsigned int u_int;
struct Node {
	char key;
	u_int freq;
	Node *self;
	Node *left, *right;
	Node() { left = right = 0; key = 0; self = this;}
	bool operator<(const Node & _n) const {
		return freq > _n.freq ? true : freq < _n.freq ? false : key < _n.key ? true : false;
	}
};
const u_int BLOCK_SIZE = 1024;
class Huffman {
	public:
		Node *buildTree() {
			priority_queue<Node> Q;
			u_int num = 0;
			for(u_int i = 0; i < 256; ++i) {
				if(counter[i] == 0) continue;
				Node *ans = new Node();
				ans->key = i, ans->freq = counter[i], ans->self = ans;
				//fprintf(stderr, "%d - %d\n", ans->key, ans->freq);
				Q.push(*ans);
				++num;
			}
			for(int i = 1; i < num; ++i) {
				assert(!Q.empty());
				Node first = Q.top(); Q.pop();
				assert(!Q.empty());
				Node second = Q.top(); Q.pop();
				//fprintf(stderr, "(%d - %d)\n", first.freq, second.freq);
				Node *ans = new Node();
				ans->left = first.self, ans->right = second.self;
				ans->freq = first.freq + second.freq;
				Q.push(*ans);
			}
			assert(!Q.empty());
			return Q.top().self;
		}
		void trace(char *_code, u_int depth, const Node * _node) {
			if(_node->left == NULL && _node->right == NULL) {
				fprintf(stderr, "key: %d\tdepth: %d\tcode: ", _node->key, depth);
				for(int i = 0; i < depth; i++)
					fprintf(stderr, "%d", *(_code - depth + i));
				fprintf(stderr, "\n");
				return;
			}
			if(_node->left) {
				//fprintf(stderr, "(");
				*_code = 0;
				trace(_code+1, depth + 1, _node->left);
				*_code = 2;
			}
			if(_node->right) {
				*_code = 1;
				trace(_code+1, depth+1, _node->right);
				*_code = 2;
				//fprintf(stderr, ")");
			}
		}
		void readFile(const char *file) {
			FILE *fin = fopen(file, "rb");
			if(fin== NULL) {
				fprintf(stderr, "fopen fail.\n");
				exit(-1);
			}
			char str[BLOCK_SIZE];
			u_int n;
			memset(counter, 0, sizeof(counter));
			while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) 
				for(u_int i = 0; i < n; ++i) counter[(int)str[i]]++;
			//for(int i = 0; i < 256; ++i) fprintf(stderr, "counter[%d]: %d\n", i, counter[i]);
			fclose(fin);
		}
		void compress(const char *file, const char *outFile) {
			readFile(file);
			Node *root = buildTree();
			char _code[256];
			//trace(_code, 0, root);
			encode(_code, 0, root);
			writeFile(file, outFile);
		}
		void i2ch(u_int n, char *str) {
 
			for(int i = 0; i < 4; ++i) {
				*(str+i) = 0xff & (n >> ((3-i)*8));
			}
		}
		void writeFile(const char *file, const char *com) {
			FILE *fin = fopen(file, "rb");
			FILE *fout = fopen(com, "wb");
			if(fin== NULL || fout == NULL) {
				fprintf(stderr, "fopen fail.\n");
				exit(-1);
			}
			u_int num = 0;
			for(int i = 0; i < 256; ++i) if(counter[i] > 0) num++;
			char ntr[8] = {0};
			i2ch(num, ntr);
			//fprintf(stderr, "num : %d-%d-%d-%d  - %u \n", ntr[0], ntr[1], ntr[2], ntr[3], num);
			if(fwrite(ntr, sizeof(char), 4, fout) < 4) {
					fprintf(stderr, "fwrite 4 error.\n");
					exit(-1);
				}
 
			for(int i = 0; i < 256; ++i) {
				if(counter[i] == 0) continue;
				char ttr[8] = {0};
				ttr[0] = i; 
				i2ch(counter[i], ttr+1);
				if(fwrite(ttr, sizeof(char), 5, fout) < 5) {
					fprintf(stderr, "fwrite 5 error.\n");
					exit(-1);
				}
			}
			char str[BLOCK_SIZE];
			char ctr[BLOCK_SIZE];
			memset(ctr, 0, sizeof(ctr));
			u_int n, ex = 0;
			int ix = 7;
			while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) {
				for(u_int i = 0; i < n; ++i) {
					for(int j = 0; j < mask[str[i]]; ++j) {
						if(code[str[i]][j] == 1)
						ctr[ex] = ctr[ex] | (1<<ix);
						ix--;
						if(ix < 0) ex++, ix = 7;
						if(ex == BLOCK_SIZE) {
							//写入文件
							if(fwrite(ctr, sizeof(char), ex, fout) < ex) {
								fprintf(stderr, "fwrite error.\n");
								exit(-1);
							}
							memset(ctr, 0, sizeof(ctr));
							ex = 0, ix = 7;
						}
 
					}
				}
			}
			//fprintf(stderr, "write in to compress ex %d\n", ex);
			if(fwrite(ctr, sizeof(char), ex, fout) < ex) {
				fprintf(stderr, "fwrite error.\n");
				exit(-1);
			}
			fclose(fin);
			fclose(fout);
		}
		void binaryPrint(char n) {
		 	for(int i = 7; i >= 0; --i)
				fprintf(stderr, "%d", ((1<<i) & (0x000000ff & n)) ? 1 : 0);
		}
		//_code : 0, _mask : 0
		void encode(char *_code, char _mask, const Node *node) {
			if(node->left == NULL && node->right == NULL) {
				for(int i = 0; i < _mask; ++i) {
					code[node->key][i] = *(_code-_mask+i);
				}
				mask[node->key] = _mask;
				return ;
			}
			if(node->left) {
				*_code = 0;
				encode(_code+1, _mask+1, node->left);
			}
			if(node->right) {
				*_code = 1;
				encode(_code+1, _mask+1, node->right);
			}
		}
 
		void decompress(const char *file, const char *outFile) {
			FILE *fin = fopen(file, "rb");
			FILE *fout = fopen(outFile, "wb");
			if(fin == NULL || fout == NULL) {
				fprintf(stderr, "fopen fail.\n");
				exit(-1);
			}
			char str[BLOCK_SIZE] = {0};
			memset(counter, 0, sizeof(counter));
			if(fread(str, sizeof(char), 4, fin) < 4) {
				fprintf(stderr, "fread first 4 char fail.\n");
				exit(-1);
			}
			u_int n = ch2i(str);
			//fprintf(stderr, "n : %d-%d-%d-%d  - %u \n", str[0], str[1], str[2], str[3], n);
			for(u_int i = 0; i < n; ++i) {
				if(fread(str, sizeof(char), 5, fin) < 5) {
					fprintf(stderr, "fread 5-group fail.\n");
					exit(-1);
				}
				counter[(int)str[0]] = ch2i(str+1);
			}
			Node *root = buildTree();
			Node *ans = root;
			char _code[256];
			//trace(_code, 0, ans);
			u_int ix = 0;
			char ctr[BLOCK_SIZE];
 
			while((n = fread(str, sizeof(char), BLOCK_SIZE, fin)) > 0) {
				for(u_int i = 0; i < n; ++i) {
					for(int j = 7; j >= 0; --j) {
						//fprintf(stderr, "%d",((1<<j) & (0x000000ff & str[i])) ? 1 : 0); 
						if(((1<<j) & (0x000000ff & str[i]))) {
							assert(ans->right != NULL);
							ans = ans->right;
						}
						else {
							assert(ans->left != NULL);
							ans = ans->left;
						}
						if(ans->left == NULL && ans->right == NULL) {
							//fprintf(stderr, "\n");
							ctr[ix++] = ans->key;
							if(ix == BLOCK_SIZE) {
								//写入文件
								fwrite(ctr, sizeof(char), ix, fout);		
								ix = 0;
							}
							ans = root;
						}
					}
				}
			}
			fwrite(ctr, sizeof(char), ix, fout);		
			fclose(fin);
			fclose(fout);
		}
		u_int ch2i(const char *str) {
			u_int res = 0;
			for(int i = 0; i < 4; ++i) res = (res<<8) | (0x000000ff & str[i]);
			return res;
		}
	private:
		char mask[256];
		char code[256][256];
		u_int counter[256];
};
int
main(int argc, char **argv) {
	Huffman huff;
	// huffman -c compress compressed
	// huffman -d decompress decompressed
	if(argc < 4) {
		fprintf(stderr, "usage: huffman -cd file.in file.out\n");
		exit(-1);
	}
	if(strcmp(argv[1], "-c") == 0) {
		huff.compress(argv[2], argv[3]);
	}
	else if(strcmp(argv[1], "-d") == 0) {
		huff.decompress(argv[2], argv[3]);
	}
	else {
		fprintf(stderr, "usage: option -c or -d.\n");
		exit(-1);
	}
 
	return 0;
}

hostMonster配置svn

4 comments November 9th, 2010

过去写的代码很少,当然现在也很少;这些天发现自己真可以称得上是游击队队员,在这放一泼代码然后走人,再去那放一泼走人,最后到处是代码,不知道什么玩意是什么玩意,所以有了把代码都导入到svn server上,很多人都用code.google来管理project,我知道;不过我总有一个潜意识告诉自己:不要钱的东西是不可靠的。所以打算自己弄一下,要不空间就浪费了。
无论是baidu还是google都可以找到一些资料,告诉你怎样在hostMonster上配置svn;就我切身体会,这些帖子的方法应该都能解决问题,我也是尝试了好几次才勉强算是成功了,说勉强是因为我还有一些问题没解决,这是后话。按照我最后参考的帖子的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
mkdir src
cd src
wget http://archive.apache.org/dist/apr/apr-1.4.2.tar.bz2
wget http://archive.apache.org/dist/apr/apr-util-1.3.9.tar.gz
wget http://subversion.tigris.org/downloads/subversion-1.6.9.tar.gz
wget http://www.webdav.org/neon/neon-0.29.3.tar.gz
wget http://www.sqlite.org/sqlite-amalgamation-3.6.22.tar.gz
 
tar -xzf apr-util-1.3.9.tar.gz
tar -xzf apr-1.4.2.tar.gz
tar -xzf subversion-1.6.9.tar.gz
tar -xzf neon-0.29.3.tar.gz
tar -xzvf sqlite-amalgamation-3.6.22.tar.gz 
 
cd apr-1.4.2
./configure --prefix=$HOME LDFLAGS="-L/lib64"
make
make install
 
cd ../apr-util-1.3.9
./configure --prefix=$HOME --with-apr=$HOME LDFLAGS="-L/lib64"
make
make install
 
cd ../neon-0.29.3
./configure --enable-shared --prefix=$HOME LDFLAGS="-L/lib64"
make
make install
 
cd ../sqlite-3.6.22/
mkdir ~/src/subversion-1.6.9/sqlite-amalgamation
cp sqlite3.c ~/src/subversion-1.6.9/sqlite-amalgamation/
 
cd ../subversion-1.6.9
./configure --with-apr=$HOME --prefix=$HOME --without-berkeley-db --with-zlib=/usr --with-ssl LDFLAGS="-L/lib64"
make
make install

执行如上脚本即可安装svn,如果不出意外应该和我一样最后遇到个什么权限导致的错误,无视之,反正我的权限就这么点,不可能得到root权限。接着,创建一个目录svnroot作为版本库的根目录,然后再在svnroot/下创建个版本库:

svn create code_xiaoe

貌似这样就完事了,当然实践连接一下的话(通过ssh连接):

svn list svn+ssh://sshUser@yourHost/code_xiaoe

如果不出意外应该和我一样遇到:

bash: svnserve: command not found

显然是没找到svnserve在哪,普遍想法就是去.bashrc文件下,把svnserve的位置加入到PATH,当然我曾经也是这么干的,问题没有解决。根据我找到的帖子等,比较正确的说法是:

因为svn调用ssh后得到是非登陆shell。

还有个老外说:
.bash_profile is only loaded if you actually have a “login” session.
.bashrc is always loaded for your user
但是实际情况是.bashrc不好使,不排除我用的不对,对bash了解有限。
最终,解决方法如下:
用ssh-keygen生成一对公钥(user.public)和密钥(user.private),把user.public弄到hostMonster自己$HOME目录下,然后用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash
# this script assists in adding an svn user to a hostmonster account.
# they have to authenticate each with their own ssh key than only allows ssh access for their
# svn username as we're only allowed one ssh login for root
# and this prevents people give svn accounts having root access to the hostmonster account!
# written by Jon Booth see www.sharpstep.com/Articles/HostMonster-svn
 
# check for an argument - the username to add
if [ "$1" == "" ]; then
	echo Usage $0 [username] [public key file]
	exit
fi
 
#check for the second argument - the public key file.
if [ "$2" == "" ]; then
	echo Usage $0 [username] [public key file]
	exit
fi
 
if [ -f "$2" ]; then
	echo public keyfile "$2" found
else
	echo unable to find public key "$2"
	echo Usage $0 [username] [public key file]
	exit
fi
 
# check to see if the given username already exists in the keys (only works if added with this script).
if [ -f  ~/.ssh/authorized_keys ]; then
	if [ "$(cat ~/.ssh/authorized_keys | grep svnrepos | grep \\-\\-tunnel-user=$1\\\" | egrep $1\$)" != "" ]; then
		echo it appears svn user \"$1\" already exists
		exit
	fi
else
	echo no authorized keys file found... skipping existing check
fi
# check that svnserve is properly in the path
if [ "$(which svnserve)" == "" ]; then
	echo
	echo Can\'t continue as svnserve doesn\'t appear to be installed on the path.
	echo it\'s part of the svn package
	exit
fi
 
echo Creating svn user $1
# create the keys
# this is no good as putty on windows won't use them - also it's safer for the users to provide the key files so now
# I'm checking them as the second argument.
#ssh-keygen -q -t rsa -f $1_key -N "" -C "svn user $1"
# append the user line to the authorised keys
echo command=\"$(which svnserve) -t -r ~/svnrepos --tunnel-user=$1\",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty $(cat "$2") svn user $1 &gt;&gt; ~/.ssh/authorized_keys
# remove the public key now it's in the authorized_keys file
rm $2
echo user $1 now added and authenticated

此脚本create_svn_user.sh,运行 sh create_svn_user.sh user.public user.public,把用户公钥等信息加入$HOME/.ssh/authorized_keys文件里;然后authorized_keys文件中:

command="/home2/liulinli/bin/bin/svnserve -t -r /home2/liulinli/svnroot

-t之前是svnserve的位置,-r后边是版本库的根目录,这里根据自己情况相应修改即可。
本地机器上也有相应的修改,这里以*nix为例(winXP系统我没有测试通过,这就是我为什么说勉强成功。。。在写完这篇文档后,又修改了下居然成功了。。),修改~/.subversion/config,在文件中[tunnels]之后加入一行:ssh=ssh -i /home/rt77789/.ssh/user.private -q
/home/rt77789/.ssh/user.private就是刚生成的私钥,就是说导入私钥。然后,测试:

svn list svn+ssh://sshUser@yourHost/code_xiaoe

这次没有bash: svnserve: command not found出现,svn + ssh成功。
另外,还有一个问题就是密钥公钥的问题,开始在winXP下用PuTTyGen生成一对,但是在ubuntu下死活不好使,最后用ssh-keygen才好使;可能,svn不能识别puttyGen生成的private key吧。有这一出后,我想难道winXP下tortoiseSVN可能也是密钥之类的问题呗,然后用putty读入ssh-keygen生成的密钥,保存一下不就是putty的格式了么,然后修改tortoiseSVN配置文件[tunnels]后边加了句话:

ssh = "D:/Program Files/TortoiseSVN/bin/TortoisePlink.exe" -i "d:/xiaoe.org/xiaoe.org.private.key.nix.ppk" -q

结果这样不work啊。。。xiaoe.org.private.key.nix.ppk是puttyGen导出的由ubuntu生成的密钥。
接着,我在setting->network->ssh client直接写

"D:\Program Files\TortoiseSVN\bin\TortoisePlink.exe" -i "D:\xiaoe.org\xiaoe.org.private.key.nix.ppk"

这样就好使了。。。
配置这个东西耗了一天多,别人有的几乎没有问题就搞定了,由此证明技术上的差距是很大的;有时间再看看tortoise怎么才好使吧,累得我屁颠屁颠的。
参考文献:

http://cache.baidu.com/c?m=9f65cb4a8c8507ed4fece7631043803b5c0ecb743ca08d552ac9d11bc6334640426cf4ba535e0705a5b368225cef1f53baa37728200250a09abb9f4aacfad6746edf6770270b873105d26ab8cb37749c7fcf09b5f90ee7cbac6fd5b9d2a28b09149605&p=87769a46d2840bff57ed9529427acd&user=baidu

http://sharpstep.com/Articles/HostMonster-svn/
http://hostmonsterforum.com/showthread.php?1294-Subversion

http://archive.apache.org/dist/apr/

http://bbs.idcspy.com/thread-94575-1-1.html