黄山游记

June 3rd, 2010

最先发布在Twitter上,写着写着也有千字了,那就也放在这里吧。

(1)三天黄山自驾游结束。旅途一开始就很刺激,朋友想进上外参观,但门卫死活不让,结果那小子就猛地一踩油门闯进校园了。门卫立马开个小摩托来追,我们在上外里上演追车好戏… 结果被十几个保安用摩托围住拦了下来,后来又来了保卫处等若干领导,最后我们只好下车道歉了好久他们才放我们走。 via

(2)接人离开松江大学城后,我们一路开往杭州。到了那儿吃个便饭,开始逛西湖。我上次来杭州西湖还是4年前高考后和爸妈一起来的,西湖那是那个西湖,当地人依然很悠闲,只是我们的谈资多了富二代、豪车和斑马线。傍晚十分我们离开杭城开往黄山山脚下的屯溪县,从夕阳开到天墨墨黑。 via

(3)放好行李我们就在宾馆了吃晚饭。席毕,和同行的老外朋友谈起了中日文化,听她讲得我们很兴起,回房间继续。老外在美国读历史专业,半年前到日本做交流,上周来上海玩。聊到为啥日本人会讨厌中国,她讲了4个原因,其中一个是因为我们老抄他们,其他我忘了,外加我英文不好没听全。 via

(4)第二天7点多我们离开宾馆开车前往黄山景区。一路高速、山峦、蔡琴我们很high,结果开到黄山北山,不过我们路遇一位当地人拦我们的车,她告知我们开错了,应该到汤口下去南山口的,现在多开了60多公里。她说她也要去那儿上班,我们就让他搭我们的车,顺便也作导游顺利到了景区。 via

(5)我们走的东海那条线路,也没爬多少山,买了点茶叶,后来去了漂流。漂流不把鞋子脱了租个拖鞋真是失误,弄得鞋子湿透。溪水很浅,皮筏艇搁浅到滩上时,我们男的只能下来作纤夫了… 一两公里的长度我们划了一个多小时,下半身几乎湿透的我们无心玩别的,直接回县城宾馆。 via

(6)晚饭我们“骗”老外吃了猪耳朵,饭后告诉了她那是什么。然后我们去屯溪老街。我看中双草鞋赶紧买了,虽然穿着有些刺脚,但比宾馆那种纸一般的好。大家也都买了些东西,有扇子、糕、宣纸、梳子等。同学的女友说这条街上的店就是卖那么几种东西,然后排列组合,精辟阿。打的回府,当地起步费5元。 via

(7)回到宾馆,老外忙她自己的事去了,我们4人待在房里看电视,我才知道各地卫视原来还有那么多非诚勿扰的山寨节目。另外一个女孩半开玩笑的问我同学和他女友需不需要我们俩电灯泡走开,给他们单处的机会。虽然我觉得这没什么,不过真要是这样我今晚要怎么睡呢?另,宾馆里抽水马桶力道真小。 via

(8)第三天早上我们开车绕徽州古城看了一圈,然后上高速回程。在收费口我熄火了好几次才开动车子,被一边的警察看到,他让我靠边停车检查了下行驶证和驾驶证。这三天怎么竟有人拦我们… 从徽行到沪杭高速我开了二百多公里,腰和背有了些反应,然后换我同学开。话说这一路高速我们撞死不少昆虫。 via

(9)这次旅行我突然觉得江南女子好啊,自己能弹个乐器或者能写上画上几笔,家里还可能有个茶园,依山傍水而居,温柔又灵性。此次一行五人二男三女玩得还是很开心的,年轻人就是能很快的玩到一起,也没啥拘束,美好的学生时代。 via

建立Google App Engine独立的Python开发环境

April 17th, 2010

文章标题取得有点虚幻,情况其实是这样的:

Google App Engine的开发运行环境(SDK和appspot.com)要求是Python 2.5.x,但现在很多发行版Python的版本都是2.6.x了,比如我的Slackware就是2.6.2。而且不是卸载掉2.6然后装个2.5就成的,因为系统很多部分依赖于当前的Python版本,一旦如此简单的降级系统很可能无法正常使用。所以要在保留当前系统使用的Python版本的前提下,要让GAE的SDK能在Python 2.5.x环境下跑起来。

