<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>vvoody's woody house</title>
	<atom:link href="http://vvoody.org/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://vvoody.org/blog</link>
	<description>善其身</description>
	<lastBuildDate>Fri, 03 Sep 2010 05:56:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>指定git使用其他sshkey</title>
		<link>http://vvoody.org/blog/?p=614</link>
		<comments>http://vvoody.org/blog/?p=614#comments</comments>
		<pubDate>Wed, 18 Aug 2010 15:01:39 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[sshkey]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=614</guid>
		<description><![CDATA[一般使用第三方code hosting网站(如GitHub)需要上传你的sshkey公钥，这个步骤很简单，网上一搜就有。不过有些情况你不想用默认的~/.ssh/id_rsa和id_rsa.pub作为你的sshkey，因为你希望在github这类网站上就使用一个sshkey公钥，然后在不同的机器上都使用这对公私钥，省得制作一堆key上传麻烦。 原先以为可以通过git自身的设置来达到目的，后来意识到和它没关系，仅仅需要配置下ssh就行。 在~/.ssh/config文件附加下面一段： Host github.com # 必须写一样的hostname，因为是要ssh xxx@github.com HostName github.com User git # 不是你在github上的账户，必须是"git" IdentityFile ~/.ssh/yet_another_key # 其他sshkey 在把~/.ssh/yet_another_key.pub上传至github后，运行ssh -v github.com可以看看整个过程。以后，git clone git@github.com:USER/PROJECT.git、git push origin master等等操作都会使用你指定的sshkey来验证。]]></description>
			<content:encoded><![CDATA[<p>一般使用第三方code hosting网站(如<a href="http://github.com/">GitHub</a>)需要上传你的sshkey公钥，这个步骤很简单，网上一搜就有。不过有些情况你不想用默认的~/.ssh/id_rsa和id_rsa.pub作为你的sshkey，因为你希望在github这类网站上就使用一个sshkey公钥，然后在不同的机器上都使用这对公私钥，省得制作一堆key上传麻烦。</p>
<p>原先以为可以通过git自身的设置来达到目的，后来意识到<a href="https://git.wiki.kernel.org/index.php/GitFaq#How_do_I_specify_what_ssh_key_git_should_use.3F">和它没关系</a>，仅仅需要配置下ssh就行。</p>
<p>在~/.ssh/config文件附加下面一段：<br />
<code><br />
    Host github.com       #  必须写一样的hostname，因为是要ssh xxx@github.com<br />
    HostName github.com<br />
    User git                    #  不是你在github上的账户，必须是"git"<br />
    IdentityFile ~/.ssh/yet_another_key  #  其他sshkey<br />
</code></p>
<p>在把~/.ssh/yet_another_key.pub上传至github后，运行ssh -v github.com可以看看整个过程。以后，git clone git@github.com:USER/PROJECT.git、git push origin master等等操作都会使用你指定的sshkey来验证。</p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=614</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>黄山游记</title>
		<link>http://vvoody.org/blog/?p=611</link>
		<comments>http://vvoody.org/blog/?p=611#comments</comments>
		<pubDate>Wed, 02 Jun 2010 17:07:19 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=611</guid>
		<description><![CDATA[最先发布在Twitter上，写着写着也有千字了，那就也放在这里吧。 （1）三天黄山自驾游结束。旅途一开始就很刺激，朋友想进上外参观，但门卫死活不让，结果那小子就猛地一踩油门闯进校园了。门卫立马开个小摩托来追，我们在上外里上演追车好戏&#8230; 结果被十几个保安用摩托围住拦了下来，后来又来了保卫处等若干领导，最后我们只好下车道歉了好久他们才放我们走。 via （2）接人离开松江大学城后，我们一路开往杭州。到了那儿吃个便饭，开始逛西湖。我上次来杭州西湖还是4年前高考后和爸妈一起来的，西湖那是那个西湖，当地人依然很悠闲，只是我们的谈资多了富二代、豪车和斑马线。傍晚十分我们离开杭城开往黄山山脚下的屯溪县，从夕阳开到天墨墨黑。 via （3）放好行李我们就在宾馆了吃晚饭。席毕，和同行的老外朋友谈起了中日文化，听她讲得我们很兴起，回房间继续。老外在美国读历史专业，半年前到日本做交流，上周来上海玩。聊到为啥日本人会讨厌中国，她讲了4个原因，其中一个是因为我们老抄他们，其他我忘了，外加我英文不好没听全。 via （4）第二天7点多我们离开宾馆开车前往黄山景区。一路高速、山峦、蔡琴我们很high，结果开到黄山北山，不过我们路遇一位当地人拦我们的车，她告知我们开错了，应该到汤口下去南山口的，现在多开了60多公里。她说她也要去那儿上班，我们就让他搭我们的车，顺便也作导游顺利到了景区。 via （5）我们走的东海那条线路，也没爬多少山，买了点茶叶，后来去了漂流。漂流不把鞋子脱了租个拖鞋真是失误，弄得鞋子湿透。溪水很浅，皮筏艇搁浅到滩上时，我们男的只能下来作纤夫了&#8230; 一两公里的长度我们划了一个多小时，下半身几乎湿透的我们无心玩别的，直接回县城宾馆。 via （6）晚饭我们“骗”老外吃了猪耳朵，饭后告诉了她那是什么。然后我们去屯溪老街。我看中双草鞋赶紧买了，虽然穿着有些刺脚，但比宾馆那种纸一般的好。大家也都买了些东西，有扇子、糕、宣纸、梳子等。同学的女友说这条街上的店就是卖那么几种东西，然后排列组合，精辟阿。打的回府，当地起步费5元。 via （7）回到宾馆，老外忙她自己的事去了，我们4人待在房里看电视，我才知道各地卫视原来还有那么多非诚勿扰的山寨节目。另外一个女孩半开玩笑的问我同学和他女友需不需要我们俩电灯泡走开，给他们单处的机会。虽然我觉得这没什么，不过真要是这样我今晚要怎么睡呢？另，宾馆里抽水马桶力道真小。 via （8）第三天早上我们开车绕徽州古城看了一圈，然后上高速回程。在收费口我熄火了好几次才开动车子，被一边的警察看到，他让我靠边停车检查了下行驶证和驾驶证。这三天怎么竟有人拦我们&#8230; 从徽行到沪杭高速我开了二百多公里，腰和背有了些反应，然后换我同学开。话说这一路高速我们撞死不少昆虫。 via （9）这次旅行我突然觉得江南女子好啊，自己能弹个乐器或者能写上画上几笔，家里还可能有个茶园，依山傍水而居，温柔又灵性。此次一行五人二男三女玩得还是很开心的，年轻人就是能很快的玩到一起，也没啥拘束，美好的学生时代。 via]]></description>
			<content:encoded><![CDATA[<p>最先发布在Twitter上，写着写着也有千字了，那就也放在这里吧。</p>
<p>（1）三天黄山自驾游结束。旅途一开始就很刺激，朋友想进上外参观，但门卫死活不让，结果那小子就猛地一踩油门闯进校园了。门卫立马开个小摩托来追，我们在上外里上演追车好戏&#8230; 结果被十几个保安用摩托围住拦了下来，后来又来了保卫处等若干领导，最后我们只好下车道歉了好久他们才放我们走。 <a href="https://twitter.com/vvoody/status/15255645711">via</a></p>
<p>（2）接人离开松江大学城后，我们一路开往杭州。到了那儿吃个便饭，开始逛西湖。我上次来杭州西湖还是4年前高考后和爸妈一起来的，西湖那是那个西湖，当地人依然很悠闲，只是我们的谈资多了富二代、豪车和斑马线。傍晚十分我们离开杭城开往黄山山脚下的屯溪县，从夕阳开到天墨墨黑。 <a href="https://twitter.com/vvoody/status/15256150155">via</a></p>
<p>（3）放好行李我们就在宾馆了吃晚饭。席毕，和同行的老外朋友谈起了中日文化，听她讲得我们很兴起，回房间继续。老外在美国读历史专业，半年前到日本做交流，上周来上海玩。聊到为啥日本人会讨厌中国，她讲了4个原因，其中一个是因为我们老抄他们，其他我忘了，外加我英文不好没听全。 <a href="https://twitter.com/vvoody/status/15256810301">via</a></p>
<p>（4）第二天7点多我们离开宾馆开车前往黄山景区。一路高速、山峦、蔡琴我们很high，结果开到黄山北山，不过我们路遇一位当地人拦我们的车，她告知我们开错了，应该到汤口下去南山口的，现在多开了60多公里。她说她也要去那儿上班，我们就让他搭我们的车，顺便也作导游顺利到了景区。 <a href="https://twitter.com/vvoody/status/15257441782">via</a></p>
<p>（5）我们走的东海那条线路，也没爬多少山，买了点茶叶，后来去了漂流。漂流不把鞋子脱了租个拖鞋真是失误，弄得鞋子湿透。溪水很浅，皮筏艇搁浅到滩上时，我们男的只能下来作纤夫了&#8230; 一两公里的长度我们划了一个多小时，下半身几乎湿透的我们无心玩别的，直接回县城宾馆。 <a href="https://twitter.com/vvoody/status/15258481383">via</a></p>
<p>（6）晚饭我们“骗”老外吃了猪耳朵，饭后告诉了她那是什么。然后我们去屯溪老街。我看中双草鞋赶紧买了，虽然穿着有些刺脚，但比宾馆那种纸一般的好。大家也都买了些东西，有扇子、糕、宣纸、梳子等。同学的女友说这条街上的店就是卖那么几种东西，然后排列组合，精辟阿。打的回府，当地起步费5元。 <a href="https://twitter.com/vvoody/status/15259476102">via</a></p>
<p>（7）回到宾馆，老外忙她自己的事去了，我们4人待在房里看电视，我才知道各地卫视原来还有那么多非诚勿扰的山寨节目。另外一个女孩半开玩笑的问我同学和他女友需不需要我们俩电灯泡走开，给他们单处的机会。虽然我觉得这没什么，不过真要是这样我今晚要怎么睡呢？另，宾馆里抽水马桶力道真小。 <a href="https://twitter.com/vvoody/status/15260674649">via</a></p>
<p>（8）第三天早上我们开车绕徽州古城看了一圈，然后上高速回程。在收费口我熄火了好几次才开动车子，被一边的警察看到，他让我靠边停车检查了下行驶证和驾驶证。这三天怎么竟有人拦我们&#8230; 从徽行到沪杭高速我开了二百多公里，腰和背有了些反应，然后换我同学开。话说这一路高速我们撞死不少昆虫。 <a href="https://twitter.com/vvoody/status/15262043534">via</a></p>
<p>（9）这次旅行我突然觉得江南女子好啊，自己能弹个乐器或者能写上画上几笔，家里还可能有个茶园，依山傍水而居，温柔又灵性。此次一行五人二男三女玩得还是很开心的，年轻人就是能很快的玩到一起，也没啥拘束，美好的学生时代。 <a href="https://twitter.com/vvoody/status/15264509843">via</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=611</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>建立Google App Engine独立的Python开发环境</title>
		<link>http://vvoody.org/blog/?p=593</link>
		<comments>http://vvoody.org/blog/?p=593#comments</comments>
		<pubDate>Sat, 17 Apr 2010 12:45:18 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[GAE]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=593</guid>
		<description><![CDATA[文章标题取得有点虚幻，情况其实是这样的： 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环境下跑起来。 步骤如下： 下载Python-2.5.2 到这里下载Python源码包 Google的appspot.com跑的就是Python 2.5.2，那么我们当然也用这个版本咯。 编译安装Python 解压源码包后，给configure加上&#8221;&#8211;prefix&#8220;参数，值可以是你家目录下某个目录，比如&#8221;&#8211;prefix=/home/YOU/lab/python-2.5.2/&#8221;。之后make &#038;&#038; make install。 我们将把Python-2.5.2独立安装在一个目录里，这样就能不影响任何东西了。在没有包管理工具的帮助下还是不建议直接&#8221;&#8211;prefix=/usr/local/&#8221;，不方便管理卸载诶 修改GAE SDK 编辑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的格式化的连接字符&#8221;%&#8221;改成逗号&#8221;,&#8221;，下面分别是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环境下基本只要出错就是下面这个&#8221;No module named _multiprocessing&#8221;的错误信息，令人一头雾水不知道从哪里排错。 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，然后惊然发现了&#8221;No module named [...]]]></description>
			<content:encoded><![CDATA[<p>文章标题取得有点虚幻，情况其实是这样的：</p>
<p>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环境下跑起来。</p>
<p>步骤如下：</p>
<ol>
<li>下载Python-2.5.2</li>
<p>到<a href="http://python.org/ftp/python/2.5.2/">这里</a>下载Python源码包</p>
<p>Google的appspot.com跑的就是Python 2.5.2，那么我们当然也用这个版本咯。</p>
<li>编译安装Python</li>
<p>解压源码包后，给configure加上&#8221;<strong>&#8211;prefix</strong>&#8220;参数，值可以是你家目录下某个目录，比如&#8221;&#8211;prefix=/home/YOU/lab/python-2.5.2/&#8221;。之后make &#038;&#038; make install。</p>
<p>我们将把Python-2.5.2独立安装在一个目录里，这样就能不影响任何东西了。在没有包管理工具的帮助下还是不建议直接&#8221;&#8211;prefix=/usr/local/&#8221;，不方便管理卸载诶 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<li>修改GAE SDK</li>
<p>编辑google_appengine/dev_appserver.py的第一行路径为刚才编译好的Python 2.5.x二进制文件的绝对路径，比如：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/home/YOU/lab/python-2.5.2/bin/python2.5</span></pre></div></div>

</ol>
<p>现在执行./google_appengine/dev_appserver.py your_app/就是运行在Python-2.5.2之下了。<br />
目前这个方法还没有经过大量的实战测试，GAE我也没有写过特别复杂的应用，不知道这种方法是否有隐患。不过理论上我觉得还是可行的。</p>
<p><strong>题外话</strong><br />
由于我系统的Python是2.6.2的，所以之前我玩GAE一直是在Python 2.6环境下跑的，基本没什么大问题，这也是因为我还没跑到够复杂吧。不过有个比较讨厌的就是，一旦你程序写错了，debug的信息你是根本看不懂的 =.=! 我举个例子，某个程序里故意把python print的格式化的连接字符&#8221;%&#8221;改成逗号&#8221;,&#8221;，下面分别是2.6和2.5环境下的错误输出debug信息截图：</p>
<p><a href="http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runerror.png">http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runerror.png</a><br />
<a href="http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runerror.png">http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runerror.png</a></p>
<p>看看，哪个debug信息更清晰？在2.6环境下基本只要出错就是下面这个&#8221;No module named _multiprocessing&#8221;的错误信息，令人一头雾水不知道从哪里排错。</p>
<p><code><br />
  File "/usr/lib/python2.6/multiprocessing/__init__.py", line 83, in <module><br />
    import _multiprocessing<br />
ImportError: No module named _multiprocessing<br />
</code></p>
<p>之前虽然在2.6下凑合着跑着，但在出错方面就是因为这个浪费了很多时间，以后再也不这么干了，老老实实用2.5。</p>
<p><font color="red">Update 4-19:</font><br />
今早在网上随便乱逛时进到了<a href="http://www.douban.com/people/zuroc/">张沈鹏</a>仙人的<a href="http://code.google.com/p/zspyun/source/browse/trunk#trunk/gae/rssfind">googlecode</a>，然后惊然发现了&#8221;No module named _multiprocessing&#8221;的解决方法，就是在app目录根目录下建个_multiprocessing.py，内容为： import multiprocessing<br />
测试了下果然不然报错，并且能准备指出错误在哪儿了。最后是这个fix的真正<a href="http://code.google.com/p/googleappengine/issues/detail?id=1504#c7">出处</a>。奇怪为啥以前没搜到呢 =.=!</p>
<p>最后贴一下GAE SDK分别跑在2.6和2.5环境下的运行环境参数：<br />
<a href="http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runok.png">http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py26_runok.png</a><br />
<a href="http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runok.png">http://vvoody.org/blog/wp-content/uploads/2010/04/gae_py25_runok.png</a></p>
<p><font color="red">Update 5-20:</font><br />
再举个不推荐用2.6跑gae sdk的例子。<br />
Google SDK 1.3.4刚发布，对dev_appserver增加了自动执行task的特性，以后再也不用手工去按那个&#8217;run&#8217;按钮了。但是，在python 2.6环境下无效，task不会自动执行。起初我以为是task code写的不对，或者这个特性有什么限制，在gae的google groups上帖子都写了一半。然后突然想起是不是python版本的问题，在dev_appserver.py改python环境为2.5.2，这回终于能自动执行了 =.=! 浪费了很多时间，血的教训。</p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=593</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>找出字幕中的生词</title>
		<link>http://vvoody.org/blog/?p=588</link>
		<comments>http://vvoody.org/blog/?p=588#comments</comments>
		<pubDate>Tue, 13 Apr 2010 13:01:33 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[pickupnewords]]></category>
		<category><![CDATA[srt]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=588</guid>
		<description><![CDATA[写了小程序(pickupnewords.py)可以找出文本中的英文生词，比如你在观影前可以找出英文字幕中你不认识的单词，逐一查明，这样就不会边看边查字典了，打扰你欣赏电影了 ^_^ 程序最新源代码在github。下面简单说明一些关于这个程序的东西。 我这程序肯定无法强大到能读取你大脑的信息得知你认不认识某个单词，它要借助本地存储，其实就是一个用pickle模块把你已经认识的单词集合写入到一个文件里，程序因此有了依据。当然了不可能把&#8217;is&#8217;、&#8217;apple&#8217;这样的词也判为生词，因此得有个基础单词库，我用的是Oxford 3000 wordlist，这个是牛津字典的单词释义所用的基础单词，我已经把它转换好了，文件名是oldwords.dat。一个没有记忆不会学习的人是可怕的，程序也是如此，这是我下面要讲的。 许多英语达人的词汇量肯定不止3000，所以在初期运行这个程序你会发现有好多单词你都认识，或者日后某些单词反复出现，慢慢你已经熟知了，那么就需要让程序记住这些单词。pickupnewords.py提供了一个非常简单甚至简陋的命令接口，告诉程序哪些单词需要记忆。再列出可能的生词列表后，程序会等待你输入指令了。你能输入的指令有下列几种： 0,9,13, 21 生词列表的每个单词前都有个序号，你输入了哪几个序号程序就会记住对应的单词 !0,9,13, 21 这个仅仅比上面的多了一个感叹号&#8220;!&#8221;，它的意思就是相反，除了感叹号后面列出的序号对应的单词都要记忆 all 记住所有列出的单词 ! 或 !all 或 直接回车 不记忆列出的任何单词，它们都是生词 使用方法： 下载pickupnewords.py和oldwords.dat，运行： python pickupnewords.py /path/to/your/english.srt 注：本程序只支持srt这类的纯文本环保格式。 任何问题建议欢迎留言 ===== 补充 ===== 单词的分词处理的十分简单，能去掉字幕文件中无意义、非英文单词的部分，但对于诸如&#8221;I&#8217;ve&#8221;、&#8221;shouldn&#8217;t&#8221;识别为一个单词，&#8221;copied&#8221;、&#8221;driving&#8221;这样的过去分词和现在分词仍然作为生词，虽然原型是非常基础的单词。Python应该有好的分词库(我了解的不多，如有好的也请推荐)，但我不想把事情搞的太复杂了，我们完全可以把这些词让程序记住，或者干脆忽略，反正除此之外能找出真正的生词就行。 Update 4-21: @weakish 在下面的留言说的很对。其实这个程序离真正可用还很远，还需要优化。]]></description>
			<content:encoded><![CDATA[<p>写了小程序(pickupnewords.py)可以找出文本中的英文生词，比如你在观影前可以找出英文字幕中你不认识的单词，逐一查明，这样就不会边看边查字典了，打扰你欣赏电影了 ^_^</p>
<p>程序最新源代码在<a href="http://github.com/vvoody/helloworld/tree/master/python/pickupnewords/">github</a>。下面简单说明一些关于这个程序的东西。</p>
<p>我这程序肯定无法强大到能读取你大脑的信息得知你认不认识某个单词，它要借助本地存储，其实就是一个用pickle模块把你已经认识的单词集合写入到一个文件里，程序因此有了依据。当然了不可能把&#8217;is&#8217;、&#8217;apple&#8217;这样的词也判为生词，因此得有个基础单词库，我用的是<a href="http://www.oup.com/elt/catalogue/teachersites/oald7/oxford_3000/oxford_3000_list?cc=global">Oxford 3000 wordlist</a>，这个是牛津字典的单词释义所用的基础单词，我已经把它转换好了，文件名是oldwords.dat。一个没有记忆不会学习的人是可怕的，程序也是如此，这是我下面要讲的。</p>
<p>许多英语达人的词汇量肯定不止3000，所以在初期运行这个程序你会发现有好多单词你都认识，或者日后某些单词反复出现，慢慢你已经熟知了，那么就需要让程序记住这些单词。pickupnewords.py提供了一个非常简单甚至简陋的命令接口，告诉程序哪些单词需要记忆。再列出可能的生词列表后，程序会等待你输入指令了。你能输入的指令有下列几种：</p>
<ul>
<li><strong>0,9,13, 21</strong></li>
<p>生词列表的每个单词前都有个序号，你输入了哪几个序号程序就会记住对应的单词</p>
<li><strong>!0,9,13, 21</strong></li>
<p>这个仅仅比上面的多了一个感叹号<strong>&#8220;!&#8221;</strong>，它的意思就是相反，除了感叹号后面列出的序号对应的单词都要记忆</p>
<li><strong>all</strong></li>
<p>记住所有列出的单词</p>
<li><strong>!</strong> 或 <strong>!all</strong> 或 <strong>直接回车</strong></li>
<p>不记忆列出的任何单词，它们都是生词
</ul>
<p><strong>使用方法：</strong><br />
下载pickupnewords.py和oldwords.dat，运行：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python pickupnewords.py <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>your<span style="color: #000000; font-weight: bold;">/</span>english.srt</pre></div></div>

<p>注：本程序只支持<a href="http://en.wikipedia.org/wiki/SubRip">srt</a>这类的纯文本环保格式。<br />
任何问题建议欢迎留言 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>===== 补充 =====<br />
单词的分词处理的十分简单，能去掉字幕文件中无意义、非英文单词的部分，但对于诸如&#8221;I&#8217;ve&#8221;、&#8221;shouldn&#8217;t&#8221;识别为一个单词，&#8221;copied&#8221;、&#8221;driving&#8221;这样的过去分词和现在分词仍然作为生词，虽然原型是非常基础的单词。Python应该有好的分词库(我了解的不多，如有好的也请推荐)，但我不想把事情搞的太复杂了，我们完全可以把这些词让程序记住，或者干脆忽略，反正除此之外能找出真正的生词就行。</p>
<p><font color="red">Update 4-21:</font><br />
@weakish 在下面的留言说的很对。其实这个程序离真正可用还很远，还需要优化。</p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=588</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Blogging with Emacs</title>
		<link>http://vvoody.org/blog/?p=498</link>
		<comments>http://vvoody.org/blog/?p=498#comments</comments>
		<pubDate>Thu, 04 Mar 2010 02:53:24 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Emacs]]></category>
		<category><![CDATA[elisp]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=498</guid>
		<description><![CDATA[用Emacs写博客 发表至WordPress howto]]></description>
			<content:encoded><![CDATA[<p>用<strong>Emacs</strong>写博客<br />
发表至<a href="http://wordpress.org/">WordPress</a> <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /><br />
<a href="http://vvoody.org/blog/?p=71">howto</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=498</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>对gtap的一些wordaround</title>
		<link>http://vvoody.org/blog/?p=447</link>
		<comments>http://vvoody.org/blog/?p=447#comments</comments>
		<pubDate>Sat, 27 Feb 2010 16:14:00 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[GAE]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[GFW]]></category>
		<category><![CDATA[gtap]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=447</guid>
		<description><![CDATA[前两天发现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&#40;webapp.RequestHandler&#41;: origUrl = self.request.url origBody = self.request.body &#40;scm, netloc, path, params, query, _&#41; = urlparse.urlparse&#40;origUrl&#41; + path = path&#91;5:&#93; # skip '/gtap' if path == '/': self.myOutput&#40;'text/html', 'here is the proxy of \&#34;twitter.com\&#34; by GTAP [...]]]></description>
			<content:encoded><![CDATA[<p>前两天发现<a href="http://code.google.com/p/gtap/">gtap</a>这个项目，也是个Twitter API代理，基于GAE(Python)。想着Choqok、qwit都没法用birdnest，所以架了个玩玩。结果弄出一堆事来 =.=!</p>
<p><strong>先是</strong>把gtap和其它几个app放在一起，如我<a href="http://vvoody.org/blog/?p=367">上篇文章</a>所讲的。这个挺简单：</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">diff --git a/gtap.py b/gtap.py                                                                                  
index 1b<span style="color: #440088;">9d8</span>ed..472157d <span style="">100644</span>                                                                                   
<span style="color: #888822;">--- a/gtap.py                                                                                                   </span>
<span style="color: #888822;">+++ b/gtap.py                                                                                                   </span>
<span style="color: #440088;">@@ -<span style="">16</span>,<span style="">6</span> +<span style="">16</span>,<span style="">7</span> @@ class MainPage<span style="">&#40;</span>webapp.RequestHandler<span style="">&#41;</span>:                                                        </span>
         origUrl = self.request.url                                                                             
         origBody = self.request.body
         <span style="">&#40;</span>scm, netloc, path, params, query, _<span style="">&#41;</span> = urlparse.urlparse<span style="">&#40;</span>origUrl<span style="">&#41;</span>
<span style="color: #00b000;">+        path = path<span style="">&#91;</span><span style="">5</span>:<span style="">&#93;</span>  # skip '/gtap'</span>
         if path == '/':
             self.myOutput<span style="">&#40;</span>'text/html', 'here is the proxy of \&quot;twitter.com\&quot; by GTAP %s !' % <span style="">&#40;</span>gtapVersion<span style="">&#41;</span><span style="">&#41;</span>
         else:
<span style="color: #440088;">@@ -<span style="">59</span>,<span style="">7</span> +<span style="">60</span>,<span style="">7</span> @@ class MainPage<span style="">&#40;</span>webapp.RequestHandler<span style="">&#41;</span>:</span>
         self.doProxy<span style="">&#40;</span>'get'<span style="">&#41;</span>
&nbsp;
 def main<span style="">&#40;</span><span style="">&#41;</span>:
<span style="color: #991111;">-    application = webapp.WSGIApplication<span style="">&#40;</span> <span style="">&#91;</span><span style="">&#40;</span>r'/.*', MainPage<span style="">&#41;</span><span style="">&#93;</span>, debug=True<span style="">&#41;</span></span>
<span style="color: #00b000;">+    application = webapp.WSGIApplication<span style="">&#40;</span> <span style="">&#91;</span><span style="">&#40;</span>r'/gtap/.*', MainPage<span style="">&#41;</span><span style="">&#93;</span>, debug=True<span style="">&#41;</span></span>
     wsgiref.handlers.CGIHandler<span style="">&#40;</span><span style="">&#41;</span>.run<span style="">&#40;</span>application<span style="">&#41;</span>
&nbsp;
 if __name__ == &quot;__main__&quot;:</pre></div></div>

<p>在app.xml里加上：</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">- url: /gtap/.*
  script: gtap.py
#  secure: always</pre></div></div>

<p><em>如果你把gtap单独架设在gae上的，而不是和几个app一起放在yourapp.appspot.com上的话，这步不需要。</em></p>
<p><strong>接着</strong>，发现Choqok等客户端发出的用户身份验证请求是到api.twitter.com，但http://api.twitter.com/account/verify_credentials.xml这样请求无效，改成http://twitter.com/account/verify_credentials.xml即可：</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">diff --git a/gtap.py b/gtap.py
index 472157d..f50f2dc <span style="">100644</span>
<span style="color: #888822;">--- a/gtap.py</span>
<span style="color: #888822;">+++ b/gtap.py</span>
<span style="color: #440088;">@@ -<span style="">36</span>,<span style="">7</span> +<span style="">39</span>,<span style="">7</span> @@ class MainPage<span style="">&#40;</span>webapp.RequestHandler<span style="">&#41;</span>:</span>
                 netloc = 'search.twitter.com'
                 newpath = path<span style="">&#91;</span><span style="">7</span>:<span style="">&#93;</span>
             elif path_parts<span style="">&#91;</span><span style="">1</span><span style="">&#93;</span> == 'api':
<span style="color: #991111;">-                netloc = 'api.twitter.com'</span>
<span style="color: #00b000;">+                netloc = 'twitter.com'</span>
                 newpath = path<span style="">&#91;</span><span style="">4</span>:<span style="">&#93;</span>
             else:
                 netloc = 'twitter.com'</pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">diff --git a/gtap.py b/gtap.py
index 472157d..f50f2dc <span style="">100644</span>
<span style="color: #888822;">--- a/gtap.py</span>
<span style="color: #888822;">+++ b/gtap.py</span>
<span style="color: #440088;">@@ -<span style="">22</span>,<span style="">6</span> +<span style="">22</span>,<span style="">9</span> @@ class MainPage<span style="">&#40;</span>webapp.RequestHandler<span style="">&#41;</span>:</span>
         else:
             if 'Authorization' not in self.request.headers :
                 headers = <span style="">&#123;</span><span style="">&#125;</span>
<span style="color: #00b000;">+                self.response.set_status<span style="">&#40;</span><span style="">401</span>, message=&quot;Unauthorized&quot;<span style="">&#41;</span></span>
<span style="color: #00b000;">+                self.response.headers.add_header<span style="">&#40;</span>'WWW-Authenticate', 'Basic realm=&quot;Secure Area&quot;'<span style="">&#41;</span></span>
<span style="color: #00b000;">+                self.response.out.write<span style="">&#40;</span>&quot;<span style="">401</span>&quot;<span style="">&#41;</span></span>
             else:
                 auth_header = self.request.headers<span style="">&#91;</span>'Authorization'<span style="">&#93;</span>
                 auth_parts = auth_header.split<span style="">&#40;</span>' '<span style="">&#41;</span></pre></div></div>

<p>原理是如果客户端的http请求头部没有Authorization字段，那么gtap返回&#8221;401 Unauthorized&#8221;，让它重新发送用户验证信息。再次抓包，Choqok第一次还是没有Authorization，接着就收到服务器发来的401状态码，于是它乖乖的再次发送请求并包含Authorization。</p>
<p>这样改之后echofon等依然可以正常使用gtap的api代理。也许你有注意到我在app.xml里注释掉了使用安全链接&#8221;#  secure: always&#8221;，经测试Choqok在http下可以正常处理收发tweets以及其它api操作，但改用https后，发推就不行了，其它还是可以的。Qwit因为貌似不支持https，所以只能用http的。</p>
<p>虽然经过这么workaround，Choqok、Qwit能看推发推了，但我还是觉得Choqok这个客户端自身有些问题，因为如果换用twip这个api代理的话，无论http、https都能正常使用，偏偏birdnest和gtap的不行。如果说gtap应用少的话，birdnest可是使用广泛的twitter api代理啊，<a href="http://vvoody.org/blog/?p=317">我的Twitter Opera Widget就用的它</a>。不想再折腾了，如果你也在用gtap，希望本文能给你些帮助 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>唉，连续两篇博文在讲twitter api代理的事儿了，老外上个网哪有天朝这么多的屁事，我朝屁民们在代理的事上浪费多少时间啊&#8230;</p>
<p><strong>参考：</strong><br />
[1] <a href="http://kevin.9511.net/archives/332.html">基本连接验证(Basic Access Authorization)的原理</a><br />
[2] <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">Status Code Definitions</a><br />
[3] <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8">Authorization</a><br />
[4] <a href="http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#z9">HTTP Request fields</a><br />
[5] <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">List of HTTP status codes</a><br />
[6] <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">Basic access authentication</a></p>
<p><strong><font color="red">UPDATE</font></strong> 2010-3-1<br />
gtap的作者<a href="https://twitter.com/rui7905">@rui7905</a>非常迅速地更新到了0.3版，修正了我这篇文章提到的问题，并且做了原因分析，感兴趣得朋友移步<a href="http://code.google.com/p/gtap/issues/detail?id=3">讨论页</a>。如果你用gtap，不要再用在下workaround的拙作了，升级到0.3吧~~</p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=447</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>使gtap与其它app脚本共存</title>
		<link>http://vvoody.org/blog/?p=367</link>
		<comments>http://vvoody.org/blog/?p=367#comments</comments>
		<pubDate>Thu, 11 Feb 2010 13:32:47 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[GAE]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[birdnest]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[gtap]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[operamini]]></category>
		<category><![CDATA[opm]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=367</guid>
		<description><![CDATA[目的是想将Birdnest和opm-server-mirror合二为一。前者是Twitter的API proxy，后者是Opera Mini的代理，均基于Google App Engine(简称GAE)。一个GAE账户只能建10个app，分别在GAE上建这两个代理不免有些浪费。另一方面，多一个地址也不好记，我希望能够一个GAE app上面同时跑多个应用，记一个地址就行了，嘿嘿～ 本文假设你会在GAE上建应用。 UPDATE 2010-09-03 gtap-0.4版的修改方法见： http://code.google.com/p/gtap/issues/detail?id=73 要把Birdnest和opm-server-mirror放在一个app里其实改动并不多。 checkout birdnest svn co -r 97 http://birdnest.googlecode.com/svn/branches/gae birdnest_r97 注意一定要r97的，因为作者最近更新过code.py了，导致&#8221;internal sever error&#8221;，可能是因为GAE不支持socket模块的原因。就是因为co的版本不对我白弄了好久。。。 下载opm-server-mirror的opm.py，放到birdnest的目录中，并作如下改动： --- opm.py 2010-02-11 21:06:12.577148400 +0800 +++ opm &#40;2&#41;.py 2010-02-11 13:04:15.739257800 +0800 @@ -29,7 +29,7 @@ self.response.out.write&#40;result.content&#41; &#160; application = webapp.WSGIApplication&#40; - &#91;&#40;'/', MainPage&#41;&#93;, + &#91;&#40;'/opm/', MainPage&#41;&#93;, debug=True&#41; &#160; def main&#40;&#41;: 更改birdnest的app.yaml： [...]]]></description>
			<content:encoded><![CDATA[<p>目的是想将Birdnest和opm-server-mirror合二为一。前者是Twitter的API proxy，后者是Opera Mini的代理，均基于Google App Engine(简称GAE)。一个GAE账户只能建10个app，分别在GAE上建这两个代理不免有些浪费。另一方面，多一个地址也不好记，我希望能够一个GAE app上面同时跑多个应用，记一个地址就行了，嘿嘿～</p>
<p>本文假设你会在GAE上建应用。<br />
<font color="red">UPDATE 2010-09-03</font><br />
gtap-0.4版的修改方法见： <a href="http://code.google.com/p/gtap/issues/detail?id=73">http://code.google.com/p/gtap/issues/detail?id=73</a></p>
<p>要把Birdnest和opm-server-mirror放在一个app里其实改动并不多。</p>
<ol>
<li>checkout birdnest</li>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">svn</span> <span style="color: #c20cb9; font-weight: bold;">co</span> <span style="color: #660033;">-r</span> <span style="color: #000000;">97</span> http:<span style="color: #000000; font-weight: bold;">//</span>birdnest.googlecode.com<span style="color: #000000; font-weight: bold;">/</span>svn<span style="color: #000000; font-weight: bold;">/</span>branches<span style="color: #000000; font-weight: bold;">/</span>gae birdnest_r97</pre></div></div>

<p>注意一定要<font color="red">r97</font>的，因为作者最近更新过code.py了，导致&#8221;internal sever error&#8221;，可能是因为GAE不支持socket模块的原因。就是因为co的版本不对我白弄了好久。。。</p>
<li>下载opm-server-mirror的<a href="http://opm-server-mirror.googlecode.com/svn/trunk/opm-server/python/opm.py">opm.py</a>，放到birdnest的目录中，并作如下改动：</li>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">--- opm.py	<span style="">2010</span>-02-<span style="">11</span> <span style="">21</span>:06:<span style="">12.577148400</span> +0800
<span style="color: #888822;">+++ opm <span style="">&#40;</span><span style="">2</span><span style="">&#41;</span>.py	<span style="">2010</span>-02-<span style="">11</span> <span style="">13</span>:04:<span style="">15.739257800</span> +0800</span>
<span style="color: #440088;">@@ -<span style="">29</span>,<span style="">7</span> +<span style="">29</span>,<span style="">7</span> @@</span>
           self.response.out.write<span style="">&#40;</span>result.content<span style="">&#41;</span>
&nbsp;
 application = webapp.WSGIApplication<span style="">&#40;</span>
<span style="color: #991111;">-                                     <span style="">&#91;</span><span style="">&#40;</span>'/', MainPage<span style="">&#41;</span><span style="">&#93;</span>,</span>
<span style="color: #00b000;">+                                     <span style="">&#91;</span><span style="">&#40;</span>'/opm/', MainPage<span style="">&#41;</span><span style="">&#93;</span>,</span>
                                      debug=True<span style="">&#41;</span>
&nbsp;
 def main<span style="">&#40;</span><span style="">&#41;</span>:</pre></div></div>

<li>更改birdnest的app.yaml：</li>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">--- app.yaml	<span style="">2010</span>-02-<span style="">11</span> <span style="">20</span>:<span style="">56</span>:<span style="">34.778320300</span> +0800
<span style="color: #888822;">+++ app <span style="">&#40;</span><span style="">2</span><span style="">&#41;</span>.yaml	<span style="">2010</span>-02-<span style="">11</span> <span style="">21</span>:<span style="">22</span>:<span style="">18.383789000</span> +0800</span>
<span style="color: #440088;">@@ -<span style="">12</span>,<span style="">6</span> +<span style="">12</span>,<span style="">8</span> @@</span>
   script: code.py
 - url: /image/.*
   script: code.py
<span style="color: #00b000;">+- url: /opm/.*</span>
<span style="color: #00b000;">+  script: opm.py</span>
 - url: /
   static_files: index.html
   upload: index.html</pre></div></div>

</ol>
<p>最后appcfg.py update birdnest_r97上传至GAE，好了。以后你给twitter客户端设api代理的时候就用 http://fckgfw.appspot.com/<font color="red">api</font>/，给Opera Mini设代理则用 http://fckgfw.appsot.com/<font color="red">opm</font>/ 。嗯，和谐了。</p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=367</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>迁移旧硬盘上的Linux到新硬盘(LVM)</title>
		<link>http://vvoody.org/blog/?p=359</link>
		<comments>http://vvoody.org/blog/?p=359#comments</comments>
		<pubDate>Sun, 07 Feb 2010 14:49:45 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[chroot]]></category>
		<category><![CDATA[fstab]]></category>
		<category><![CDATA[LILO]]></category>
		<category><![CDATA[LVM]]></category>
		<category><![CDATA[Migration]]></category>
		<category><![CDATA[Slackware]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=359</guid>
		<description><![CDATA[买了块新的大硬盘，准备把原先硬盘上的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 [...]]]></description>
			<content:encoded><![CDATA[<p>买了块新的大硬盘，准备把原先硬盘上的Slackware迁移过去，并且采用LVM，xp不要了换成Win7。记录下迁移过程和遇到的一些问题及解决方法。</p>
<ul>
<li>用Slackware 13.0 dvd系统盘引导启动，并分区。Slackware <a href="http://slackware.osuosl.org/slackware-13.0/README_LVM.TXT">从12.0开始支持安装系统到LVM</a>。</li>
<p><code><br />
Device     Boot      Start         End      Blocks   Id  System<br />
/dev/sda1   *           1          13      102400    7  HPFS/NTFS<br />
/dev/sda2              13        2611    20869120    7  HPFS/NTFS<br />
/dev/sda3            2611        3917    10485760    c  W95 FAT32 (LBA)<br />
/dev/sda4            3917       38913   281110368+   5  Extended<br />
/dev/sda5            3917        3981      519047   83  Linux<br />
/dev/sda6            3982        4504     4200966   82  Linux swap<br />
/dev/sda7            4505       38913   276390261   8e  Linux LVM</code></p>
<p>这个是我新硬盘的最终分区情况。sda1是Win7保留的100M启动分区，sda2是Win7系统盘，sda3是D盘。500M大的sda5我原本想作为/boot，不过目前我就Win7+Slackware+LILO不需要，留作未来使用吧。swap(sda6)没有用LVM，剩下的260多G(sda7)都交给LVM管理了。</p>
<li>建立LV分区并激活</li>
<p><code><br />
pvcreate /dev/sda7<br />
vgcreate MYVG /dev/sda7<br />
lvcreate -L 20G -n ROOT MYVG<br />
lvcreate -L 10G -n USRLOCAL MYVG<br />
lvcreate -L 100G -n DATA MYVG<br />
lvcreate -L 50G -n HOME MYVG</p>
<p>vgscan --mknodes<br />
vgchange -ay<br />
</code></p>
<li>格式化LV分区并挂载到新的root目录</li>
<p><code><br />
mkreiserfs /dev/MYVG/ROOT<br />
mkreiserfs /dev/MYVG/USRLOCAL<br />
mkreiserfs /dev/MYVG/HOME</p>
<p>mkdir /new_root<br />
mount -t reiserfs /dev/MYVG/ROOT /new_root<br />
mkdir -p /new_root/usr/local<br />
mount -t reiserfs /dev/MYVG/USRLOCAL /new_root/usr/local<br />
mkdir /new_root/home<br />
mount -t reiserfs /dev/MYVG/HOME /new_root/home<br />
</code></p>
<li>挂载旧硬盘上的系统目录到旧root目录</li>
<p><code><br />
mkdir /old_root<br />
mount -t reiserfs /dev/sda5 /old_root<br />
mount -t reiserfs /dev/sda7 /old_root/usr/local<br />
mount -t reiserfs /dev/sda8 /old_root/usr/local/opt<br />
mount -t reiserfs /dev/sda9 /old_root/home<br />
</code></p>
<p>又买了个移动硬盘盒，旧硬盘就可以当移动硬盘了。</p>
<li>迁移(复制)旧系统到新硬盘</li>
<p><code><br />
cd /old_root<br />
/old_root/bin/tar cpBf - . --exclude=tmp/* | ( cd /new_root &#038;&#038; /old_root/bin/tar xvpBf -)<br />
</code></p>
<p>漫长的等待&#8230;&#8230; /dev 啥的统统要拷过来。根据参考[5]，到这里接着用直接chroot后就可以mkinitrd和lilo了，但事实不是这样的，还得额外多些操作。</p>
<li>chroot到/new_root，制作initrd和LILO</li>
<p><code><br />
mount --bind /proc /new_root/proc<br />
mount --bind /sys /new_root/sys<br />
mount --bind /dev /new_root/dev<br />
chroot /new_root<br />
cd /boot<br />
mkinitrd -c -k 2.6.29.6-smp -m reiserfs -f reiserfs -r /dev/MYVG/ROOT -L -o /boot/initrd.gz<br />
vim /etc/lilo.conf<br />
lilo -v<br />
</code></p>
<p>三行mount &#8211;bind是必须的，slackware的<a href="http://slackware.osuosl.org/slackware-13.0/README_LVM.TXT">README_LVM.TXT</a>说安装程序会将/proc和/sys挂载上，但我目前不是全新安装没有使用setup安装程序，而且我运行setup企图让它帮我挂载/proc等未果 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  所以得用&#8211;bind(见参考[6])，不过我不是很了解这个选项。不这么mount的话执行mkinitrd会出现cat /proc/partitions错误，执行lilo会出现 Fatal: raid_setup: stat(&#8220;/dev/sda&#8221;)。</p>
<p>/etc/lilo.conf 也作相应的调整：<br />
<code><br />
boot="/dev/sda"<br />
......<br />
image="/boot/vmlinuz"<br />
        initrd="/boot/initrd.gz"<br />
        root="/dev/MYVG/ROOT"<br />
        label="2.6.29.6-smp"<br />
        read-only<br />
# Linux bootable partition config ends<br />
# Windows bootable partition config begins<br />
other = /dev/sda1<br />
        label="Windows7"<br />
  table = /dev/sda<br />
# Windows bootable partition config ends<br />
</code></p>
<p>Win7的引导分区是sda1，不是系统盘sda2。马上就要好了 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<li>在新系统的/dev目录下建立LVM设备文件</li>
<p><code><br />
exit # 退出chroot<br />
umount /new_root/dev<br />
chroot /new_root<br />
vgscan --mknodes<br />
vgchange -ay<br />
</code></p>
<p>如果没有这一步，重启后LILO引导菜单已经可以看见，Win7引导正常，Slackware能引导起来，但是在挂载文件系统是提示找不到 /dev/MYVG/ROOT 文件。于是我就如上这么干了，在/dev下就会有MYVG/ROOT等LV设备文件了。不过我不太明白，必须得通过vgscan &#8211;mknodes的方式来建立几个lv分区的设备文件吗？那/dev/sda文件应该是我旧系统上复制过来的，换了硬盘后能直接使用？啊呀，这方面知识太欠缺了，我自己已经没法解释了，望路过的朋友帮我解惑一下 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<li>建立fstab文件</li>
<p><code><br />
/dev/sda6           swap             swap        defaults         0   0<br />
/dev/MYVG/ROOT      /                reiserfs    defaults         1   1<br />
/dev/MYVG/USRLOCAL  /usr/local       reiserfs    defaults         1   2<br />
/dev/MYVG/HOME      /home            reiserfs    defaults         1   2<br />
/dev/sda3           /media/D         vfat        uid=0,umask=0022,fmask=0111,shortname=mixed,iocharset=utf8        0   0<br />
/dev/cdrom          /mnt/cdrom       auto        defaults,user,ro,noexec  0   0<br />
devpts              /dev/pts         devpts      gid=5,mode=620   0   0<br />
proc                /proc            proc        defaults         0   0<br />
</code>
</ul>
<p>至此我的系统迁移完毕。这一次让我发现又有很多不懂不明白啊~~~</p>
<p><strong>参考：</strong><br />
[1] <a href="http://www.ibm.com/developerworks/cn/linux/filesystem/lvm/lvm-1/index.html">通用线程: 学习 Linux LVM，第 1 部分</a><br />
[2] <a href="http://www.ibm.com/developerworks/cn/linux/filesystem/lvm/lvm-2/">通用线程：学习 Linux LVM，第 2部分</a><br />
[3] <a href="http://http://slackware.osuosl.org/slackware-13.0/README_LVM.TXT">README_LVM.TXT</a><br />
[4] <a href="http://vvoody.org/blog/wp-content/uploads/2010/02/lvm_whitepaper.pdf">LVM White Paper</a> 本地PDF文件<br />
[5] <a href="http://www.unixwerk.eu/linux/slack/lvm2root.html">Slackware 12.1 on LVM &#8211; Installation and Migration</a><br />
[6] <a href="http://forums.lunar-linux.org/viewtopic1323.html?t=467">Backup almost working, LILO hangs</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=359</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>承上启下</title>
		<link>http://vvoody.org/blog/?p=356</link>
		<comments>http://vvoody.org/blog/?p=356#comments</comments>
		<pubDate>Thu, 31 Dec 2009 15:17:28 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[vvoody]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=356</guid>
		<description><![CDATA[年头那几天跟@hkai同学聊起某事件似乎才刚发生过，2009就只剩1个多小时了。有08奥运今年开的的错觉，才发现这一年太多荒唐可笑之事发生在每个人身边。我总是记不清这些事件的具体时间，因为它们太应接不暇了，因为它们仍然在继续演出着。 昨天刚结束了一种生活状态，就和当年高二升高三分班一样，还处在镇痛期。09年许多事情让我比较清醒地认识到了自己的性格弱点，不管某个结果如何，未来的一年我都将迎来全新的生活。 2010我希望自己继续善其身，也希望能为争取个人权利多做些什么；希望肉食者能够偶尔吃点蔬菜，清清自己的宿便；更希望有那么一个人与我一起共赏这纠结而又精彩美好的世界 这是一篇比微博长，比博客短的日志~ 新年快乐]]></description>
			<content:encoded><![CDATA[<p>年头那几天跟<a href="https://twitter.com/hkai">@hkai</a>同学聊起某事件似乎才刚发生过，2009就只剩1个多小时了。有08奥运今年开的的错觉，才发现这一年太多荒唐可笑之事发生在每个人身边。我总是记不清这些事件的具体时间，因为它们太应接不暇了，因为它们仍然在继续演出着。</p>
<p>昨天刚结束了一种生活状态，就和当年高二升高三分班一样，还处在镇痛期。09年许多事情让我比较清醒地认识到了自己的性格弱点，不管某个结果如何，未来的一年我都将迎来全新的生活。</p>
<p>2010我希望自己继续善其身，也希望能为争取个人权利多做些什么；希望肉食者能够偶尔吃点蔬菜，清清自己的宿便；更希望有那么一个人与我一起共赏这纠结而又精彩美好的世界 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>这是一篇比微博长，比博客短的日志~ 新年快乐 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=356</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>养一下驴子</title>
		<link>http://vvoody.org/blog/?p=353</link>
		<comments>http://vvoody.org/blog/?p=353#comments</comments>
		<pubDate>Sat, 19 Dec 2009 06:10:23 +0000</pubDate>
		<dc:creator>vvoody</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ed2k]]></category>
		<category><![CDATA[eMule]]></category>
		<category><![CDATA[KAD]]></category>
		<category><![CDATA[MLDonkey]]></category>
		<category><![CDATA[mlnet]]></category>
		<category><![CDATA[nodes.dat]]></category>
		<category><![CDATA[P2P]]></category>
		<category><![CDATA[server.met]]></category>

		<guid isPermaLink="false">http://vvoody.org/blog/?p=353</guid>
		<description><![CDATA[用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");] 主要修改&#8221;server.met&#8221;和&#8221;nodes.gzip&#8221;两段，server.met用的参考[1]里提供的链接，设成0是表示只需在MLDonkey启动时载入; nodes.gzip用的参考[2]里提供的链接，设成1是表示每1小时更新一次。其他字段默认。 参考： [1] 安全eD2k服务器列表 2009-11-28 [2] Kad节点文件 nodes.dat [3] 终于可以在ubuntu上养驴了 [4] [问题]mldonkey可以连接kad吗？]]></description>
			<content:encoded><![CDATA[<p>用MLDonkey很久了下不热门的资源一直非常慢，以至失去用ed2k网络的兴趣了。最近才发现原来是我没有开启MLDonkey的KAD功能 -_____-!! 没有KAD之类的技术用P2P久失去了很大的乐趣。</p>
<p>下面记录下几点设置，我不太懂养驴子，应该还有使驴子跑得更快的设置，还请路过大大教教我 <img src='http://vvoody.org/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>1. MLDonkey里的enable_kademlia设为true</p>
<p>2. 网上看到说需要nodes.dat和contact.dat(其实这个文件不需要了，是eDonkey的Overnet网络，现在eMule的ed2k和KAD网络足矣)，而且还得手工添加。其实可以通过配置MLDonkey的download.ini文件来实现自动更新nodes.dat文件。</p>
<p>~/.mldonkey/download.ini<br />
 web_infos = [<br />
  ("server.met", 0, "http://sn.im/server.met");<br />
  ("nodes.gzip", 1, "http://upd.emule-security.net/nodes.dat");<br />
  ("contact.dat", 168, "http://download.overnet.org/contact.dat");<br />
  ("geoip.dat", 0, "http://www.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz");<br />
  ("guarding.p2p", 96, "http://www.bluetack.co.uk/config/level1.gz");<br />
  (hublist, 0, "http://dchublist.com/hublist.config.bz2");]</p>
<p>主要修改&#8221;server.met&#8221;和&#8221;nodes.gzip&#8221;两段，server.met用的参考[1]里提供的链接，设成0是表示只需在MLDonkey启动时载入; nodes.gzip用的参考[2]里提供的链接，设成1是表示每1小时更新一次。其他字段默认。</p>
<p>参考：<br />
[1] <a href="http://emule-fans.com/server-list-09-11-28/">安全eD2k服务器列表 2009-11-28</a><br />
[2] <a href="http://emule-fans.com/emule-kad-node-dat/">Kad节点文件 nodes.dat</a><br />
[3] <a href="https://lists.ubuntu.com/archives/ubuntu-zh/2005-August/000159.html">终于可以在ubuntu上养驴了</a><br />
[4] <a href="http://203.208.37.132/search?q=cache:E73eBCyj-4gJ:forum.ubuntu.org.cn/viewtopic.php%3Ff%3D73%26t%3D152949%26view%3Dprevious+kad_load+ov_load&#038;cd=2&#038;hl=zh-CN&#038;ct=clnk&#038;gl=cn&#038;st_usg=ALhdy2-_sgUyg_q6xdOKpU8DRmSMQKrIEw">[问题]mldonkey可以连接kad吗？</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vvoody.org/blog/?feed=rss2&amp;p=353</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