步骤如下:

  1. 下载Python-2.5.2
  2. 这里下载Python源码包

    Google的appspot.com跑的就是Python 2.5.2,那么我们当然也用这个版本咯。

  3. 编译安装Python
  4. 解压源码包后,给configure加上”–prefix“参数,值可以是你家目录下某个目录,比如”–prefix=/home/YOU/lab/python-2.5.2/”。之后make && make install。

    我们将把Python-2.5.2独立安装在一个目录里,这样就能不影响任何东西了。在没有包管理工具的帮助下还是不建议直接”–prefix=/usr/local/”,不方便管理卸载诶 ;-)

  5. 修改GAE SDK
  6. 编辑google_appengine/dev_appserver.py的第一行路径为刚才编译好的Python 2.5.x二进制文件的绝对路径,比如:

    #!/home/YOU/lab/python-2.5.2/bin/python2.5

现在执行./google_appengine/dev_appserver.py your_app/就是运行在Python-2.5.2之下了。
目前这个方法还没有经过大量的实战测试,GAE我也没有写过特别复杂的应用,不知道这种方法是否有隐患。不过理论上我觉得还是可行的。

题外话
由于我系统的Python是2.6.2的,所以之前我玩GAE一直是在Python 2.6环境下跑的,基本没什么大问题,这也是因为我还没跑到够复杂吧。不过有个比较讨厌的就是,一旦你程序写错了,debug的信息你是根本看不懂的 =.=! 我举个例子,某个程序里故意把python print的格式化的连接字符”%”改成逗号”,”,下面分别是2.6和2.5环境下的错误输出debug信息截图:

http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runerror.png
http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runerror.png

看看,哪个debug信息更清晰?在2.6环境下基本只要出错就是下面这个”No module named _multiprocessing”的错误信息,令人一头雾水不知道从哪里排错。


File "/usr/lib/python2.6/multiprocessing/__init__.py", line 83, in
import _multiprocessing
ImportError: No module named _multiprocessing

之前虽然在2.6下凑合着跑着,但在出错方面就是因为这个浪费了很多时间,以后再也不这么干了,老老实实用2.5。

Update 4-19:
今早在网上随便乱逛时进到了张沈鹏仙人的googlecode,然后惊然发现了”No module named _multiprocessing”的解决方法,就是在app目录根目录下建个_multiprocessing.py,内容为: import multiprocessing
测试了下果然不然报错,并且能准备指出错误在哪儿了。最后是这个fix的真正出处。奇怪为啥以前没搜到呢 =.=!

最后贴一下GAE SDK分别跑在2.6和2.5环境下的运行环境参数:
http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runok.png
http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runok.png

Update 5-20:
再举个不推荐用2.6跑gae sdk的例子。
Google SDK 1.3.4刚发布,对dev_appserver增加了自动执行task的特性,以后再也不用手工去按那个’run’按钮了。但是,在python 2.6环境下无效,task不会自动执行。起初我以为是task code写的不对,或者这个特性有什么限制,在gae的google groups上帖子都写了一半。然后突然想起是不是python版本的问题,在dev_appserver.py改python环境为2.5.2,这回终于能自动执行了 =.=! 浪费了很多时间,血的教训。

找出字幕中的生词

April 13th, 2010

写了小程序(pickupnewords.py)可以找出文本中的英文生词,比如你在观影前可以找出英文字幕中你不认识的单词,逐一查明,这样就不会边看边查字典了,打扰你欣赏电影了 ^_^

程序最新源代码在github。下面简单说明一些关于这个程序的东西。

我这程序肯定无法强大到能读取你大脑的信息得知你认不认识某个单词,它要借助本地存储,其实就是一个用pickle模块把你已经认识的单词集合写入到一个文件里,程序因此有了依据。当然了不可能把’is’、’apple’这样的词也判为生词,因此得有个基础单词库,我用的是Oxford 3000 wordlist,这个是牛津字典的单词释义所用的基础单词,我已经把它转换好了,文件名是oldwords.dat。一个没有记忆不会学习的人是可怕的,程序也是如此,这是我下面要讲的。

许多英语达人的词汇量肯定不止3000,所以在初期运行这个程序你会发现有好多单词你都认识,或者日后某些单词反复出现,慢慢你已经熟知了,那么就需要让程序记住这些单词。pickupnewords.py提供了一个非常简单甚至简陋的命令接口,告诉程序哪些单词需要记忆。再列出可能的生词列表后,程序会等待你输入指令了。你能输入的指令有下列几种:

  • 0,9,13, 21
  • 生词列表的每个单词前都有个序号,你输入了哪几个序号程序就会记住对应的单词

  • !0,9,13, 21
  • 这个仅仅比上面的多了一个感叹号“!”,它的意思就是相反,除了感叹号后面列出的序号对应的单词都要记忆

  • all
  • 记住所有列出的单词

  • !!all直接回车
  • 不记忆列出的任何单词,它们都是生词

使用方法:
下载pickupnewords.py和oldwords.dat,运行:

python pickupnewords.py /path/to/your/english.srt

注:本程序只支持srt这类的纯文本环保格式。
任何问题建议欢迎留言 ;-)

===== 补充 =====
单词的分词处理的十分简单,能去掉字幕文件中无意义、非英文单词的部分,但对于诸如”I’ve”、”shouldn’t”识别为一个单词,”copied”、”driving”这样的过去分词和现在分词仍然作为生词,虽然原型是非常基础的单词。Python应该有好的分词库(我了解的不多,如有好的也请推荐),但我不想把事情搞的太复杂了,我们完全可以把这些词让程序记住,或者干脆忽略,反正除此之外能找出真正的生词就行。

Update 4-21:
@weakish 在下面的留言说的很对。其实这个程序离真正可用还很远,还需要优化。

Blogging with Emacs

March 4th, 2010

Emacs写博客
发表至WordPress ;-)
howto

对gtap的一些wordaround

February 28th, 2010

前两天发现gtap这个项目,也是个Twitter API代理,基于GAE(Python)。想着Choqok、qwit都没法用birdnest,所以架了个玩玩。结果弄出一堆事来 =.=!

先是把gtap和其它几个app放在一起,如我上篇文章所讲的。这个挺简单:

diff --git a/gtap.py b/gtap.py                                                                                  
index 1b9d8ed..472157d 100644                                                                                   
--- a/gtap.py                                                                                                   
+++ b/gtap.py                                                                                                   
@@ -16,6 +16,7 @@ class MainPage(webapp.RequestHandler):                                                        
         origUrl = self.request.url                                                                             
         origBody = self.request.body
         (scm, netloc, path, params, query, _) = urlparse.urlparse(origUrl)
+        path = path[5:]  # skip '/gtap'
         if path == '/':
             self.myOutput('text/html', 'here is the proxy of \"twitter.com\" by GTAP %s !' % (gtapVersion))
         else:
@@ -59,7 +60,7 @@ class MainPage(webapp.RequestHandler):
         self.doProxy('get')
 
 def main():
-    application = webapp.WSGIApplication( [(r'/.*', MainPage)], debug=True)
+    application = webapp.WSGIApplication( [(r'/gtap/.*', MainPage)], debug=True)
     wsgiref.handlers.CGIHandler().run(application)
 
 if __name__ == "__main__":

在app.xml里加上:

- url: /gtap/.*
  script: gtap.py
#  secure: always

如果你把gtap单独架设在gae上的,而不是和几个app一起放在yourapp.appspot.com上的话,这步不需要。

接着,发现Choqok等客户端发出的用户身份验证请求是到api.twitter.com,但http://api.twitter.com/account/verify_credentials.xml这样请求无效,改成http://twitter.com/account/verify_credentials.xml即可:

diff --git a/gtap.py b/gtap.py
index 472157d..f50f2dc 100644
--- a/gtap.py
+++ b/gtap.py
@@ -36,7 +39,7 @@ class MainPage(webapp.RequestHandler):
                 netloc = 'search.twitter.com'
                 newpath = path[7:]
             elif path_parts[1] == 'api':
-                netloc = 'api.twitter.com'
+                netloc = 'twitter.com'
                 newpath = path[4:]
             else:
                 netloc = 'twitter.com'

最后是最头疼的,本来经过上面两次改动echofon已经是可以正常收发推了。可偏偏Choqok和Qwit就是没法用gtap的api代理。老是提示”Could not authenticate you.“。经过抓包,我发现,这两个客户端竟然不会像其它客户端一样在http请求中加入Authorization头部,也就是用户名和密码,用来给网站验证的,难怪会出现错误。哪位朋友如果用Choqok/Qwit并且使用birdnest api代理的请支一声~ 经过一番摸索(省去纠结的zzzzzzzz过程),改动了gtap对http头部不含有Authorizatioin的处理:

diff --git a/gtap.py b/gtap.py
index 472157d..f50f2dc 100644
--- a/gtap.py
+++ b/gtap.py
@@ -22,6 +22,9 @@ class MainPage(webapp.RequestHandler):
         else:
             if 'Authorization' not in self.request.headers :
                 headers = {}
+                self.response.set_status(401, message="Unauthorized")
+                self.response.headers.add_header('WWW-Authenticate', 'Basic realm="Secure Area"')
+                self.response.out.write("401")
             else:
                 auth_header = self.request.headers['Authorization']
                 auth_parts = auth_header.split(' ')

原理是如果客户端的http请求头部没有Authorization字段,那么gtap返回”401 Unauthorized”,让它重新发送用户验证信息。再次抓包,Choqok第一次还是没有Authorization,接着就收到服务器发来的401状态码,于是它乖乖的再次发送请求并包含Authorization。

这样改之后echofon等依然可以正常使用gtap的api代理。也许你有注意到我在app.xml里注释掉了使用安全链接”# secure: always”,经测试Choqok在http下可以正常处理收发tweets以及其它api操作,但改用https后,发推就不行了,其它还是可以的。Qwit因为貌似不支持https,所以只能用http的。

虽然经过这么workaround,Choqok、Qwit能看推发推了,但我还是觉得Choqok这个客户端自身有些问题,因为如果换用twip这个api代理的话,无论http、https都能正常使用,偏偏birdnest和gtap的不行。如果说gtap应用少的话,birdnest可是使用广泛的twitter api代理啊,我的Twitter Opera Widget就用的它。不想再折腾了,如果你也在用gtap,希望本文能给你些帮助 ;-)

唉,连续两篇博文在讲twitter api代理的事儿了,老外上个网哪有天朝这么多的屁事,我朝屁民们在代理的事上浪费多少时间啊…

参考:
[1] 基本连接验证(Basic Access Authorization)的原理
[2] Status Code Definitions
[3] Authorization
[4] HTTP Request fields
[5] List of HTTP status codes
[6] Basic access authentication

UPDATE 2010-3-1
gtap的作者@rui7905非常迅速地更新到了0.3版,修正了我这篇文章提到的问题,并且做了原因分析,感兴趣得朋友移步讨论页。如果你用gtap,不要再用在下workaround的拙作了,升级到0.3吧~~

将Birdnest和opm-server-mirror合二为一

February 11th, 2010

前者是Twitter的API proxy,后者是Opera Mini的代理,均基于Google App Engine(简称GAE)。一个GAE账户只能建10个app,分别在GAE上建这两个代理不免有些浪费。另一方面,多一个地址也不好记,我希望能够一个GAE app上面同时跑多个应用,记一个地址就行了,嘿嘿~

本文假设你会在GAE上建应用。

要把Birdnest和opm-server-mirror放在一个app里其实改动并不多。

  1. checkout birdnest
  2. svn co -r 97 http://birdnest.googlecode.com/svn/branches/gae birdnest_r97

    注意一定要r97的,因为作者最近更新过code.py了,导致”internal sever error”,可能是因为GAE不支持socket模块的原因。就是因为co的版本不对我白弄了好久。。。

  3. 下载opm-server-mirror的opm.py,放到birdnest的目录中,并作如下改动:
  4. --- opm.py	2010-02-11 21:06:12.577148400 +0800
    +++ opm (2).py	2010-02-11 13:04:15.739257800 +0800
    @@ -29,7 +29,7 @@
               self.response.out.write(result.content)
     
     application = webapp.WSGIApplication(
    -                                     [('/', MainPage)],
    +                                     [('/opm/', MainPage)],
                                          debug=True)
     
     def main():
  5. 更改birdnest的app.yaml:
  6. --- app.yaml	2010-02-11 20:56:34.778320300 +0800
    +++ app (2).yaml	2010-02-11 21:22:18.383789000 +0800
    @@ -12,6 +12,8 @@
       script: code.py
     - url: /image/.*
       script: code.py
    +- url: /opm/.*
    +  script: opm.py
     - url: /
       static_files: index.html
       upload: index.html

最后appcfg.py update birdnest_r97上传至GAE,好了。以后你给twitter客户端设api代理的时候就用 http://fckgfw.appspot.com/api/,给Opera Mini设代理则用 http://fckgfw.appsot.com/opm/ 。嗯,和谐了。

迁移旧硬盘上的Linux到新硬盘(LVM)

February 7th, 2010

买了块新的大硬盘,准备把原先硬盘上的Slackware迁移过去,并且采用LVM,xp不要了换成Win7。记录下迁移过程和遇到的一些问题及解决方法。

  • 用Slackware 13.0 dvd系统盘引导启动,并分区。Slackware 从12.0开始支持安装系统到LVM

  • Device Boot Start End Blocks Id System
    /dev/sda1 * 1 13 102400 7 HPFS/NTFS
    /dev/sda2 13 2611 20869120 7 HPFS/NTFS
    /dev/sda3 2611 3917 10485760 c W95 FAT32 (LBA)
    /dev/sda4 3917 38913 281110368+ 5 Extended
    /dev/sda5 3917 3981 519047 83 Linux
    /dev/sda6 3982 4504 4200966 82 Linux swap
    /dev/sda7 4505 38913 276390261 8e Linux LVM

    这个是我新硬盘的最终分区情况。sda1是Win7保留的100M启动分区,sda2是Win7系统盘,sda3是D盘。500M大的sda5我原本想作为/boot,不过目前我就Win7+Slackware+LILO不需要,留作未来使用吧。swap(sda6)没有用LVM,剩下的260多G(sda7)都交给LVM管理了。

  • 建立LV分区并激活

  • pvcreate /dev/sda7
    vgcreate MYVG /dev/sda7
    lvcreate -L 20G -n ROOT MYVG
    lvcreate -L 10G -n USRLOCAL MYVG
    lvcreate -L 100G -n DATA MYVG
    lvcreate -L 50G -n HOME MYVG

    vgscan --mknodes
    vgchange -ay

  • 格式化LV分区并挂载到新的root目录

  • mkreiserfs /dev/MYVG/ROOT
    mkreiserfs /dev/MYVG/USRLOCAL
    mkreiserfs /dev/MYVG/HOME

    mkdir /new_root
    mount -t reiserfs /dev/MYVG/ROOT /new_root
    mkdir -p /new_root/usr/local
    mount -t reiserfs /dev/MYVG/USRLOCAL /new_root/usr/local
    mkdir /new_root/home
    mount -t reiserfs /dev/MYVG/HOME /new_root/home

  • 挂载旧硬盘上的系统目录到旧root目录

  • mkdir /old_root
    mount -t reiserfs /dev/sda5 /old_root
    mount -t reiserfs /dev/sda7 /old_root/usr/local
    mount -t reiserfs /dev/sda8 /old_root/usr/local/opt
    mount -t reiserfs /dev/sda9 /old_root/home

    又买了个移动硬盘盒,旧硬盘就可以当移动硬盘了。

  • 迁移(复制)旧系统到新硬盘

  • cd /old_root
    /old_root/bin/tar cpBf - . --exclude=tmp/* | ( cd /new_root && /old_root/bin/tar xvpBf -)

    漫长的等待…… /dev 啥的统统要拷过来。根据参考[5],到这里接着用直接chroot后就可以mkinitrd和lilo了,但事实不是这样的,还得额外多些操作。

  • chroot到/new_root,制作initrd和LILO

  • mount --bind /proc /new_root/proc
    mount --bind /sys /new_root/sys
    mount --bind /dev /new_root/dev
    chroot /new_root
    cd /boot
    mkinitrd -c -k 2.6.29.6-smp -m reiserfs -f reiserfs -r /dev/MYVG/ROOT -L -o /boot/initrd.gz
    vim /etc/lilo.conf
    lilo -v

    三行mount –bind是必须的,slackware的README_LVM.TXT说安装程序会将/proc和/sys挂载上,但我目前不是全新安装没有使用setup安装程序,而且我运行setup企图让它帮我挂载/proc等未果 :( 所以得用–bind(见参考[6]),不过我不是很了解这个选项。不这么mount的话执行mkinitrd会出现cat /proc/partitions错误,执行lilo会出现 Fatal: raid_setup: stat(“/dev/sda”)。

    /etc/lilo.conf 也作相应的调整:

    boot="/dev/sda"
    ......
    image="/boot/vmlinuz"
    initrd="/boot/initrd.gz"
    root="/dev/MYVG/ROOT"
    label="2.6.29.6-smp"
    read-only
    # Linux bootable partition config ends
    # Windows bootable partition config begins
    other = /dev/sda1
    label="Windows7"
    table = /dev/sda
    # Windows bootable partition config ends

    Win7的引导分区是sda1,不是系统盘sda2。马上就要好了 ;-)

  • 在新系统的/dev目录下建立LVM设备文件

  • exit # 退出chroot
    umount /new_root/dev
    chroot /new_root
    vgscan --mknodes
    vgchange -ay

    如果没有这一步,重启后LILO引导菜单已经可以看见,Win7引导正常,Slackware能引导起来,但是在挂载文件系统是提示找不到 /dev/MYVG/ROOT 文件。于是我就如上这么干了,在/dev下就会有MYVG/ROOT等LV设备文件了。不过我不太明白,必须得通过vgscan –mknodes的方式来建立几个lv分区的设备文件吗?那/dev/sda文件应该是我旧系统上复制过来的,换了硬盘后能直接使用?啊呀,这方面知识太欠缺了,我自己已经没法解释了,望路过的朋友帮我解惑一下 ;-)

  • 建立fstab文件

  • /dev/sda6 swap swap defaults 0 0
    /dev/MYVG/ROOT / reiserfs defaults 1 1
    /dev/MYVG/USRLOCAL /usr/local reiserfs defaults 1 2
    /dev/MYVG/HOME /home reiserfs defaults 1 2
    /dev/sda3 /media/D vfat uid=0,umask=0022,fmask=0111,shortname=mixed,iocharset=utf8 0 0
    /dev/cdrom /mnt/cdrom auto defaults,user,ro,noexec 0 0
    devpts /dev/pts devpts gid=5,mode=620 0 0
    proc /proc proc defaults 0 0

至此我的系统迁移完毕。这一次让我发现又有很多不懂不明白啊~~~

参考:
[1] 通用线程: 学习 Linux LVM,第 1 部分
[2] 通用线程:学习 Linux LVM,第 2部分
[3] README_LVM.TXT
[4] LVM White Paper 本地PDF文件
[5] Slackware 12.1 on LVM – Installation and Migration
[6] Backup almost working, LILO hangs

承上启下

December 31st, 2009

年头那几天跟@hkai同学聊起某事件似乎才刚发生过,2009就只剩1个多小时了。有08奥运今年开的的错觉,才发现这一年太多荒唐可笑之事发生在每个人身边。我总是记不清这些事件的具体时间,因为它们太应接不暇了,因为它们仍然在继续演出着。

昨天刚结束了一种生活状态,就和当年高二升高三分班一样,还处在镇痛期。09年许多事情让我比较清醒地认识到了自己的性格弱点,不管某个结果如何,未来的一年我都将迎来全新的生活。

2010我希望自己继续善其身,也希望能为争取个人权利多做些什么;希望肉食者能够偶尔吃点蔬菜,清清自己的宿便;更希望有那么一个人与我一起共赏这纠结而又精彩美好的世界 ;-)

这是一篇比微博长,比博客短的日志~ 新年快乐 :D

养一下驴子

December 19th, 2009

用MLDonkey很久了下不热门的资源一直非常慢,以至失去用ed2k网络的兴趣了。最近才发现原来是我没有开启MLDonkey的KAD功能 -_____-!! 没有KAD之类的技术用P2P久失去了很大的乐趣。

下面记录下几点设置,我不太懂养驴子,应该还有使驴子跑得更快的设置,还请路过大大教教我 ;-)

1. MLDonkey里的enable_kademlia设为true

2. 网上看到说需要nodes.dat和contact.dat(其实这个文件不需要了,是eDonkey的Overnet网络,现在eMule的ed2k和KAD网络足矣),而且还得手工添加。其实可以通过配置MLDonkey的download.ini文件来实现自动更新nodes.dat文件。

~/.mldonkey/download.ini
web_infos = [
("server.met", 0, "http://sn.im/server.met");
("nodes.gzip", 1, "http://upd.emule-security.net/nodes.dat");
("contact.dat", 168, "http://download.overnet.org/contact.dat");
("geoip.dat", 0, "http://www.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz");
("guarding.p2p", 96, "http://www.bluetack.co.uk/config/level1.gz");
(hublist, 0, "http://dchublist.com/hublist.config.bz2");]

主要修改”server.met”和”nodes.gzip”两段,server.met用的参考[1]里提供的链接,设成0是表示只需在MLDonkey启动时载入; nodes.gzip用的参考[2]里提供的链接,设成1是表示每1小时更新一次。其他字段默认。

参考:
[1] 安全eD2k服务器列表 2009-11-28
[2] Kad节点文件 nodes.dat
[3] 终于可以在ubuntu上养驴了
[4] [问题]mldonkey可以连接kad吗?

本地机器上运行远程X程序、X环境

November 6th, 2009

X11Forwarding
X11转发,在本地机器(Linux/Windows)上运行远程服务器上的X程序

***Linux***

方法1、2是在本地Linux机器上的当前窗口上显示远程服务器上的X程序(单独窗口的形式);
方法2、3使用SSH的X11转发,因此确保远程服务器上的/etc/ssh/sshd_config的X11Forwarding为yes;
方法3、4是在本地Linux上新的控制台下的新的X server上运行远程服务器的完整X环境;
方法1、4需要设置DISPLAY环境变量;
* 所有方法在两端都不需要root权限
* 192.168.1.xx 为本地Linux的IP

方法一:
本地Linux:
$ xhost +
$ ssh user@remotehost
远程服务器:
$ export DISPLAY=192.168.1.xx:0[.0]
$ xeyes& ; nautilus&

* xhost + 允许远程X程序在当前X server上允许,详细man

方法二:
本地Linux:
$ xhost +
$ ssh -X user@remotehost
远程服务器:
$ xeyes&; konqueror&

方法三:
本地Linux:
$ X :12.0 vt12 2>&1 > /dev/null &
$ xterm -display :12.0 -e ssh -X user@remotehost &
切到Ctrl+Alt+F12,在里面的xterm里运行 xeyes 等X程序,或者gnome-session、
startkde等运行完成的X环境

方法四:
本地Linux:
$ X :11.0 vt11 2>&1 > /dev/null &
$ xterm -display :11.0 &

切到Ctrl+Alt+F11在xterm里运行:
$ xhost +

本地Linux:
$ ssh user@remotehost
$ export DISPLAY=192.168.1.xx
$ xeyes& or gnome-session& or startkde&

一般来讲用ssh -X比较方便,方法1、4只是在探讨原理,实际使用相对麻烦。
根据你的不同需求选择方法2、3,在本地只单独运行某些X程序,还是需要完整的X环境。

***Windows***

Windows下需要如下软件:
X server – 本文使用Xming
ssh client – 本本使用Putty

Putty设置:
Connect -> SSH -> X11,勾选”允许 X11 映射”,填入localhost:0.0,MIT-Magic-Cookie-1协议

Xming设置:
如果你只运行单独的X程序,选择哪种窗口模式无所谓;
如果你需要完整的X环境,请选择单窗口或者全屏模式;
一定要勾选上”No Access Control”

最后用Putty登录到远程服务器,运行xeyes等独立X程序,或者gnome-session、startkde完整X环境。

References:
[1] Linux下DISPLAY环境变量的作用
[2] 用SSH实现X11转发