<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[蜻蜓点水 举重若轻]]></title>
	  <link>http://eishn.blog.163.com</link>
	  <description><![CDATA[ 君子终日乾乾]]></description>
	  <language>zh-CN</language>
	  <pubDate>Thu, 17 May 2012 05:13:07 +0800</pubDate>
	  <lastBuildDate>Thu, 17 May 2012 05:13:07 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[eishn]]></managingEditor>
	  <webMaster><![CDATA[沈崴]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[蜻蜓点水 举重若轻]]></title>
	  	<url>http://img.bimg.126.net/photo/FlkqMvptMUXJR9TUObEkuA==/212795082393634857.jpg</url>
	  	<link>http://eishn.blog.163.com</link>
	  </image>
  <item>
  	<title><![CDATA[首届中国 PyCon 大会！让我们聚首上海]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201191381314841</link>
    <description><![CDATA[<div><p></p><center><img title="首届中国 PyCon 大会"  alt="首届中国 PyCon 大会"  src="http://img2.ph.126.net/OMCfUUjoghPuyrLEBsAYng==/2499497793207637612.png"  ></center><p></p>  <p>世界 Python 爱好者的顶级盛会 —— PyCon 大会将首次在中国举办！本次大会由（Python 软件基金会下的）PyCon.Org 正式授权 GTUG、TopGeek、CPyUG 等社区联合举办，由 Python 作者 Guido van Rossum 及其所在的 Google 公司提供关键支持。</p>  <p>本次大会云集了国内外最为杰出的 Python 开发者，国内 Python 领域的领军人物几乎悉数到场、作为 Python 重镇的各大知名公司几乎无一缺席，所有嘉宾都承诺将自己压箱底的 Python 绝活呈现给大家！我也会在大会上进行题为《Python，通向未来之路》的纯技术演讲，欢迎捧场。</p>  <p><br></p> <p><font size="5"  ></font></p><font size="5"  ><center>12 月，让我们聚首上海！ <br> <a style="text-decoration: none;" target="_blank" rel="nofollow" href="http://pycon.51qiangzuo.com/"  >大会订票已经开始 <strong>pycon.51qiangzuo.com</strong>&nbsp;手速一定要快哦！</a></center></font><p></p> <p><br></p>  <p>会议为期两天（12 月 3 日至 4 日），票价 60￥，全部用于会议期间的就餐费用，其余大会所有费用及礼品主要由 Google 等公司承担赞助。作为国内最大的赞助者之一，我们也同样很荣幸能够服务于广大中国 Python 爱好者。</p> <p><br></p> <p></p><center><img title="湖州迅普"  alt="湖州迅普"  src="http://img2.ph.126.net/2iNXIUGx1M6bi3rorErOyA==/576460752320426642.png"  style="height: 70px; margin: 0pt 10px; float: none; width: 164px;"  >&nbsp; <img title="遛宝"  alt="遛宝"  src="http://img3.ph.126.net/Kc_1Tw2MjBv-WGxbSREvYQ==/2522015791344490283.png"  style="margin: 0pt 10px; float: none;"  height="70"  width="106"  ></center></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201191381314841</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201191381314841</guid>
    <pubDate>Thu, 13 Oct 2011 22:13:32 +0800</pubDate>
    <dcterms:modified>2011-10-20T15:55:50+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[程序员的 100 种境界]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201102831731444</link>
    <description><![CDATA[<div><h2>境界零：混沌态、浆糊状（小白、新兵）</h2>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<img title="程序员的 100 种境界 - 沈崴 - 蜻蜓点水 举重若轻" alt="程序员的 100 种境界 - 沈崴 - 蜻蜓点水 举重若轻" src="http://image2.766.com/res/h009/h73/img200810141202482_s.jpg"></p>

<p>刚刚毕业、初出茅庐，有丰富把妹经验，无任何项目经验。</p>

<p>典型台词：“<span style="text-decoration:underline;">哇塞，薯熟你居然能写出这样这样酷的程序啊</span>”。</p>

<p>此时身为薯熟的你切不可信以为真，因为任何简单的程序对他们来说 ……</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
其实都是写不出来的。</p>

<p>技能：<span style="text-decoration:underline;">hello world!</span></p>

<p>经验：<span style="text-decoration:underline;">0 年</span></p>

<p>角色：<span style="text-decoration:underline;">新手村游荡者</span>（虽然 ID 很酷，但改变不了时常被怪虐的事实）</p>

<h2>境界一：CODE SMELL（IT 民工）</h2>

<p>对于一些不太残忍的需求，竟已经能够完成了！了不起。</p>

<p>技能：<span style="text-decoration:underline;">面向对象、无脑肉搏</span></p>

<p>经验：<span style="text-decoration:underline;">1 年</span></p>

<p>角色：<span style="text-decoration:underline;">肉盾、坦克、血牛</span></p>

<p>公司终于可以放心地把一些 “没那么关键” 的项目扔给他了。</p>

<p>但遗憾的是，公司绝大部分的编码工作其实都 “没那么关键”。
这很容易理解，因为 “管理层“ 是不写代码的，高手则忙着折腾那几行关键代码。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
兄弟！剩下的就全靠你啦。</p>

<p>在这个配合良好的团队中，身处一线承担 90% 的炮火，此时他们最需要的技能是 “吸引攻击” ……</p>

<p>“你每天编几个小时程序？能不能承受得起？”</p>

<p>“每天 77 小时，承受得起。”</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
—— 大家都露出了 YD 的笑容。</p>

<p>典型台词：“<span style="text-decoration:underline;">面向过程什么的最讨厌了</span>”。</p>

<p>其他常用语：“<span style="text-decoration:underline;">瀑布模型什么的最讨厌了</span>”。</p>

<p>高手很快从他们这些代码中闻到了坏味道，至于是 “不够面向” 或者 “不够工程” 导致的，
还是他们根本就没空清理代码，这是一个迷。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<img title="" alt="" src="http://img03.taobaocdn.com/bao/uploaded/i7/T1B4lEXXVtXXblE7.V_021449.jpg_310x310.jpg" style="width: 200px;"></p>

<p>当然说句公道话，我们知道程序上线后能死撑多久，是和味道无关的。</p>

<p>赶时间随便凑起来的代码基本是稳定的，被自己恶心到于是下决心认真经营的那些代码一般会随机崩溃。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
显然这只和人品相关。</p>

<h2>境界二：SUCKS（TEAM LEADER、架构师、高手）</h2>

<p>对于一些不太残忍的需求，竟已经能够华丽丽地完成了！了不起。</p>

<p>对仍在 “新手村论坛” 上转悠的那些童鞋们，你简直就是神一样的存在。
别犹豫了，不是新手的坏家伙毕竟是少数，你的确就是神一样的存在。</p>

<p>“虽然我那几千行没有一行是实际做事情的，但是，架构很重要” 你说道，“你懂的”。</p>

<p>次日 ……</p>

<p>“虽然我那几千行是面向复用和好味道设计的，但是，重构很重要” 你说道，“所以我重写了”。</p>

<p>技能：<span style="text-decoration:underline;">设计模式、软件工程、ppt</span></p>

<p>经验：<span style="text-decoration:underline;">2 年</span></p>

<p>角色：<span style="text-decoration:underline;">TEAM LEADER</span></p>

<p>典型台词：“<span style="text-decoration:underline;">我们的目标是，木有一行重复代码</span>”。</p>

<p>正如预想的那样，很不幸，战斗顺利演变为缠绵悱侧的恶斗。
大伙抬起头遥望天边如血的残阳，麻的，又要甲板。</p>

<p>是的，项目延期，再次地。</p>

<p>大家已经数不清曾经已经延期了多少项目。
但好像，项目保质保量按时完成的情况，就如同新闻联播中的传说，似乎从来没有出现过。</p>

<p>似乎 LEADER 再次给出了乐观得不行的预期，虽然工期是三个月，但是我们都知道没有三年是搞不掂这事的
 —— 但更迫在眉睫的是公司会在三年内上市（虽然公司今年夏天才开张）。</p>

<p>如果不够乐观，这种不给力的感觉，届时老板会毫不犹豫地把这个部门裁掉，然后找一堆更便宜，并且更加乐观得不行的家伙把你们替换掉。</p>

<p>要知道网上无所不能，并且对现实工资非常不满的程序员遍地都是。面对这个残酷的现实，你必须乐观起来才行！</p>

<p>……</p>

<p>经过数年的延期，终于赶在公司上市前把项目搞定了，谢天谢地。
在万分危急的最后一刻，LEADER 再次 “重构” 了整个系统，团队终于逃出生天。</p>

<p>然而在一个阴暗的角落，是主程冷峻的目光，注视着高手们的代码。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<img title="" alt="" src="http://images6.cpcache.com/product/4396016v0_350x350_Back.jpg" style="width: 200px;"></p>

<p>“SUCKS！” 从他的牙缝中迸出几个字，轻蔑在他的嘴角蔓延。</p>

<h2>境界三：MAGIC（主程）</h2>

<p>技能：精通各种 <span style="text-decoration:underline;">MAGIC</span> 和 <span style="text-decoration:underline;">HACK</span></p>

<p>经验：<span style="text-decoration:underline;">3 年</span></p>

<p>角色：<span style="text-decoration:underline;">法师</span></p>

<p>典型台词：“<span style="text-decoration:underline;">IE 的这个 BUG 只要用 IE 另外的一个 BUG 就可以解决了</span>”。</p>

<p>你曾经不小心看到了主程的源码，这个文件充斥着大量注释为（也是唯一的一种注释）“HACK” 的代码，剩下的则全都是 MAGIC。
从此你就很后悔因为好奇打开了这个文件。</p>

<p>后来主程去了纳尼亚，你的朋友小明就奉命继续维护他的代码，这从一开始就是一个错误，其中一个 BUG 花了他将近两年的时间 —— 仍然没有搞定。
所以后来小明也去了纳尼亚。</p>

<p>幸运的是你接手了小明的工作，你试图说服公司，与其在主程的程序里调试，重新实现一遍要快得多。</p>

<p>公司冷酷的答复是，不行。这是公司宝贵的精神财富，是照耀所有员工不断前进的动力。
况且这些代码还 HARDCODE 了各种 8086 指令，来加速最新的 ARM，这让我们的竞争对手不寒而栗。</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<img title="" alt="" src="http://www.ledgood.com/wp-content/uploads/2011/01/zrtn_001n49526640_tn.jpg"></p>

<p>心灰意冷的你于是决定看破红尘，但是无名禅师的一番话让你幡然醒悟。于是你回到公司按主程的程序原样抄写了一遍</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
—— BUG 消失了。</p>

<h2>境界四：迷</h2>

<p>技能：<span style="text-decoration:underline;">UNKNOW</span></p>

<p>经验：<span style="text-decoration:underline;">UNKNOW</span></p>

<p>角色：<span style="text-decoration:underline;">UNKNOW</span></p>

<p>传说在每一个挨踢公司里都有一个扫地大妈，会在某天经过你的身边，扫一眼代码淡淡地说 “小心，栈溢出了”……</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201102831731444</comments>
    <slash:comments>14</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201102831731444</guid>
    <pubDate>Fri, 28 Jan 2011 15:38:46 +0800</pubDate>
    <dcterms:modified>2011-01-28T15:54:57+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[IE 也支持的 DEFLATE 格式]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201011151193497</link>
    <description><![CDATA[<div><div style="background: #333; color: #3f3;padding: 10px;">zlib.compress(data)[2:-4]</div></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201011151193497</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201011151193497</guid>
    <pubDate>Wed, 15 Dec 2010 13:19:03 +0800</pubDate>
    <dcterms:modified>2010-12-15T13:19:03+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[得道的程序员 。。。]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182010102342531684</link>
    <description><![CDATA[<div><p></p><center>“得道的程序员，既不封装，也没有重复代码。”</center><p></p>
<p><br></p>
<p><a href="http://img.bimg.126.net/photo/riFFKqLDRaQDuW9ReN3cYA==/2553259513742418280.jpg"><img title="" alt="" style="margin:0 10px 0 0;" src="http://img.bimg.126.net/photo/riFFKqLDRaQDuW9ReN3cYA==/2553259513742418280.jpg"></a></p>
<p><br></p>
<p style="font-size:12px;">无意中翻到了 06 年时笔记本的桌面，那时博客的副标题还是很给力的。留念下。</p>
<p style="font-size:12px;">今天，你得道了吗？得道更健康 。。。</p>
<p style="color:#888;font-size:11px;">PS. 那时网易博客左上角还有 163 徽标，他们现在应该是想通了，与其被 crack 掉还不如自宫&nbsp;<img title="" alt="" src="http://b.bst.126.net/common/portrait/face/preview/face38.gif"></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182010102342531684</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182010102342531684</guid>
    <pubDate>Tue, 23 Nov 2010 16:26:41 +0800</pubDate>
    <dcterms:modified>2010-12-02T13:23:05+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[这是幻觉来的 。。。]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201062194122378</link>
    <description><![CDATA[<div><div style="color: #3f3; background: #111; padding: 5px;"  > #!/usr/bin/env python<br> from thread import start_new_thread<br> def loop():<br> &nbsp;&nbsp;&nbsp;&nbsp;while 1:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br> start_new_thread(loop, ())<br> start_new_thread(loop, ())<br> start_new_thread(loop, ())<br> loop() </div>  <p>关于 cpython 线程能否充分用到 cpu 多核，相信很多人都做过这个测试。每个线程都起一个空循环，如果能把 cpu 多核全部占满，则说明已经用到多核。</p>  <p>这个实验很久以前做过，结果当然是只有一个 cpu 核心 100% 满载，其他核心无负荷。关于这个问题，似乎早有定论，由于 GIL 的存在 python 多线程是无法充分使用多核的。</p>  <p>最近又就此做了下测试，忽然发现机器上的双核都用完了。而且在 cpython2.5.5、cpython2.6.4、cpython2.7、unladen swallow q3、pypy-jit1.3 上普遍如此。</p>  <br>  <p><img alt=""  title=""  style="margin:0 10px 0 0;"  src="http://img307.ph.126.net/-crQsld7yLA2fgpsdlFsdw==/3800475135547394715.png"  ><br><b><i style="font-size: x-small;"  >AMD Athlon(tm) Dual Core Processor 5000B<br>#37-Ubuntu SMP Fri Jun 11 08:03:28 UTC 2010</i></b></p>  <p>关于这件事，<b><a rel="nofollow" href="https://groups.google.com/group/python-cn/browse_thread/thread/d4c5683ca61c798e/2112f75909884fb5"  >我在 python-cn 论坛上发了个贴</a></b>。不多时，zoomq 说的洗具发生了，在其他机器上也得到了相同的结果。</p>  <br><br>  <p><img alt=""  title=""  style="margin:0 10px 0 0;"  src="http://img.ph.126.net/viFIF1LRBaKibtLQGIBEEA==/3282279703424343375.png"  ><br><b><i style="font-size: x-small;"  >由 Zoom Quiet 提交<br>Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz<br>ubuntu 10.04 i686</i></b></p>  <p><img alt=""  title=""  style="margin:0 10px 0 0;"  src="http://img.ph.126.net/zTBVkR2LoPstNlndCs0JDw==/3330130449464238708.png"  ><br><b><i style="font-size: x-small;"  >由 GKermit 提交<br>i5 430M 2.26Hz, 1066 MHz FSB<br>ubuntu 10.04</i></b></p>  <p>这意味着<b>至少在一些情况下 python 线程是可以使用多核的。</b></p>  <h1>最新测试结果表明，这是幻觉来的 。。。</h1>  <div style="color: #3f3; background: #111; padding: 5px;"  > #!/usr/bin/env python<br> from time import time, sleep<br> from thread import start_new_thread<br> def ipp():<br> &nbsp;&nbsp;&nbsp;&nbsp;i = 0<br> &nbsp;&nbsp;&nbsp;&nbsp;while 1:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if time() &gt; t:<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '[i]'%i<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i += 1<br> t = time() + 5<br> start_new_thread(ipp, ())<br> start_new_thread(ipp, ())<br> start_new_thread(ipp, ())<br> start_new_thread(ipp, ())<br> ipp()<br> sleep(1)<br> </div>  <p>在这种简单情况下，只能用到单核。并且单线程完成的循环数要高于多线程的总循环数，性能更好。</p>  <p><b>幻觉，一切都是幻觉</b>。空循环只是个特例，大家洗洗睡吧 ……</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201062194122378</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201062194122378</guid>
    <pubDate>Wed, 21 Jul 2010 10:29:57 +0800</pubDate>
    <dcterms:modified>2011-09-24T12:26:20+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[在 64 位 ubuntu 上使用 pypy-jit]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182010613105315358</link>
    <description><![CDATA[<div><p>其实这篇文章应该叫 “在 64位 linux 上使用 32位程序”。事实上在开源世界，代码都是可以跨平台编译的，这种愿望并不很强烈。而 pypy-jit 是一个例外。</p>  <p>这里提供一种在 64位平台上运行 pypy-jit 的思路。chroot 是一种比较简单的方法，不太熟悉 chroot 的朋友可以按照这篇文章进行部署。</p>  <p>首先使用 debootstrap 建立 ia32 root。这里使用了 163 lucid 的仓库。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ sudo apt-get install debootstrap<br> $ sudo debootstrap --arch i386 lucid /opt/lucid-i386 http://mirrors.163.com/ubuntu/<br> </div>  <p>这需要一定时间。然后复制一些需要的文件到 ia32 root，这里也复制了一些用户文件，这样你就可以在 32位系统上使用当前主机上的帐号了。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ sudo cp /etc/apt/sources.list /opt/lucid-i386/etc/apt/<br> $ sudo cp /etc/passwd /opt/lucid-i386/etc/<br> $ sudo cp /etc/shadow /opt/lucid-i386/etc/<br> $ sudo cp /etc/group /opt/lucid-i386/etc/<br> $ sudo cp /etc/sudoers /opt/lucid-i386/etc/<br> </div>  <p>在 32 位系统上挂接一些需要的目录，然后 chroot 到 32位系统，进行更新。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ sudo mount --bind /home /opt/lucid-i386/home<br> $ sudo mount --bind /tmp /opt/lucid-i386/tmp<br> $ sudo mount --bind /dev /opt/lucid-i386/dev<br> $ sudo chroot /opt/lucid-i386<br> # mount -t proc none /proc<br> # mount -t sysfs none /sys<br> # mount -t devpts none /dev/pts<br> # apt-get update<br> # apt-get upgrade<br> </div>  <p>你现在已经以 root 身份进入了 32位系统，安装 pypy 需要的 libexpat1 包。然后下载一个 pypy-jit 的预编译包放到 opt 目录下。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > # apt-get install libexpat1 wget<br> # cd /opt<br> # sudo wget http://pypy.org/download/pypy-1.3-linux.tar.bz2 -O- | tar -xjf -<br> </div>  <p>现在退出 32位系统。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > # exit<br> </div>  <p>为方便在 64位主机上直接调用这个 32位的 pypy-jit 程序下面进行一些配置。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ sudo apt-get install dchroot<br> $ sudo vi /etc/schroot/schroot.conf<br> </div>  <p>编辑 schroot.conf 的内容如下。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > [ia32]<br> aliases=default<br> command-prefix=<br> description=ia32 chroot (dchroot 兼容性)<br> directory=/opt/lucid-i386<br> environment-filter=^(BASH_ENV|CDPATH|ENV|HOSTALIASES|IFS|KRB5_CONFIG|KRBCONFDIR|KRBTKFILE|KRB_CONF|LD_.*|LOCALDOMAIN|NLSPATH|PATH_LOCALE|RES_OPTIONS|TERMINFO|TERMINFO_DIRS|TERMPATH)$<br> groups=<br> personality=linux<br> priority=0<br> root-groups=<br> root-users=<br> script-config=script-defaults<br> type=plain<br> users=你的用户名,多个用户名用逗号分开<br> </div>  <p>建立 32位 pypy-jit 的 “快捷方式”。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ mkdir ~/bin<br> $ cd ~/bin<br> $ vi pypy<br> </div>  <p>编辑文件内容如下。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > #!/bin/sh<br> exec dchroot -c ia32 -d -q "/opt/pypy-1.3/bin/pypy" "$@"<br> </div>  <p>尝试执行 pypy-jit 。</p>  <div style="color: #3f3; background: #111; padding: 5px;"  > $ pypy<br> Python 2.5.2 (75551, Jun 24 2010, 05:12:10) [PyPy 1.3.0] on linux2<br> Type "help", "copyright", "credits" or "license" for more information.<br> And now for something completely different: ``Every time someone argues with<br> "Smalltalk has always done X", it is always a good hint that something needs to<br> be changed fast. - Marcus Denker''<br> &gt;&gt;&gt;&gt; import platform<br> &gt;&gt;&gt;&gt; platform.platform()<br> 'Linux-2.6.32-23-generic-x86_64-with-debian-squeeze-sid'<br> &gt;&gt;&gt;&gt; platform.architecture()<br> ('32bit', 'ELF')<br> </div>  <p>种种迹象表明 pypy 很快将获得进入生产领域的足够能力，对常规公司而言确实如此。而很多充满信心的技术人员则在生产环境中使用 pypy 这一族技术已经很久了。我相信 pypy-jit 登陆 64位平台已可预期，在不远的将来。而在此之前，即便是 64位的服务器，我们也已经迫不及待地准备在项目中尝试 pypy-jit 了。</p>  <p><i>参考资料 <a rel="nofollow" href="http://wiki.ubuntu-tw.org/index.php?title=Ubuntu-AMD64-Howto"  >Ubuntu AMD64 Howto</a></i></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182010613105315358</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182010613105315358</guid>
    <pubDate>Tue, 13 Jul 2010 10:53:15 +0800</pubDate>
    <dcterms:modified>2011-09-24T15:07:59+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[写了个在 ubuntu 上安装配置 wine、迅雷和 QQ 的自动化脚本]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820106834316900</link>
    <description><![CDATA[<div><p>在这里&nbsp;<a rel="nofollow" href="http://code.google.com/p/winevil/"  >http://code.google.com/p/winevil/</a></p> <p><img alt="写了个在 ubuntu 上安装配置 wine、迅雷和 QQ 的自动化脚本 - 沈崴 - 蜻蜓点水 举重若轻"  title=""  src="http://winevil.googlecode.com/files/screenshot1.png"  ></p> <p>脚本是 python 的，带有<b><a rel="nofollow" href="http://slickeel.wordpress.com/2010/06/02/starcraft-2-beta-wings-of-liberty-in-ubuntu-lucid-lynx-with-wine/"  >星际2 补丁</a></b>。</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820106834316900</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820106834316900</guid>
    <pubDate>Thu, 8 Jul 2010 15:43:16 +0800</pubDate>
    <dcterms:modified>2011-09-23T22:04:33+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Javascript 中的 for in]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201032105439371</link>
    <description><![CDATA[<div><p>前段时间和朋友提到 javas<wbr>cript，可惜没有 foreach。朋友当时便有点诧异。我补充说 for…in 其实还是有的，只是不可预期而已。</p>    <p>使用 for…in 遍历数组的方法。</p>    <div style="color: #3f3; background: #111; padding: 5px;"  >  var lst = [1, 2, 3, 4, 5, 6];<br><br>  // 输出 123456<br>  for (var i in lst)<br>  &nbsp;&nbsp;&nbsp;&nbsp;document.write(lst[i]);  </div>    <p>目前一切都还正常。但试着加上一行代码，就会有变化。</p>    <div style="color: #3f3; background: #111; padding: 5px;"  >  var lst = [1, 2, 3, 4, 5, 6];<br>  Array.prototype.xxx = 'XXX'; // +++<br><br>  // 输出 123456XXX<br>  for (var i in lst)<br>  &nbsp;&nbsp;&nbsp;&nbsp;document.write(lst[i]);  </div>    <p>看上去给 array 加上一个 xxx 明显是一件极其 silly 的事情。但是想一下很久之前 IE 中的 array 是没有 push 方法的，那时我们经常会用这种方法给 IE 加上 push。</p>    <p>这样看来顺理成章，for…in 不能用了。</p>    <p>如果再考虑到低版本的 IE 不支持 push，早期 “安全” 的 javas<wbr>cript 就会像这个样子。</p>    <div style="color: #3f3; background: #111; padding: 5px;"  >  var lst = [1, 2, 3];<br><br>  &nbsp;&nbsp;…<br><br>  lst[lst.legnth] = 4; // push 4<br>  lst[lst.legnth] = 5; // push 5<br>  lst[lst.legnth] = 6; // push 6<br><br>  &nbsp;&nbsp;…<br><br>  for (var i = 0; i++; i &lt; lst.legnth)<br>  &nbsp;&nbsp;&nbsp;&nbsp;document.write(lst[i]);  </div>    <p>没有经历过那个时代的朋友乍一看到，不禁会问，这，这是什么情况？</p>    <p>—— 这确实是太糟糕了。</p>    <p>异曲同工之妙，string 也是可以 for…in 遍历的。</p>    <div style="color: #3f3; background: #111; padding: 5px;"  >  var str = 'abcdef';<br><br>  // 输出 abcdef<br>  for (var i in str)<br>  &nbsp;&nbsp;&nbsp;&nbsp;document.write(str[i]);  </div>    <p>杯具的是，给 string 加 strip 之类的方法也是很常见的。这样才是最 “面向对象” 的扩展方式，不是吗？</p>    <div style="color: #3f3; background: #111; padding: 5px;"  >  var str = 'abcdef';<br>  // var strip = function(s) { return s.replace(/^[\r\n\s\t]*|[\r\n\s\t]*$/g, ''); }; // XXX 不够面向<br>  String.prototype.strip = function() { return this.replace(/^[\r\n\s\t]*|[\r\n\s\t]*$/g, ''); };<br><br>  for (var i in str)<br>  &nbsp;&nbsp;&nbsp;&nbsp;document.write(str[i]);  </div>    <p>当然最抱歉的写法应该是 “ Object.prototype.xxx = XXX ” 了。</p>    <p>使用 javas<wbr>cript 小心 IE。这个大家都清楚，自不必多说。如果 javas<wbr>cript 中引用了第三方代码，或会被别人用到，for…in 最好不用。prototype 也尽量少用。</p>    <p>我以前说过，对于成熟的 library / framework 开发者来说，接口过多和接口太少，其实就是一码事。</p>    <p>特性越多，功能越少，“ for…in vs prototype ” 这是一个典型例子。</p>    <p></p><center><a rel="nofollow" href="http://laurentszyster.be/blog/jruby-vs-cpython/"  ><img title="Javas&lt;wbr&gt;cript 中的 for in - 沈崴 - 蜻蜓点水 举重若轻"  alt="Javas&lt;wbr&gt;cript 中的 for in - 沈崴 - 蜻蜓点水 举重若轻"  src="http://laurentszyster.be/blog/wp-images/jruby-vs-cpython.png"  ></a></center><p></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201032105439371</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201032105439371</guid>
    <pubDate>Fri, 2 Apr 2010 10:54:39 +0800</pubDate>
    <dcterms:modified>2011-09-24T05:13:02+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[张秀才]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182010212103729853</link>
    <description><![CDATA[<div><h2>安装</h2>    <div style="color: #3f3; background: #111; padding: 5px;"  >  sudo apt-get install build-essential<br>  sudo apt-get install autoconf libtool iptables-dev<br>  wget http://scholarzhang.googlecode.com/files/west-chamber-0.0.1.tar.gz<br>  tar -xzf west-chamber-0.0.1.tar.gz<br>  cd west-chamber-0.0.1<br>  ./autogen.sh<br>  CFLAGS="" ./configure --prefix=/usr --libexecdir=/lib<br>  make<br>  sudo make install<br>  cd examples<br>  sudo ipset -R &lt; CHINA<br>  sudo ipset -R &lt; GOOGLE<br>  sudo ipset -R &lt; YOUTUBE<br>  sudo ipset -R &lt; NOCLIP<br>  sudo iptables -A INPUT -p tcp --sport 80 --tcp-flags FIN,SYN,RST,ACK SYN,ACK -m state --state ESTABLISHED -m set --match-set NOCLIP src -j ZHANG -m comment --comment "client-side connection obfuscation"<br>  sudo iptables -A INPUT -p tcp --dport 80 --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j CUI -m set --match-set CHINA src -m comment --comment "server-side connection obfuscation"<br>  sudo iptables -A INPUT -p tcp --sport 80 -m state --state ESTABLISHED -m gfw -j LOG --log-level info --log-prefix "gfw: " -m comment --comment "log gfw tcp resets"<br>  sudo iptables -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -m gfw -j DROP -m comment --comment "drop gfw dns hijacks"<br>  </div>    <br><br>    <h2>使用健康的 DNS</h2>    <div style="color: #3f3; background: #111; padding: 5px;"  >  1) <b>sudo vi /etc/dhcp3/dhclient.conf</b>，加入 <b>prepend domain-name-servers <i style="color: #383;"  >8.8.8.8</i>;</b>。<br>  2) 重启网卡 <b>sudo ifconfig eth<i style="color: #383;"  >0</i> down</b>，然后 <b>sudo ifconfig eth<i style="color: #383;"  >0</i> up</b>。<br><br>  <i>用 <b>network-manager</b> 也可以，直接改 <b>/etc/resolv.conf</b> 一般不是很推荐。</i></div>    <br><br>    <div style="color: #3f3; background: #111; padding: 5px;"  >  项目信息：<b><a style="color: #3f3;" rel="nofollow" href="http://2tu.us/1s55"  >GFVVREV</a></b><br>  参考资料：<b><a style="color: #3f3;" rel="nofollow" href="http://blog.xiaogaozi.org/2010/03/ubuntu.html"  >http://blog.xiaogaozi.org/</a> 、INSTALL 、USAGE</b> 。</div></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182010212103729853</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182010212103729853</guid>
    <pubDate>Fri, 12 Mar 2010 10:37:29 +0800</pubDate>
    <dcterms:modified>2011-09-24T22:05:52+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Vi 编辑器快速上手]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182010244211794</link>
    <description><![CDATA[<div><p>接触 vi 也有十多年了。这里也试着聊下 vi 编辑器快速上手的方法，对刚开始准备使用 vi 的朋友可能会有点帮助，高手就不用看了。</p>

<p>方法很简单，去用，就很快会了。当然 vi 的操作确实比较繁多，不知怎么下手。我这里提炼出一些常用的，一丁点内容，保守用两天来熟悉。不用怀疑，对于所有编辑任务确实已经够用了。既然这样，读完后，马上就开始用，去用，就很快会了。</p>

<p>vi 主要是两种模式，按 Esc 键进入指令模式（常见有人会狂按 Esc 直至电脑喇叭发出哔哔声以确认进入指令模式），按 i 键（insert）进入输入模式（可以输入东西编辑文件了）。</p>

<br><br>

<p><b>开始时默认进入的是指令模式：</b></p>

<p>用 h（左）j（上）k（下）l（右）移动光标。Ctrl+f 向下翻页，Ctrl+b 向上翻页。</p>

<p>i 键插入当前光标位置，或 a 键在光标后插入。同时进入输入模式，进行编辑，按 Esc 键再返回命令模式。</p>

<p>x 删除当前字符，dd（按两次 d）删除（剪切）当前行。</p>

<p>u（undo）撤销。</p>

<p><b>保存文件：</b></p>

<p>在指令模式中（最不用动脑筋的办法是乱按一通 Esc 可以保证从编辑模式进入指令模式）按“:”键（冒号）可以进入 vi 的末行模式，退出末行模式回到命令模式只要按退格键删除“:”字符即可。</p>

<p>输入 :wq（回车）即是保存退出。:w 保存不退出。:q! 退出不保存。</p>

<br><br>

<p><i>以上内容，花一天熟悉。浏览文件，做点简单编辑已经足够了。注意不要用小键盘，比如上下左右这些，否则就很难学会 vi 了。在 vi 里手不会离开大键盘，用不了多久这些指令就会条件反射，编辑效率比较高。</i></p>

<br><br>

<p><b>下面是相对不太常用的：</b></p>

<p>o 在当前行后插入一行，O 在当前行前插入一行。和 i、a 一样，同时进入输入模式。</p>

<p>数字键 0 跳到行首，$ 跳到行尾。</p>

<p>Shift+j 将当前行和下一行合并成一行。</p>

<p>Ndd 剪切 N 行（N 是一个数字）。</p>

<p>yy 复制当前行。Nyy 复制 N（N 是一个数字）行。按 p 键粘贴。</p>

<p>:N 跳到第 N 行。直接打 N 跳到当前行后的第 N 行。N 可以是负数。</p>

<p>在命令模式下输入 /word（回车）来在文件中搜索字符 word。按 n（next）跳到下一个搜索到的字符。</p>

<p>使用“:s/被替换字符/替换字符/g”这行命令来进行搜索替换。比如“:s/^M//g”是把 windows 文件的行尾 ^M 删除掉。其中“^M”的输入方法是按住 Ctrl+v，然后保持 Ctrl 并放掉 v 键，再按 M。</p>

<p>这就开始使用 vi 吧。</p>

<br><br>

<p><i>主题无关，这里聊些其他的。其实很多貌似常用的指令我都没有写，比如 X 删除，sS 替换等等，我觉得刚开始用记那么多负担太重。况且 s 我经常用打个 x 再打个 i 效果一样。</i></p>

<p><i>记这么点东西我觉得够了。用熟练了，再找资料学更多方便编辑的命令和配置方法。一口气吃不成胖子。我自己比较特别，用 vi 写代码是不用自动补齐和自动缩进的。拿自动缩进来说，不喜欢在文件里有我不知道的空格悬挂在那里。也不显示行号，甚至不用代码着色。这样代码稍微冗长一点，稍微混乱一点，读起来麻烦，视觉上马上就警惕了。帮助我避免写出烂代码（当然也有会觉得程序越长越复杂越牛逼的，人都有不同，各取所好吧）。所以 ssh 到其他管理员配置的服务器上，我有时会把那些对我没用，看着麻烦的配置都还原掉。因为对我来说没那么多复杂的东西，可视模式啊，分屏什么的，基本没用，所以也没写。文中的东西够我所有日常应用了，理论上，对我来说不需要 vim，给个 vi 就够了。</i></p>

<p><i>vi 是神器，即便 emacs 或者其他玩家，简单了解下也是要的。less 命令或者看 man 手册，甚至 python 的 help() 函数用的到处都是 vi 指令。</i></p>

<br><br>

<p>另外，遇到 vi 编辑中非正常退出的文件（被锁），ls -a 一下把 .swp 文件删了就可以了。差点忘了，编辑系统文件用 sudo vi，除非在 /root 下生成一堆 X 配置文件你觉得无所谓，那么用 gedit 之类的 gui 编辑器也无所谓。</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182010244211794</comments>
    <slash:comments>3</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182010244211794</guid>
    <pubDate>Thu, 4 Mar 2010 16:21:17 +0800</pubDate>
    <dcterms:modified>2010-03-04T16:30:26+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[关于 WSGI]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318201011082044410</link>
    <description><![CDATA[<div><p>正和朋友讲解 WSGI 。打了一大段没发出去 QQ 就崩溃了 (没打补丁)。我想对准备接触 WSGI 的初学者朋友都有会点用, 就记在这里吧。</p>    <p>WSGI 主要是读一下 <a rel="nofollow" href="http://www.python.org/dev/peps/pep-0333/"  ><b>PEP333</b></a> 。其实把里面两段示范代码看了就明白了。我读了下示范代码和环境变量的要求, 就写了 (eurasia) WSGI server 事情就这么简单。</p>    <p>一个比较容易产生疑惑的地方是, 可能会把 (1) WSGI server 和 (2) 基于 WSGI 的 framework 混淆了。其实 WSGI 是分成 server 和 framework (即 application) 两部分 (当然还有 middleware)。严格说 WSGI 只是一个协议, 规范 server 和 framework 之间连接的接口。</p>    <p>(1) WSGI server 把服务器功能以 WSGI 接口暴露出来。比如 mod_wsgi 是一种 server, 把 apache 的功能以 WSGI 接口的形式提供出来。</p>    <p>(2) WSGI framework 就是我们经常提到的 Django 这种框架。不过需要注意的是, 很少有单纯的 WSGI framework  , 基于 WSGI 的框架往往都自带 WSGI server。比如 Django、CherryPy 都自带 WSGI server  主要是测试用途, 发布时则使用生产环境的 WSGI server。而有些 WSGI 下的框架比如 pylons、bfg 等, 自己不实现 WSGI server。使用 paste 作为 WSGI server。</p>    <p>Paste 是流行的 WSGI server, 带有很多中间件。还有 flup 也是一个提供中间件的库。</p>    <p>搞清除 WSGI server 和 application, 中间件自然就清楚了。除了 session、cache 之类的应用, 前段时间看到一个 bfg 下的中间件专门用于给网站换肤的 (skin) 。中间件可以想到的用法还很多。</p>    <p>这里再补充一下, 像 django 这样的框架如何以 fastcgi 的方式跑在 apache 上的。这要用到 flup.fcgi 或者 fastcgi.py (eurasia 中也设计了一个 fastcgi.py 的实现) 这些工具, 它们就是把 fastcgi 协议转换成 WSGI 接口 (把 fastcgi 变成一个 WSGI server) 供框架接入。整个架构是这样的: django -&gt; fcgi2wsgiserver -&gt; mod_fcgi -&gt; apache 。</p>    <p>虽然我不是 WSGI 的粉丝, 但是不可否认 WSGI 对 python web 的意义重大。有意自己设计 web 框架, 又不想做 socket 层和 http 报文解析的同学, 可以从 WSGI 开始设计自己的框架。在 python 圈子里有个共识, 自己随手搞个 web 框架跟喝口水一样自然, 非常方便。或许每个 python 玩家都会经历一个倒腾框架的阶段吧。</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318201011082044410</comments>
    <slash:comments>4</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318201011082044410</guid>
    <pubDate>Wed, 24 Feb 2010 21:09:54 +0800</pubDate>
    <dcterms:modified>2011-09-23T17:41:06+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[[全文整理] 二千年传承的古武术秘密]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820091129249650</link>
    <description><![CDATA[<div><div style="color: rgb(136, 136, 136);"  >  <b>整理说明</b>    <p>这是一篇比较出名的经典老文了, 似乎没看到有完整的 stand-alone 版本。这里从论坛原文整理出完整版本, 尽量保持了原文排版布局的风貌, 并收录所有作者主题相关的文字。力求忠于原著。</p>    <p>此文作者是<a rel="nofollow" href="http://www.ws61.net/bbs/u.php?uid=99075"  ><b>养生无双</b></a>。原文见 <a rel="nofollow" href="http://www.ws61.net/bbs/read.php?tid=69901"  ><b> (一) </b></a><a rel="nofollow" href="http://www.ws61.net/bbs/read.php?tid=70005"  ><b> (二) </b></a><a rel="nofollow" href="http://www.ws61.net/bbs/read.php?tid=70177"  ><b>(三)</b></a><a rel="nofollow" href="http://www.ws61.net/bbs/read.php?tid=70556"  ><b> (四) </b></a><a rel="nofollow" href="http://www.ws61.net/bbs/read.php?tid=71288"  ><b> (五) </b></a>。以下正文。</p>  </div>    <p>&nbsp;</p>    <h2>二千年传承的古武术秘密 (一)</h2>    <p>在火器时代之前, 中国是天下第一步战强国。动则数十万人的战争中, 能活下来的人所凭借的东西到底是什么?<br>我研究在世上活命之道二十年, 不敢在擂台上说能打赢泰森, 小光头, 格雷西, 但是自有自己独到之处。如今就完全免费地和各位分享一下。</p>    <p>本文会分析中国几大传统拳种的源流。看看它们的来历和用途。将分为如下几个章节 [1]。</p>    <ol>  <li>战场之拳</li>  <li>义士之拳</li>  <li>暗杀之拳</li>  <li>飞贼之拳</li>  <li>擂台之拳</li>  </ol>    <p><b>战场之拳</b></p>    <p>中国古代战争的特点就是人多, 多到什么地步呢? 我打个比喻, 一个足球场大概可以容纳5万人在那里密密麻麻地站着。一场较大规模的战争, 大概就是好几个足球场的人密密麻麻地挤在一起。这么多人挤在一起, 面临的最大危险是什么?</p>    <p>答案是个废话, 就是被踩死。五万人中只要有1000人突然发了神经乱走路。至少一瞬间就能踩死2000人。踩残废的则不计其数。什么泰森小光头遇到这 1000个发神经乱走路的人, 可能可以一阵摆拳打倒四五个, 但最后也只有死路一条。死得最快的是什么人? 是格雷西家族的人, 这个家族的人有个坏习惯, 就是一打架就往地上趴。只见一阵大脚丫过后, 顿时退货。<br>如果这发了神经乱走路的1000人, 不是一般人, 是骑着马拿着长矛的, 死的人就更多了。什么? 发了神经的不止1000人, 是另外50000个骑马拿长矛的人?!?!</p>    <p>所以各位喜欢看穿越小说的兄弟们, 千万不要以为自己练了点什么无限制啊, k1啊, 跑到古代就能吃香。真过去的话吃的估计都是烧的香。<br>  在战场之中, 对武功的第一要求是</p>    <p>  1. 重心低+平衡感 (马步稳) , 否则一滑倒则万事休矣<br>  2. 保护要害。挨一刀一枪则省下娶老婆生孩子的费用了。  </p>    <p>这里说的保护要害, 可千万不要以为是像拳击手一样两手护着太阳穴和下巴。在战场上你摆这个姿势就是找死。<br>首先分析你是个什么兵种, 你是长枪兵 (排在最前面送死的就是你这个兵种) 就摆个形意拳的三体式。前手防咽喉和胸, 后手防腹+下阴, 两手抓一支长枪, 用趟泥步前进。形意拳号称是岳飞传下来的武功。岳飞用的肯定不是什么泰拳黑市拳。动脑想想就明白了。</p>    <p>你是刀盾兵 (好不到哪里, 也是个送死的兵种啊! ) 就一手在前持盾, 一手在后持刀。摆个太极拳的白鹤亮翅的姿势。谁要是摆泰拳姿势死了不要怪我没指点啊!</p>    <p>你是弓箭兵 …… 安心射箭吧, 别想这么多了。士兵在该死的时候不死是一种耻辱。</p>    <p>如果你祖先积德, 分配了个骑兵, 也别太得意。你照样要练马步。那些喜欢蝴蝶步的兄弟还是在家和美女扑蝶嬉戏吧。</p>    <p>看到这里, 也许有些聪明的朋友已经明白了一个道理, 那就是“功夫实用不实用, 关键看你在哪里用”</p>    <p>当年巴西有个小男生, 学了日本的柔术。据他自己说“删除了一些不实用的技法, 创编了无敌的格雷西柔术”<br>格雷西柔术现在已经到处挨打了。说明这世界上那有什么无敌的东西? 那都是广告! 我们分析一下日本柔术和格雷西柔术的异同, 就不难发现格雷西删除的是什么技术。</p>    <p>日本柔术的针对对象, 是双手持武士刀的铠甲武士 (一般开始从小练刀, 反应不会比你差) 。面对这样的对手, 你用什么鞭腿, 什么下潜抱腿摔都是假的, 你若用鞭腿, 只见对方潇洒地大刀一挥, 只见一条腿如鞭一样飞上半空去了。<br>  吾观察街斗多年, 未见有人敢对手持西瓜刀的对手使用高鞭腿, 便是这个道理。<br>但如果对手是个空手的人, 那便不可怕了, 拼着挨几拳, 也要把对方推倒凌辱一番。但这依然有危险, 你永远不知道他身上是不是藏着把小刀, 或者摸出把钥匙朝你脸上猛刺。<br>  我观察了一下泰森的身板, 在要害未被刺中的前提下, 他大约能在挨5刀的情况下支持10分钟不死亡。超出10分钟则情形不乐观。<br>如果要害被刺中, 没啥说的, 当场毙命。<br>  在街斗中, 吾未见面对匕首者双手护头跳跃作泰森状的。反对的人请上视频证明。</p>    <p>日本柔术和中国同类拳法 (太极拳) 的最大异同在哪里? 两者都有快速进身反关节夺刀的技术, 都有快速进身用“内劲”打透铠甲的技术, 都有借力跌人的技术。这几项都是战场上最实用的东西。<br>  但日本柔术多出一个“寝技”, 其原因无他, 因为日本战争人少, 几百人对打就是大会战了。打着打着就稀疏起来, 可以放心用擒抱技术来抓俘虏, 除此以外, 还因为日本从来没发明过盾牌兵之类的兵种, 只要躲开了对方双手持的刀、枪, 近了身抱住对方的手臂就安全了。要是到了中国, 一盾牌 (铁山靠) 把你撞开, 顺手补一刀, 看你还来寝技?<br>但到了格雷西的时代, 就离战场越来越远, 在单对单徒手对抗中, 只剩下插眼踢裆等技术还能让对方忌惮一下, 格雷西柔术大刀一挥, 把插眼踢裆去掉了, 在不用武器的前提下, 寝技顿时失去了天敌, 迅速繁殖起来。我常常见一些热心的传统武术家在思考怎么对付格雷西柔术, 我每次都对他们说, 别想怎么对付了, 干脆就别对付。干吗去找郁闷呢?</p>    <p>战场之拳的第二要求是</p>    <p>1. 有去无回<br>有去无回不是指一种精神状态, 而是指你后面的人时刻在挤着你向前走。你一停步或者回头看一看就被50000人踩死。沉迷于侧踹, 鞭腿啊的兄弟抚心自问。你背后有人始终用全力推着你的时候你的鞭腿还剩下几成功力? 踢完人之后能不能站稳?</p>  <p>2. 贴身发力<br>我前面说的内劲打透铠甲, 估计已经有兄弟怀疑了。这也不怪你们, 谁叫你们没练过内劲呢? 我没练过也不相信有人深蹲900公斤。要真有人深蹲900公斤, 别说打透铠甲, 打透航母都可以啊!</p>    <p>在这里就公布一个不传之秘, 那就是日本人潜心研究中国拳法多年, 研究出来的内劲速成太监版。放到空手道馆, 至少要骗你几万块学费, 混到个什么师范才教你。<br>一般人出拳, 是先蹬地, 然后扭腰, 然后送肩, 然后出拳, 然后击中对手。<br>用内劲的人是先出拳, 然后迅速上前一步 (很重要) , 扭腰, 送肩, 同时击中对手, 就这么简单。只要用这个诀窍, 就算后面有一千人在拼命推你, 你也能连续不断打出重拳。能不能透甲, 就看你每天花几个小时练了。兄弟们, 拿出点练黑市拳流深蹲的精神出来!  </p>    <p>&nbsp;</p>    <p><i><b>外篇, 透甲打神秘吗?</b><br>答, 丝毫不神秘。练过散打跆拳道的都知道, 穿着硬式护甲被人一击KO的例子比比皆是。护甲充其量作用是避免流血性外伤罢了。你背靠墙站定不动, 在胸口垫一块木板, 我找个没练过任何功夫的大汉对木板猛击, 在座的兄弟估计没几个人能挨几下后还不吐血。何况我国古代铠甲一般以片状叠加的软甲为主。<br>透甲打只是一种更方便贴身的针对铠甲研发的发力方法而已。</i></p>    <p>总结一下, 在中国古战场上, 最实用的招数就是“站稳, 保护要害, 在对方武器以外的范围痛打对方。”<br>我国古代贪污成风, 士兵的武器基本都是偷工减料的。能拿到一套正常的武器/铠甲, 该士兵要含泪跪谢祖宗。这不是开玩笑的话, 是血   腥的事实。而即使是正常的武器, 砍了几个盔甲人以后也会损坏。作为一个老兵, 你不得不考虑后备武器, 那就是你的肉体, 这就是战场之拳的雏形。至于战场之拳的真正成型, 是在元代的禁武令之后。<br>元朝禁武器, 汉人藏武器者全家死。菜刀必须几户公用。申请备案。该菜刀出了血案伤了元人的话, 共用菜刀的这几户一起咔嚓咔嚓了。<br>宋军虽然积弱, 但毕竟曾用步兵对抗游牧民族几百年, 怎么可能没几分实力? 于是藏在民间两眼发红, 一边拜岳爷爷一边时刻准备还我河山的军人比比皆是。然而元朝的禁武令下, 你要是带着一批村民每天拿着武器练捅人砍人, 估计没几天你就挂在旗杆上示众了。<br>  所以元朝的汉人武士们发明了一种看上去很像健身操的东西。“左手撑着, 向前一步, 右手向前伸一下, 回手摸一下自己后脑勺, 再摸一下前面……”“一手在喉咙位置, 一手在下阴位置, 用趟泥步往前走……”</p>    <p>太极拳里面有一招看起来很华而不实的招数“切地龙” (用日本人的说法就是“XX流秘奥义——地龙死闪) , 其真正用法就是近身后先举着盾牌顶着对方, 同时挡住对方视线, 然后保持盾牌举着, 身体下潜一刀子猛捅对方下阴。还有什么海底针 (水龙死闪) 大致上也是如此。揽雀尾则是用左手来抱着对方的长矛, 右手猛斩。<br>张三丰被元朝皇帝召见, 路上杀山贼若干, 他说他是夜梦神人授拳, 鬼 (元朝鬼子) 才相信。实际上答案很简单, 他就是传承战场之拳的人之一。但这要是明着和元朝皇帝说, 元朝皇帝绝不会表扬张三丰热爱科学实事求是, 而会命令御林军猛冲过来考验科学。</p>    <p>&nbsp;</p>    <p><i><b>外篇: 戚家军剿匪法</b><br>有朋友提到, 在战场上最实用的是武器而不是拳法, 并且举出了戚继光为例子。<br>但事物并非一成不变的, 实际上在古战场上, 双方隔开距离对刺对砍, 实在是一种非常理想化的状况。实际的状况是什么呢? 是两军第一回合的对刺对砍之后, 你还没来得及刺第二枪, 砍第二刀, 就已经被后面的人挤得和敌人脸贴脸, 心连心了。这个时候如果你还没死, 那么最可靠的不再是手中的大刀长矛, 而是拳法, 肘法。只要能一拳把对手打晕2秒, 你就可能多活了两秒。<br>戚家军的鸳鸯阵是一种剿匪阵法, 适合对抗不能形成践踏性杀伤的小股的步兵倭寇势力。但是却不适合大规模军阵, 戚继光的战友余大猷中后期被调去守北边, 对付北方骑兵, 他就没再使用鸳鸯阵, 而是使用了其他更适合环境的阵法。<br>不审势则宽严皆误啊。</i></p>    <p>战场之拳中还有些叫“劈拳”的招数, 是单手从上到下砸对方的脸。这种拳法在手持刀柄的情况下威力特别强大。还有些叫大劈的招数, 则是一手高一手低地同时往下砸, 这一招的密码只需要手持长枪即可明白, 这是用枪尾凿击近身对手的技术啊。</p>    <p>以传承战场技术为目的的战场之拳在清代发生了很大变化, 其中相当一部发展为更适合用来单兵/小规模作战的“义士之拳”这点会在后文再述。</p>    <p>&nbsp;</p>    <h2>二千年传承的古武术秘密 (二)</h2>    <p>闲言闲语, 在这个时代, 保守其实是没啥意义的, 我的师父们教我的时候不是怕教会徒弟打师父, 而是怕东西失传, 恨不得先都塞到我脑子里。但东西还是在我这一代失传了不少, 为什么? 因为这东西不值钱。<br>  不值钱的东西就没人去学去练, 这是千古不易的真理。好比说我在第一贴里毫不保留地说了破甲打的发力方法。在古代我估计就会因此被同门追杀, 但是这样便宜地说出来, 留意的人又有几个?<br>  其他人也就罢了, 但却要点名批评一下24, 这家伙最近一直挂着太极拳的名义到处招摇撞骗, 却连实战太极拳最基础的东西发劲都不会 (简直就像拳击手不会直拳一样) , 看见了真传一句话的东西, 却不去详细琢磨一下。中国功夫的名声, 就是败在这些终日大言炎炎, 沉迷于自我心理满足的人手里。</p>    <p>许多看帖人都在留意“古代打仗怎样才能赢” (其实养生一句都没提过战争的胜负问题) 。而自动忽略其他内容, 这就是功利心。这样的人适合当军师, 但不适合当士兵, 适合当票友, 却不适合当拳手。</p>    <p>下面我会专门用太极拳的一些秘奥义来讲解一下这一流派的战争之拳精髓。觉得不能理解或者声称自己没听说过的人也不用怀疑, 当小说看即可。</p>  <p>在说太极拳之前, 先说一下巴西的华丽格斗术: 卡波依拉<br>卡波依拉的动作主要为腿技, 其次是一些匪夷所思的翻滚跳跃技巧。这东西在现代人看来只是怪招, 看起来好看。改成街舞能泡MM。但这种拳法的来历是什么呢?<br>  是几百年前, 殖民者入侵巴西, 将巴西男子列为奴隶, 持有武器者杀杀杀。大部分奴隶还要带着较长的手铐工作。连晚上睡觉都不能解下来。在这种情况下, 巴西人发明了一种华丽的“传统舞蹈”, 这种舞蹈实际上是专门利用手铐铁链为武器而研发的杀人拳。<br>  卡波依拉的基础格斗式是身体不断左右变换 (尽量躲闪火枪) 两手保持距离交错在面前划过 (用铁链锁拿刺刀) 一旦抓住机会, 就用铁链锁住对方手臂或脖子, 然后通过身体的跳跃和旋转勒断目标, 这种包含体重和跳跃力的锁链技, 加上攻击角度诡异, 实在是奴隶们对抗火枪的最有效的方法。<br>看到这里, 我知道肯定有人把自己代入到殖民者的身份说: “这样能打得过火枪吗? 我如果拿火枪去打, 对方如何如何, 等等。”<br>但我也要反问, 当你就是那些奴隶的时候, 你去哪里拿火枪? 难道没火枪就安心当亡国奴了吗? 手上有啥你就用啥, 战争的胜负轮不到你关心, 但是关键在你努力了。</p>    <p>巴西有这样的技术, 中国也有。而且种类更多。<br>形意拳是以枪化拳, 太极拳则是刀盾兵留下来的拳法, 一刀一盾, 就是那阴阳鱼 (当然, 还有别的比喻)<br>所谓的借力打力, 在徒手打斗中没那么管用, 或者说, 使用难度太高, 但是配上了盾牌+刀, 就是最恐怖的技术。<br>  当一个盾牌兵顶着四米长的长矛, 冲到敌人跟前, 他的任务就是把敌人的长矛阵破开, 让自己的兄弟们能冲上来。<br>在敌人的枪阵还没冲破的时候, 太极拳奥义“切地龙”“海底针”“跌叉”等技术的方法都是持盾矮身潜进, 避开上身的矛头, 用刀猛捅对方下身。而当近身以后, 则使用揽雀尾等技巧抱住对方的多枝长矛, 用刀猛砍。<br>揽雀尾的雀尾, 指的是孔雀的尾巴, 用来比喻许多长矛。当一个刀盾兵奋不顾身地抱住了对手好几根长矛的时候, 他的战友们就可以乘虚猛冲进去乱砍。<br>这也是揽雀尾被称为太极拳母拳的原因之一。当然, 揽雀尾也可以用来接腿摔, 用来反关节。但效果便打有折扣。<br>而当兄弟们都冲到身后, 把你挤得和敌人已经脸贴脸, 心连心的时候, 你已经没有距离举刀, 这种情况下, 你有几个选择</p>    <p>  1. 用发力距离极短, 可以借背后力的发劲透甲打来打对方, 把对手打晕或者打退, 有了挥刀距离后补上一刀。<br>  2. 用盾牌猛击对手。 (太极拳凡是用小臂发劲的技术大致都出于此) <br>  3. 用刀柄自上而下猛砸对方的脸。<br>  4. 丢了武器抱住对方脖子拧 (看着练太极拳的兄弟在那里玩太极石球, 不要奇怪, 等你的脑袋像石球一样在对方手里的时候就明白了)<br>  5. 用盾牌挤对手, 趁对手用力对抗的时候盾牌上玩点虚实, 让对方失势跌倒 (牵动四两拨千斤) , 成功的话, 是让对手一大堆人一起跌倒 (踩死)<br>  6. 用BT的柔韧性, 突然矮身用盾牌和肩膀撞击对方小腿 (七寸靠) , 让出上盘的空间给自己兄弟在背后砍/捅对方。<br>  7. 用长劲将对方撞退, 然后突进砍杀。<br>  </p>    <p>除了刀拳合一的拳击术外, 太极拳有种种匪夷所思的小臂劲法, 例如堋、履、挤、按, 这些都是用盾牌打击或者挤压对手的训练法。还有採、挒这两种针对长矛或者对方手臂的控制技, 肘、靠两种近身打击技。</p>    <p>上述都是实用至极的标准军人技术。但军人和军人之间总有区别, 其中一些军人将自己的军体拳和道家的“返先天”奥义结合, 潜心体己, 发现了一些进阶的锻炼技巧。<br>  注意, 是锻炼技巧。不是实战技, 我知道肯定有些回帖不看帖的人会在那里大喊: “这些东西战场上有用吗? ”我现在就提前回答: “这些就像长跑跳绳一样, 不是实战用的, 都是锻炼用的, 锻炼锻炼锻炼锻炼……”</p>    <p>和真正练太极拳的人搭手, 会有奇怪的发现, 就是无法从对方的手上感觉到对方的重心, 但对方却能抵抗住你的力量不后退。这个情况在某些练日本剑道的人身上也能找到。</p>    <p>答案其实在李仲轩前辈的门下另一条走狗徐浩峰 [2] 的书中已经披露, 那就是无名指锻炼法。 (全身及其他手指放松, 只有无名指紧张) , 无名指在日常生活中是废指, 很难动用到相关的力量, 但是它紧张的时候却能让力量传到手上。而且你感觉不到自己无名指的相关力量, 对方也感觉不到从你无名指上传出来的暗劲。<br>正确用刀挥砍的时候, 主要就是无名指带动刀的运行, 其他手指只是在砍中目标的时候紧张以保持刀的平稳, 所以很多练剑道的人无意中能练出这个效果, 专练柔道的兄弟反而练不出来。</p>    <p>而太极拳最重要的攻击力量虽然来源于无名指, 但是其核心却在大拇指上, 在持刀挥刀的时候, 身体因刀而失重, 全靠大拇指来维系刀的重量和平衡。内家拳的“人刀合一”秘法, 也在大拇指上。</p>    <p>我们平时坐公共汽车, 汽车一颠簸, 我们就要找个地方扶一下来维持平衡, 实际上扶一下那个力相对是很轻的, 为何就能让我们一百多两百斤的体重保持平衡了呢? 因为我们只是要找一下平衡感。找到了来源于两个大拇指的平衡感, 就进入了“不动之动”的境界。真正的 “四两” 拨千斤, 用的是四两重的大拇指, 拨自己的体重千斤。<br>  养生自己发明了一个方法, 平时把大拇指握在其他四个手指里。行走时假装失重, 有时拇指从其他四个手指里寻找借力来平衡, 有时其他四个手指也从拇指上找借力来寻找平衡。</p>    <p>题外解释一下, 手背为阳, 手掌为阴, 把大拇指握在手掌里这种互相借力的方法, 暗语称为“阴中有阳, 阳中有阴”</p>    <p><i><b>关于原文:</b><br>养生自己发明了一个方法, 平时把大拇指握在其他四个手指里。行走时假装失重, 有时拇指从其他四个手指里寻找借力来平衡, 有时其他四个手指也从拇指上找借力来寻找平衡。<br>题外解释一下, 手背为阳, 手掌为阴, 把大拇指握在手掌里这种互相借力的方法, 暗语称为“阴中有阳, 阳中有阴”<br><b>作者的解释:</b><br>重心前倾走路, 感觉快失重的时候拇指一顶, 就像顶在别的物体上一样顺势把重心调整过来。<br>语言表达有其极限, 你可以试着坐公共汽车, 扶着扶手, 感受用手指轻轻借力来维持身体平衡的状态。平时练习, 就把拇指当作其他手指扶着的扶手。以此保持身体平衡。或者把其他四个手指当作拇指顶着来维持平衡的物体。</i></p>    <p>中国的武家, 为了避免被禁武的当局发现自己在练武, 纷纷借用道家学说来掩盖武功的练法, 所以你看一本古代的武功秘籍, 里面一大堆阴阳啊, 五行啊, 千万不要奇怪, 那些都是为了保证这本书被警察看到的时候不至于让书的持有人满门抄斩才这么写的。用时髦的话来说, 道家的隐语成了军用密码。例如“吕洞宾”“吕纯阳”, “吕祖”这些词指的都是男人的小鸡鸡。 (洞里的客人)<br>这些军用密码, 在上一代的武术家都还有很多能翻译, 但是到了我们这一代, 能翻译的人就越来越少了。还有些乱翻译的人 (好吧, 我是在说我自己) , 搞得秘笈出版界一片混乱。<br>  读者们只需要明白, 当两个元朝/清朝初期的武术家在谈论“阴随以无厚入海”这种莫名其妙的话, 其实是在谈悄悄地背后用刀插入对方小鸡鸡附近的暗杀技术。就好了。</p>    <p>当统治渐渐稳定, 战场之拳再难有用武之地, 其中一部分战场之拳的传人沦为街头卖艺者, 向高难度的华丽动作发展, 一部分沦为拳手, 专业角斗供吃饱了撑的观众取乐 (或换个好听的说法说是参加奥运会为国争光) 。而其中一部分转变为义士之拳。</p>    <p>义士这个词, 在古代就是黑*色*会的意思。在元代, 是明教, 白莲教为主, 在清代是以天地会, 红花会等为主。这些秘密会社以反清复明为己任, 大多数时候潜伏在民间, 一般很少有大规模作战。打斗的对手一般也不是军人, 而是衙役, 捕头, 密探, 在这种情况下, 战场之拳就不那么实用了。其中有一些实战高手发明了更实用与当前这种情况的技术。</p>    <p>我年轻的时候, 遇到个练八卦掌的朋友, 这位朋友练了好几年的八卦掌, 但是还是打不过拳击手, 他十分苦恼。认为是他内力未到的原因, 实际上按他那种练法, 就算练十年, 也打不过练了十年的拳击手, 因为八卦掌这东西最早出现在商业社会的时候, 虽然是在一次职业擂台赛上, 但是八卦掌最早的诞生用途却绝非打擂台, 而是反清复明。<br>八卦掌的手法和身法让人眼花缭乱, 打击力却不尽如人意。有很多八卦掌的朋友因此苦恼, 都兼练铁砂掌之类的重手法, 但是铁砂掌配合到这样灵活的身手上却又没了威力。所以当世很多八卦掌名家都遇到两难的境地。<br>  实际上八卦掌的可怕之处还是在兵器上, 空手的掌法也是掩人耳目罢了, 甚至连八卦掌这个名字也是掩人耳目。八卦掌的精华在其独门武器子午鸳鸯钺, 这东西可以锁勾, 可以划, 可以抠, 可以割。但这东西也只是和平年代用来表演的。子午鸳鸯钺的真正平民身份是——镰刀。<br>  在夕阳下的小树林里, 一个双手持镰刀的农民, 突然用极其诡异的身法, 向着你的颈动脉, 股动脉, 脚筋, 腕动脉等地方连续不断地袭击, 你出一刀的时间他已经对你攻了五六刀。而当你反击的时候, 他又躲到了树后, 用匪夷所思的角度不断袭击你。八卦掌的“九宫步”, 说穿了就是在人群中, 树林里逃走或者躲闪反击的技术。在树林/无辜群众里的话, 什么形意拳, 什么太极拳, 都不是八卦掌的对手。<br>八卦掌其实是介乎暗杀拳和义士拳之间, <br>真正招牌的义士之拳就是“洪拳” (前身为太祖长拳, 后来者为国标武术长拳套路)<br>太祖长拳, 即托名宋太祖的黑*色*会拳法, 在元朝就有出现。<br>其特征如下:</p>    <p>  1. 注重王八拳 (最符合人体本能的拳法, 但此王八拳非彼王八拳, 下面会详述) <br>  2. 注重桥手 (小臂运用技巧) <br>  3. 注重移动, 上一招向东打, 下一招可能就向南跑了<br>  </p>    <p>今晚累了, 明天看看有没有朋友能猜到为何会有这三个特征。</p>    <p>&nbsp;</p>    <h2>二千年传承的古武术秘密 (三)</h2>    <p>小温侯所谓的言论自由, 我国自古就有, 不过定义稍有不同, 大多数人对言论自由的定义是 “我有批评你的言论自由, 但是你没有反驳我的言论自由。”</p>    <p>上个帖子里, 有人不就具体问题反驳或骂 (这点24倒是做得比他们好) , 却喋喋不休于“武人学文就是忽悠人”“我最反感有人一个人会很多门派功夫的”</p>    <p>金庸大侠说的好, 某些人一辈子就练一种拳法, 美其名曰“贵精不贵多”, 他们是否能做到“精”, 那是很可疑的, 至于“多”是肯定做不到的。所以只要有人说“贵精不贵多”, 他们就油然而生知己之感。<br>  而养生刚好相反, 所学的拳法能不能做到精这个很难说, 但至少种类多是无可疑的。而且读书不少, 所以绝不是他们的知己。</p>    <p>养生认为太极拳为刀盾兵所创, 证据嘛……比太极拳是张三丰夜梦神人所授, 或者陈王庭在乡下种田时拍脑袋想出来的还是要充足一点的。<br>  陈王庭创太极拳说, 来源于陈氏族谱。而养生的说法, 来源于春秋时期齐桓公的……错了, 那个应该是神虎术。那么就来源于李景林将军的秘传日记本好了, 李景林将军深明打仗之道。他日记里的记载应该比在座各位都有说服力吧? 看谁还敢质疑?</p>    <p>调侃就到这里好了, 前几天有兄弟其实已经答对了。义士之拳是利用杂物, 以少对多, 克制古代警察的一种拳法。</p>    <p>顺便回空格兄的话, 依靠鲸鱼和鲨鱼样子长得像, 是不能判断他们属于同族的, 但是却能够判断出这两种东西都是在海里生活的。因为他们的样子都符合海洋生物原则, 而不符合陆地生物原则。</p>    <p>我们先看看义士之拳必须符合什么原则</p>    <p>  1. 身体平衡, 不容易在移动中摔倒。一旦倒地, 就会被一堆捕快扑上去施展巴柔紧紧擒住。而被擒住的话, 则比死还惨, 自己受尽酷刑不说, 还要连累亲戚好友一起死。<br>  2. 反擒拿, 不能被人轻易用关节技抓住, 理由同上。<br>  3. 在一群围着自己的对手中找到可逃生的空位, 并且冲出去。<br>  4. 为活命不择手段。 (没错, 就是24如获至宝地发现的无限制格斗术)<br>  5. 简单速成。<br>  6. 所用武器便携。<br>  </p>    <p>义士拳五宝之一, 四平大马<br>大部分义士之拳里都有四平大马, 就算不是四平, 也是马步桩。李连杰演的精武门里批评马步桩, 说那样不适合起腿踢人, 所以是死马。那部片的动作指导估计是个李小龙迷+散打控, 哪里知道马步桩的妙处?</p>    <p>马步桩之妙, 第一在速成。<br>义士们平时要工作养家, 还要打扮成良民大大的样子, 自然不能像职业拳手那样买了各种器材, 公然夏练三伏冬练三九给官府看, 这样一来, 大多数时候也只有晚上睡觉前能关了灯练一阵子。在这种前提下, 四平大马就是最快的增加平衡力和腿力, 协调性的方法。</p>    <p>站四平大马也没啥标准和诀窍, 就是按标准站到四平状态, 站到四平就啥都懂了。诸如“两膝对称撑拔, 气沉丹田, 腰马合一。”等, 一句话概括起来都是四平状态, 说多了反而让人糊涂。<br>练拳有两种方法, 一种是明理后练拳, 一种是练拳后明理。前者精细, 后者强壮。各有各的好处。各有各的好处, 嘿嘿。</p>    <p>有人也许会说“四平大马这东西对膝盖有害啊, 是不科学的练法。”, 义士们对此则回答说, 眼前还活着最重要, 让科学见鬼去吧。<br>四平大马之妙, 还在于这是一种在移动时能时刻保持身体平衡的步法。拳击的步法在打中目标时固然威力强大, 但是在开始移动到攻击到目标之前, 身体都处于被他人一撞就会失重的状态。这种步法是不适合群战的。<br>当然, 义士之拳中也有高位步法, 所谓的高位步法也没什么特别, 就和田径运动员的短跑/跳远前的助跑差不多。但只要有人近身, 就会马上切换为马步。</p>    <p>&nbsp;</p>    <h2>二千年传承的古武术秘密 (四)</h2>    <p>AMAN和风云生是两个不同的例子, 风云生认为传统拳法有其适应性, 所以坚持在研究传统拳法在现代擂台上的应用, 以及和西方技术的结合。AMAN则直接否定, 认为传统的发力方式在西方人厚实肌肉面前不起作用。<br>对于适应性, 我的看法是这样的。<br>一匹马和一匹毛驴结合, 生下的是骡子。虽然骡子可能比马和驴都更适应特定环境, 但是他们非马非驴。<br>形意拳和拳击结合, 它们的产物可以叫形意拳击或者风云道, 但是不能叫形意, 也不能叫拳击。形意拳和拳击各有其对应环境, 集合了一些精华的同时, 必然导致其他一些精华的失传。以传承为目标的, 则是形意, 以发扬形意拳其中某些技术或训练方法为目标的, 则是风云道。</p>    <p>AMAN所练的, 则是散打, 散打就是散打, 不是别的东西, 他说他练过形意拳, 但只要他用的教的研究的练的不是形意拳, 那就等于没学过。把两者扯到一起, 也只是骗骗外国人吧。<br>  题外说一句, 85年左右我还是儿童的时候, 曾看过AMAN对张建国的散打比赛。因为某些缘故, 有深刻印象。一转眼二十多年, 物是人非, 真是让人感伤。</p>    <p>题外话说完了, 继续说义士之拳<br>义士之拳的第二宝, 是王八拳。<br>对于一般没受过职业训练的街战者来说, 为什么本能的用王八拳? 因为王八拳是一种杀伤范围大的拳法, 只要在手臂范围内, 都在扇形攻击覆盖下, 只有整体下潜躲闪才能躲得过。而会使用下潜躲闪的人一般都是受过职业训练的人 (会使用腰腿力) , 常人无非就是硬抗或者后仰躲闪。<br>王八拳能保证在自身训练时间较短, 而又面对大批平庸对手时, 有相对较高的命中率。而杀伤力问题则用武器来弥补。<br>《杀破狼》里吴京手持一把短刀来使用长拳。动作设计者是个明白人。但最适合长拳的武器不是短刀, 而是峨嵋刺, T字短拐等。一个王八拳摆过去, 对方低头闪过了后, 还能回手再摆一下或者顺势举起往下扎砸。一个回合能攻击好几次。如果配合马步移动还能造成一次出拳横扫几个目标。回步又横扫或者突捶其他目标等。<br>也许你这种横扫几个目标的拳法杀伤力不够大, 但却能起到“荡开阵脚”的地步。在横扫的过程中, 对手谁是最弱的, 马上就能分辨出来。</p>    <p>用三国演义中三英战吕布的局面来比喻一下, 三英战吕布描述的不是军阵, 而是小群殴, 吕布单对单未必能绝对搞定关羽张飞, 但是依靠赤兔马的移动和力量, 却能和他们两个打得不落下风。等到刘备上阵, 形成合围, 吕布移动就有了困难, 但刘备三人组中最弱的刘备还是成了吕布逃跑的突围点。<br>这个突围法, 是义士之拳的第三宝<br>冲撞<br>义士之拳中有很多冲捶类的拳法, 冲捶之后还有靠撞的小动作。<br>冲捶的原理和训练方法很简单, 就是上半身硬梆梆的, 把手和身体化为刚体, 利用下身的快速移动把这个刚体向对手捅去。这东西没什么技术含量, 就是简单速成, 无需悟性。<br>琉球人的空手道也是义士之拳的传承, 他们最喜欢召集一大堆学生把这样硬梆梆的一个正拳练上N久, 只有入室弟子花钱买了黑带才教身追手的破甲打。<br>  这个故事告诉我们, 功夫有时不需要精深, 只需要够用就好。一名义士如果能用这样没有技术含量的技巧在人群中冲撞出一个缺口跑掉。就是捡回了自己的命, 捡回了组织的命。捡回了红花会千千万万弟兄的命。</p>    <p>这类不精深但是好用的拳还有很多精髓, 例如 “唯快不破”。<br>人的反应神经最快的时间一般在0.2秒左右。很多拳击手出拳都比0.2秒快, 那么对手怎么办呢? 还是可以破, 因为可以观察对手的身体变化, 尤其是肩部或者脚步, 可以判断出提前量。<br>而大部分普通人出一拳至少要 1 秒, 那些没时间进行职业训练的义士估计不会比普通人好到哪里。但是他们却能做到超越对手的神经反应能力, 避开对手对自己的身体预估来对对手进行打击。<br></p><p>待续, 看看有没有兄弟猜到义士之拳中的 “唯快不破”是如何解释和应用的。</p>    <p>&nbsp;</p>    <p>唯快不破</p>    <p>在说这个技巧之前, 我先埋下伏笔。说一下别的东西。</p>    <p>  李小龙的截拳道创立时期, 李小龙主要的交手对象为中国南方的武师而非外国拳法, 而李小龙的拳法架势非常特别。在这里估计没人不了解截拳道的架势, 就不重复了。<br>  清末, 埋藏数百年的战场之拳太极形意等纷纷重出江湖。和八卦掌一起横扫北方武林。<br>  王芗斋认为形意拳有不适合环境的地方, 于是对形意拳进行了一定的改革, 其独特架势为前手远远撑抱的矛盾桩。<br>  </p>    <p>上述拳法在当时虽不能说中国无敌, 但是却都是一方豪强。至少都是公开接受挑战的。而且挑战者众。证明其是有实战作用的。<br>  但这几种拳法到今天则再也不能横扫一方, 为什么呢?</p>    <p>继续扯。</p>    <p>义士之拳故老相传中常说“某招可破某招, 某招可克制某招”。这些话, 练现代搏击的人自然都不屑一顾, 但是在一两百年前, 这些话是谁都不怀疑的真理。<br>原因就在唯快不破, 唯硬不破这八个字上。</p>    <p>上文说到人体反应一般最快就是0.2秒, 义士们在社会稳定的情况下, 纷纷退出江湖, 成为“技击家”, 作为技击家, 一般对手就是单体攻击为主, 虽然还有群战套路传下来, 但是较技时一般不用群战套路, 而是用门内秘传的“独门绝招”<br>  需的说, 这个世界上没有什么绝招, 只有对方破不了的攻击。要对方破不了, 只有更快。</p>    <p>在肌肉能力有其极限的情况下, 最快频率攻击对方的守则如下</p>    <p>  1. 动作尽可能小, 避免对手预读后躲避, 小动作也有两条出路, 一条出路是纯靠手法袭击对方面部脆弱器官, 身体不参与出力。另一条是手先动, 身体到2. 最后一刻才参与作功。<br>  3. 发力距离尽可能短, 距离2米出手, 就算再快也要0.7秒才打的到对手, 距离10厘米出手就算不快也只要0.1秒。<br>  4. 减少自己出拳时花费的思考和计划时间。<br>  </p>    <p>南方之拳术家相角, 则一二手, 多亦不过五六手, 势均力敌者, 不互中要害, 即相揪相扭, 同时力竭罢角, 或重整旗鼓, 相与复角, 曾未有角至若干手, 尚不分胜负者, 此其分别之点, 在北拳尚气劲, 南拳则不然, 纯以技巧胜, 功夫不到者无论已, 有工夫者, 其气劲不必惊人, 然出手必能创敌, 角时多不施展门户, 临时落马, 意到手随, 每有胜负之分, 非特旁观者, 不知所以致胜之道, 即被创之人, 亦多不明敌手来去之路。</p><center>&nbsp;&nbsp;&nbsp; —— 平江不肖生</center><p></p>    <p>&nbsp;</p>    <h2>二千年传承的古武术秘密 (五)</h2>    <p>东西方的思维模式是完全不同的, 好比说某男失恋后迁怒, 杀了他的教授, 东方思维是: “如果他没失恋, 就不会杀人了。”西方思维是“幸亏那女的没嫁给某男, 不然也和教授一起被杀了。”<br>这两种思维都是对的, 也都不对。</p>    <p>思维模式的差异, 最终使东西方拳法开始走向不同的领域。如果按西方的思维看唯快不破, 那么就是猛练速度, 比对手更快到达目的地。按东方的思维就是减少距离, 比对方更快到达目的地。<br>  我培训一批新下属时, 常用一个手段, 就是问对方认为自己的上限是每秒能打击多少次。有人回答1次, 有人回答3次, 有些经过锻炼对自己速度比较自信的人回答5 次。我便拿着秒表给他计时10秒, 让他尽全力高速鼓掌, 自己数次数。结果是很出人意表的, 一般普通人每秒鼓掌平均在7次以上, 部分人达到12次以上, 受训的人往往也被自己所数的次数所震撼。不相信是自己做出来的。</p>    <p>这个鼓掌的原理, 包含了许多纯技巧上的武学至理, 例如什么同动近取, 截拳中途, 本能出击, 贴身发力等。当然, 这些只是博大精深的武学中的一个局部。但人都有走极端的时候, 大约在清代中后期, 中国拳法在整体上就走向了这样的一个极端。<br>  因为义士之拳普遍使用小兵器作战, 所以在这个情况下, 你只要手上拿一支小铁笔, 用鼓掌的速度对对方眼睛, 咽喉连续猛插, 一般没练过的对手就铁定得死。<br>而如果手上没有小铁笔怎么办呢? 也有办法, 就是将自己的手练得坚硬如铁。这也是现代内家拳的人往往不齿的“局部力、局部硬度。”以一对坚硬如铁的手, 用练成了本能的鹤啄, 虎爪, 手刀, 拍掌等手法, 每秒7~12下地对对手脸部发动多角度攻击, 如果配合马步突进, 实际攻击速度还能翻倍。而人体反应速度的上限是每秒反应5次 (做到这点的也是神人了) 。外加眼睛受到威胁时的本能躲闪反应时间, 理论上几乎是1秒内必分胜负。<br>当双方都完全依靠“拳招”来形成鼓掌式攻击本能时, 谁的招数 (攻击角度次序) 最能克制对方的攻击角度次序, 谁就能先击中对手, 一旦击中, 则绵绵不绝。 (如果手持武器, 则一击必杀) , 在这种情况下, 传说中的“拳招时代”就到来了。</p>    <p>当然, 每秒 7~12 下只是理论速度。实际上影响攻击有效性的因素很多。为了对抗这种 “闪电手”, 我国拳法家也发明了很多训练方法, 例如 “听劲” “粘手” “擒拿” “拔根” “控距” “地堂” 等。</p>    <p>清末, 隐藏多年的战场之拳突然重出江湖, 大杀三方。并不是战场之拳在街头打起来一定真的比这种义士之拳实用, 而是因为“杀人时代”过去了, “比武时代”开始到来。在徒手比武中, 因为前提是被对方轻攻击击中非要害部位不会死, 那么战场之拳就能大行其道。<br>  战场之拳最擅长的就是用整劲使对方的锋锐 (长枪或鹤啄手, 砍刀或虎爪) 的攻击偏移, 使对方不能连击。例如形意拳的整劲硬打硬进, 八卦掌的闪击, 太极拳的缠绞。这些隐藏拳法的重出江湖, 为一味追求“唯快不破”的武林带来了一片新的气息。但也是真正的战场之拳, 义士之拳失传的开始。当战场之拳, 义士之拳用于和平年代的比武, 他们就像被阉割后的动物, 只能发出瞬间的光辉了。一旦有其他更适合和平年代比武的拳法出现, 这些旧时代的拳法就必然被淘汰或挂羊头卖狗肉。</p>    <p>而除此以外, 还有擅长距离控制的流派。例如大成拳和截拳道。<br>  大成拳王芗斋公然声称“一切局部硬度的手法打法, 全不足取”, 他在当时也未尝一败, 主要原因还是他的对手主要是古拳法, 他所发明的矛盾桩也是一种专门破解唯快不破拳法的架势, 重心后倾, 前手远撑不让对方近身, 后手和脚等待机会给与打击。这样的架势适合对抗古拳法, 却不适合对抗现代拳法。</p>    <p>李小龙的截拳架势则是侧身对敌, 用低端截踢控制距离。等待机会给与重击。这样的架势适合对抗古拳法, 但也不适合对抗现代拳法。</p>    <p>所谓的“拳本无法, 有法也空”“以无法为有法”其中透露出来的信息, 就是“用最适合环境的打法去在这个环境里打”, 在散打擂台上, 最实用的拳法就是散打, 在泰拳擂台上, 最实用的拳法就是泰拳。<br>  在这个和平年代, 最实用的拳法就是养生。如果以泡妞为目的, 最实用的拳法就是跆拳道 (不带I) , 如果想要保命, 则最实用的是消除自己的一切心理盲点, 让自己迅速进入环境, 进入角色。</p>    <p>空拳老陶的拳法可以说威力一般, 看老陶体型也很疏于锻炼, 但是我相信很多专心练习 XX 拳的人打不过他。原因无它, 因为他没有 “心理盲点”。这个心理盲点则是专注于 “XX拳” “XX擂台” 的人最致命的地方。<br>  替老陶打了一下广告, 这家伙应该付我钱。</p>    <p><b>--</b><br>附注:<br>  [1] 因为是论坛连载, 作者比较注重和读者回帖互动, 并调整内容。在结构上较为随意, 并没有完全按照提纲进行编写。<br>  [2] 这里是学习借用网友 "太极拳24" 的说法, 没有贬损的意思。  </p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820091129249650</comments>
    <slash:comments>8</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820091129249650</guid>
    <pubDate>Tue, 29 Dec 2009 14:04:09 +0800</pubDate>
    <dcterms:modified>2011-09-23T21:35:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[用 Python 写自己的 C Module]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182009810115428341</link>
    <description><![CDATA[<div><p>
本文说一下如何把 python 翻译成如假包换的 c 源码, 然后编译成一个 python module。据官方博客称性能接近或超过 c。用到了 pypy —— python 史上最大的玩具。
</p>

<p>
</p><p>先写个 python 源码文件, 待会编译出来:</p><pre># hello.py 文件<br><br><span style="font-weight: bold;">def</span> hello(a, b):<br>   <span style="font-weight: bold;">print</span> a, b<br>   <span style="font-weight: bold;">return</span> 'OK'<br><br><span style="font-weight: bold;">def</span> target(drv, args):<br>   <span style="font-weight: bold;">return</span> hello, [str, str]<br></pre>
<p></p>

<p><br>
</p><p>先测试通过:
</p><pre>&gt;&gt;&gt; <span style="font-weight: bold;">imp</span><wbr style="font-weight: bold;"><span style="font-weight: bold;">ort</span> hello<br>&gt;&gt;&gt; result = hello.hello('hello', 'world!')<br>hello world!<br>&gt;&gt;&gt; <span style="font-weight: bold;">print</span> result<br>OK<br></pre>
<p></p>

<p><br>
</p><p>翻译成 c 并编译:<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="text-decoration: underline;">$ pypy/translator/goal/translate.py --batch hello.py
</span></p>

<p>
生成的目标在, /tmp/usession-dist-USERNAME/testing_1/testing_1.so 。<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="text-decoration: underline;">$ mv /tmp/usession-dist-USERNAME/testing_1/testing_1.so _hello.so</span><br><br>
也可以写个自动化脚本编译完自动拷贝出去, 生成 testing_1.so 的目录位置在 driver.cbuider 对象里。可以参考 translate.py 写一个自己的编译平台 (哦, 一个玩笑)。
</p>

<p>
我们得到了 _hello.so 。里面有这么一个接口, 可以想见 python 调用起来很方便 (c 定义):<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span style="text-decoration: underline;">PyObject *pypy_g_pyfn_hello(PyObject *l_a_0, PyObject *l_b_0);</span><br><br>
至少在 pypy-1.1.0 里是这样的, 以后就不一定了。
</p>

<p><br>
</p><p>测试。先写个 _hello.so 的 python wrapper:
</p><pre># hello.py 文件, _hello.so 的 python wrapper<br><span style="font-weight: bold;">from</span> ctypes <span style="font-weight: bold;">imp</span><wbr style="font-weight: bold;"><span style="font-weight: bold;">ort</span> *<br>_hello = PyDLL('/PATH/TO/_hello.so')<br>_hello.RPython_StartupCode()<br>hello = _hello.pypy_g_pyfn_hello<br>hello.restype  = py_object<br>hello.argtypes = [py_object, py_object]<br></pre>
<p></p>

<p><br>
</p><p>测试通过:</p><pre>&gt;&gt;&gt; <span style="font-weight: bold;">imp</span><wbr style="font-weight: bold;"><span style="font-weight: bold;">ort</span> hello<br>&gt;&gt;&gt; result = hello.hello('hello', 'world!')<br>hello world!<br>&gt;&gt;&gt; <span style="font-weight: bold;">print</span> result<br>OK<br></pre>
<p></p>

<p><br>
</p><p>这样, 我们就可以用 rpython 来写可编译执行的 python c module 了 (这是 c 后端, 据称在 cli 和 jvm 上能做的事情更多一些)。然后好处是, 你的模块可以同时兼容 python2、python3、pypy 了。进一步他是个 c lib (pypy 会导出 c 接口), 其实在任何语言平台上都是可以用的。
</p>

<p>
不过, 这显然不是标准的 pypy 应用, 事实上我们应该用 pypy 的 MixedModule 来写。不过可惜的是 MixedModule 编译到 python c module 的功能已经在 pypy-1.1.0 取消了。pypy 团队在事后就此事和广大 pypy 用户进行了讨论, 取消该功能是否是个好主意 (在已经取消的前提下)。官方觉得, 还是专注于把 jit 搞好吧, 其他炫的东西先放一放, 毕竟 jit 搞定了, 你就不再需要什么 python c module 了。总之, 你需要等很久, 无聊的话, 像这篇文章这样玩一下也不错 。
</p>

<p style="color: rgb(102, 102, 102);">PS: 喜欢把 python 编译执行的朋友, 可以试一下 Cython 和 ShedSkin, 他们是专门为这个目标设计的。</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182009810115428341</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182009810115428341</guid>
    <pubDate>Thu, 10 Sep 2009 11:54:28 +0800</pubDate>
    <dcterms:modified>2009-09-16T08:24:17+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[中國書畫史半部在湖州]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182009824511595</link>
    <description><![CDATA[<div><center><img title="中國書畫史半部在湖州 - 沈崴 - 蜻蜓点水 举重若轻" alt="中國書畫史半部在湖州 - 沈崴 - 蜻蜓点水 举重若轻" src="http://news.hz66.com/Files/newscenter/2009/02/19/1%E4%B9%8C%E7%AF%B7%E8%88%B98.JPG"></center><br><br>當時與人同遊於湖州霅溪公園, 我若有所思地說, 米南宮的《苕溪帖》正是泛舟於那一旁河水之上所就。是我最喜歡的行書之一了。對著公園的畫壁詩書, 我歎道, 半部詩畫史都在湖州, 幾面牆壁又怎能容下呢, 就連那些名篇工匠都還沒刻上去呢。旁邊問, 既然如此, 現在的湖州為何如此不顯? 我說大概是因為那時藍營又稱湖州幫吧, 人走茶也涼, 秋風掃落葉。時代變遷, 文化凋零, 往事已矣。如今也衹有那遠來的姑蘇客, 古風依舊, 尚依稀記得湖州在建國前幾千年歷史上的輝煌了[1]。<br><br>我比較喜歡行書, 算是對半部書法史有所了解。忽然興之所至, 說一下湖州有關的書法人。本來也沒想過要寫湖州的書法, 過於浩瀚且不想查資料, 累人。今天記下來, 或許只是為了備忘。上次講到巨鹿大戰破釜沉舟殲滅四十萬秦軍一戰成名的八千子弟、烏程 (湖州秦代古稱) 軍, 還有那不肯過烏江相見的江東父老, 就是你湖州人, 這段英雄悲壯的歷史, 衹怕湖州人自己都已經淡忘了吧。現在知道湖州項王城、霸王門這些地方的人, 除了小時候就有印象的中年人, 就剩老人了。網上《史記》記項羽起兵吳中, 基本被考證到蘇州新鮮設立的吳中區了。然後誰跑出來說話了呢? 是顏真卿。<br><br>顏魯公時任湖州刺史。在項羽駐軍的地方, 立弁山碑 "西楚霸王, 当秦之末, 与叔梁避住于吴中, 盖今之湖州也。虽灭秦而宰制天下, 其魂魄犹思乐兹邦, 至今庙食不绝"。一般來說, 司馬遷所撰, 被人奉為信史, 歸其治史態度。顏真卿其人格魅力更令人敬佩, 被認為絕不可能妄言。身處中唐亂世的顏真卿為人正直, 在安史之亂中平叛有功, 為玄宗所識。後身為國家重臣, 明知是一去不返, 仍赴汝州撫叛。叛將李希烈脅迫顏真卿上輸漂白自己, 遭怒斥。李希烈羞愧不已, 扣留了颜真卿。顏真卿面對威逼利誘全然不為所動, 大義凜然慷慨赴死, 至死痛罵反賊。顏真卿死後, 舉國哀悼, 三軍慟哭, 其高風亮節為世人楷模。<br><br>從孔子的知其不可為而為之, 到浩然天地正氣, 再到我心光明, 亦复何言! 這就是中國士人, 這就是顏體字的風骨。我們初學書法時, 常說要從顏體字練起, 以顏字為骨不管多大的字都可以寫, 氣勢磅礴。不知湖州人在練習書法時, 臨摹湖州前任市長的筆跡時, 想到字如其人, 想到隨字跡千古流傳下來的那股精神, 心中是否會感慨萬千。<br><br>除了顏魯公、楚霸王的遺跡, 還有更多年輕湖州人所不自知的, 比如湖州中心城區, 是愛山街道、愛山廣場, 和愛山臺。仁者樂山, 智者好水。愛山所謂, 源於湖州另一任市長蘇軾留在湖州的名句 "道場山頂何山麓, 上彻雲峰下幽穀, 我從山水窖中來, 尚愛此山看不足"。李煊寫道 "儂家生長碧湖頭, 打漿真從鏡裏遊。難怪當年蘇學士, 杭州不住住湖州", 可以發現其實湖州才是讓蘇東坡真正寄情的地方。可惜蘇學士生老湖州的願望最後沒有實現, 蘇軾在湖州任上發生了 "烏臺詩案", 貶放黃州。<br><br>除了詩詞, 蘇軾同樣以書法聞名, 和上面提到的米芾一樣, 屬宋四家。宋字不似晉唐, 浪漫飄逸, 就連皇帝和奸臣大抵都寫得一手充滿個性的好字, 令人印象深刻。觀宋帖, 深得生活樂趣, 百看不厭。<br><br>湖州的另一古稱, 吳興, 在書法史上也是振聾發聵。行書的創立者, 王羲之、王獻之都是吳興太守。而趙孟頫則是吳興人 (湖州人)。在霅溪公園韓世忠像邊 [2] 是趙孟頫的吳興賦。我在湖州有看到兩份吳興賦的字碑, 另一個是在湖州園林 [3] 也是趙孟頫別業的蓮花莊內。趙孟頫寫字, 上下前後大小疏密, 一筆一劃, 安排縝密, 用儀器也無法找出破綻, 精美漂亮之極, 令人驚歎。二王就不說了, 都是練字者傾其一生難以超越的人。自古以來, 無數書法家為此發出望洋興嘆的感慨。我寫得一手爛字, 一如《寒食帖》說的, "死灰吹不起", 再練也枉然, 卻能放下心態享受欣賞和臨字的樂趣, 不亦快哉。<br><br>而想到碼這麼一大篇文字, 卻是因為另一位書法家, 杜牧的關系。那時杜牧聽聞湖州美女如雲, 就跑去打望。果然對一清麗出俗的女孩子一見鍾情, 為了說服她的家人, 便約定十年為期, 必來湖州做市長, 到時來娶這女子。由是要當上湖州刺史成為杜牧的終極奮鬥目標。輾轉黄州、池州和睦州, 歷時十四年的打拼, 杜牧終於做上了湖州刺史。然而此時該女子已經出嫁。杜牧質問 "昔既許君矣, 為何適人?", 答曰 "向約三年, 不來而後嫁, 嫁已三年矣"。這讓杜牧傷心欲絕, 寫下 "自是尋春去較遲, 往年層見未開時。如今風擺花狼藉, 綠葉成蔭子滿枝" 的悵詩。<br><br>"清明時節雨紛紛, 路上行人於斷魂。借問酒家何處有? 牧童遙指杏花村" 可見當時杜牧的心境。<br><br>每到一年七夕, 在歡樂的氣氛中我都會想起惆悵的杜牧。七夕是個相當溫情的節日, 是父母獻給女兒的女兒節, 是姐妹們一起相伴度過的乞巧節。七夕作為中國的情人節, 一如中國人的愛情, 含蓄到甚至不像是情人節, 因為它本來就是情人的節日。因為商業需要, 我們把西洋情人節的成功模式搬進七夕。在歡騰的氣氛中, 在節日的餐館前排隊等候, 等候消失於快餐文化中。很難再有時間為了一個虚幻的約定去努力、去等待十年, 這種一刹那凝固, 卻能在千百年後依然能被人在無意間想起的愛情。這幕喜劇不是比悲劇更可悲嗎。或許我門可以再靜靜地看著星空, 天上的鵲橋, 牛郎和織女在那裏相會呢。那一幕靜謐之美, 一如書法一樣永恆。<br><br>半部書畫史都在湖州, 然而今天湖州卻在中國消失了。是我們拋棄了她, 還是她拋棄了我們? 到了七夕, 我就會想起杜牧, 想到書法, 想到該寫些什麼。達則兼濟天下, 窮則獨善其身。當你想告訴別人, 像中國人一樣活在天地之間是一件相當開心的事情, 往往是沒有效果的。一個人的福分, 衹有自己努力, 不是別人能硬塞給他的。<br><br>哦, 對了。文房四寶之首, 就是湖州的湖筆。<br><br><br>-<br>[1] 直到上個世紀, 湖州仍然在創造輝煌的歷史。中國四大商幫中唯一一個地區性商幫, 富可敵國的湖商, 崛起於近代。傾資財幫助孫中山革命, 是主要財力來源, 並且在革命中湖州人捨生取義, 為現代中國的締造奮不顧身。在已經佚去的歷史中, 也是上海的主要構建者之一, 壟斷上海的金融、商業、地產等高層架構, 上海幾乎就是湖州人的財產, 也造就了亞洲第一大都會城市的繁榮。新中國建立以後, 當時還沒有現在私有制的概念, 土地財產均分, 有財產就必須死。湖商的輝煌也就成為絕響, 瞬間淡出歷史。上海也逐漸淪為亞洲的二流城市。<br><br>據網文《再論湖州的發展》(http://bbs.sogou.com/110218/u96uyPyA49mIBAAAA.html) 描述: 新中國成立後, 湖州近代史上的從政從商者隨著舊政權的垮臺而逐漸隱退, 在遠走他鄉的同時, 一大批山東團營級老幹部降臨這座江南小城, 除了在生活上多娶了一房湖州女人外, 在文化上很難和湖州人融合在一起, 他們執政湖州時顯得束手無策, 湖州人一直很藐視他們, 稱之為 "彎舌頭", 整個城市象一對貌合神離的夫妻, 過著同床異夢的生活。但是從商的念頭一直跳動在小城人的心間, 直到文革其間, 一位李姓商人被 "投機倒把罪" 判處死刑後, 湖州僅剩的一點元氣也蕩然無存。改革開放後, 湖州經濟社會的發展變得中規中矩, 象奧運會會上跳水的常規動作, 沒有難度系數, 唯求入水花小罷了。<br><br>—— 湖州的老本一直吃到八十年代, 便被蘇州和新貴杭州超越。在 GDP 上。<br><br>[2] 公園旁就是馬軍巷, 韓世忠駐軍和金國決戰的地方, 立像以為紀念。<br>[3] 《江南園林志》稱, 南宋以來, 園林之勝首推四州, 湖、杭、蘇、楊。湖州居首。<br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182009824511595</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182009824511595</guid>
    <pubDate>Wed, 2 Sep 2009 16:51:15 +0800</pubDate>
    <dcterms:modified>2009-09-18T15:15:53+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[上海 python 聚会]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820097242653395</link>
    <description><![CDATA[<div><p></p><center><img title="上海 python 聚会 - 沈崴 - 蜻蜓点水 举重若轻"  alt="上海 python 聚会 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://www.chinachunqiu.com/wp-content/uploads/2009/08/P8090031.JPG"  style="width: 600px;"  ></center><center style="font-size: 9px; color: rgb(102, 102, 102);"  ><a rel="nofollow" href="http://www.chinachunqiu.com/"  >图片来源于 meng9999 的博客</a></center><p></p>    <i style="font-size: 13px;"  >  <p>我们 python 上海社区最近于 2009 年 8 月 9 日进行了一次技术聚会, 由支晓勇准备了场地和设备, 志愿者们录像、摄影, 打理了各种事务。活动看上去井井有条, 还是比较圆满的。而且会后各种资料整理得相当齐全, 尤其是<a style="color: rgb(51, 51, 136);" rel="nofollow" href="http://www.tudou.com/playlist/playindex.do?lid=6791340"  ><b>视频资料</b></a>让没有赶去上海的朋友也能身临其境。在此感谢所有志愿者付出的辛勤工作!</p>    <p>同时也要感谢 robbin 和 javaeye 社区为活动做的支持和宣传。Javaeye 的号召力, 轻松挤爆了科学会堂。在第一个演讲中还可以持续不断地听到有搬凳子加座位的声音。自 2001 年以后从诸如 c++、java 那些忍受快十年的技术, 轻身一跃, 完全转到 python 以后, 我就逐渐走向了 c++ 和 java 技术设计思想的反面。但 javaeye 是少数我比较关注的 java 类社区。Javaeye 社区是国内动态语言技术的先行者, 对 ruby 技术的推广不遗余力, 同时也是 python 技术的重要山头之一。Robbin 也参加了聚会, 一如他的照片可以一眼认出来。本人较照片更有型。</p>    <p>应组织者支支的要求, 我做了 eurasia3 相关技术的主题演讲 (<a style="color: rgb(51, 51, 136);" rel="nofollow" href="http://www.tudou.com/playlist/playindex.do?lid=6791340&amp;iid=34406198&amp;cid=21"  ><b>第五段视频</b></a>)。</p>  </i>    <br><br>    <p>昨天 8 月 23 日, 我们就如何把以后上海 python 聚会的组织得更好, 于科技会堂再次进行了线下讨论。我们觉得上海 python 技术聚会一直有在办, 以后可以更常态化, 并且做到更好、做到超赞。归纳一下, 我们谈到以下几点。</p>    <h2>1. 我们需要好的场地。</h2>    <br>    <p>好场地可以产生好氛围。上次聚会我提到像科技会堂、学校教室容易产生上课的效果, 而我们可能更喜欢放松、愉快的效果, 比如茶话会形式。场地影响到活动形式, 然后改变活动内容, 我们可能不再以会课、演讲形式为主, 而使用更轻松的活动方式。我们提到将来可以采用的场地和形式有咖啡馆、一茶一座、公园以及烧烤等。</p>    <p>与会人士纷纷表现出向往的神情。</p>    <p>支晓勇提到, 作为长三角 python 用户组, 不能局限于上海。下一次可以开展到苏州、南京、杭州等地方。组织方可以提供方便, 比如把上海或者其他地方的人打包运到杭州。根据案例算上交通、饮食每人共需花费 60￥, 费用自理。旅游 + 技术, 交流 + 休闲, 还能把 python 技术推广到长三角各个城市。</p>    <p>所有人表示支持, 高呼满塞。</p>    <p>这就产生一个衍生话题, 活动经费的问题。我认为像上次那样由组织者也就是支晓勇承担所有场地和设备的费用 (科学会堂场地租用是 700￥, 仅租用场地方投影 400￥ … 等等) 可行但不利于长期开展活动, 或许个人可以长期负担这项开支, 但是这也对活动产生限制, 比如我们就不能开展上面提到的旅游聚会, 我们总不至于让组织者个人来支付所有人的旅行的开销吧。同时我们认为为了举办活动而收取固定会费也是不可取的。</p>    <p>我们很快想到了解决办法, 在活动前的一段时间, 我们可以先在网上召唤出足够多可选的场地, 并给出每个场地产生的费用。比如咖啡馆, 每人只要买一杯 20￥ 的饮料即可蹭一下午, 烧烤亦然。公园场地、科学会堂则在网上对当此活动每人需要分摊的经费进行公示。我觉得如果谁有认识不错的场地提供方, <span style="font-weight: bold;"  >我非常推荐给他们拉下生意, 比如咖啡馆、酒吧之类</span>, 只要他们愿意为我们提供实惠的价格和良好的服务, 这绝对是双赢的好事情!</p>    <p>大家在网上对列出的场地进行投票, 选出支持率最高的。</p>    <p>我认为在会的志愿者大家都是活动的参与者和决策者, 大家一起提供场地选项, 投票决定。只是志愿者要更热心一些。然后比如大家认为下一次活动可以在杭州举行, 那么我们就根据投票里面公示的地点、日程和费用, 包车, 并把杭州场地搞定。除了上海, 比如南京的同学在志愿者的努力下也应该可以一起打包前往。</p>    <h2>2. 我们需要好的内容。</h2>    <br>    <p>几个世纪以来, 漫长而又沉闷的演讲, 无尽的技术剖析, python 技术推广一直是我们的光荣传统。</p>    <p>我的观点是, python 技术和技术聚会也可以是一种生活, 我们可以不用刻意去搞一次技术交流, 因为这本来就是周末可以选择的一种休闲, 它带来愉悦, 这就像生活本身一样自然。我们享受生活。如果这不是生活, 就会是一种负担, 我们很难坚持做一件给自己带来压力和负担的事情。</p>    <p>我们谈到很多有意思的交流的方式, 比如 7 分钟演讲。演讲者可以随时被番茄轰炸下去。提出 7 分钟演讲的同学说, 他参加这类活动, 场面火爆, 天涯海角、绿树红花、千奇百怪、海阔天空、欢声笑语、鸟语花香。我们还可以像广州 python 聚会和 google 那样插播乐器演奏和才艺表演。并且鼓励参与者做一些有趣的技术演示, 提供看得到的好玩, 比如 pygame 、硬件 DIY 等。</p>    <p>加入诗歌朗诵、才艺表演, 把技术聚会变成周末娱乐, 回过头来发现本质上依然是技术交流, 依然是会课, 这不是更好的 python 推广吗。就好像本质上是填饱肚子, 除了让人如同嚼蜡, 我们还可以选择把菜做得相当艺术。</p>    <p>活动内容集思广益, 投票决定。决定活动形式和大家感兴趣的技术话题, 其中当然也包括较为严肃的会课, 提供入门或者某些专题技术的系统讲解。一些大家不太感兴趣的话题只要人数足够也提供专场活动。这也是大家所需要的。这并不矛盾, 社区里不同口味的技术人员应该可以自己组织起不同形式的活动, 甚至可以在同一场分成不同话题和形式的多个讨论区。</p>    <p>我提到技术沙龙应该还具有更多的功能。比如撮合项目, 可以是开源项目、公共项目也可以是商业项目, 让志同道合的人走到一起, 发现商机, 共同解决技术难题, 或者合作创业。而这又回到前面, 我们需要一个能让大家充分放松、令人愉悦的环境, 还有开放式的、扫除拘谨的活动形式。这样就不会像上课那样只有一个演讲者在那里讲, 所有人都可以方便地交流观点, 互相认识。</p>    <p>我们需要这么一个平台, 不是么?</p>    <p>开始的自我介绍就会比较重要, 可以让大家先介绍一下自己, 网名, 从事的工作和感兴趣的技术。每个人一旦开讲, 就会消除很多拘束, 大家迅速熟悉起来。</p>    <p>对于喜欢在技术交流上作商业广告的同学, 我并不排斥。只要对大家真的有用, 并且不要过了限度变成你的广告发布会, 我也不会强烈反对。</p>    <h2>3. 接下来的活动</h2>    <br>    <p>我们谈了下以后可以为 python 技术聚会长期开展能做的事情。我们纷纷表示为了正义的 python 事业有力出力, 没钱卖血。基本上, 我们可以贡献的是投影仪、摄像机等器械, 人力还有时间。希望更多的朋友能够加入进来, 人多力量大。</p>    <p>接下来可能会先找一下提议、投票等组织工具, 如果现有的不够用/不够好用, 反正这里都是程序员 ……</p>    <p>长三角地区, 如果你有熟悉的场地, 如果你有亲戚朋友或者自己在经营咖啡馆酒馆茶馆, 如果你比较熟悉旅行社, 如果你能够为 python 技术聚会提供任何帮助, 欢迎联系我们。</p>    <p>你可以发信联系支支同学 (他是上次活动的组织者, 他把全家都动员了)。</p>    <p></p><center>支晓勇 hunterpig(at)gmail.com | 当然也可以联系我 wileishn(at)gmail.com</center><p></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820097242653395</comments>
    <slash:comments>3</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820097242653395</guid>
    <pubDate>Mon, 24 Aug 2009 14:06:53 +0800</pubDate>
    <dcterms:modified>2011-09-23T22:28:06+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[编译中文 Python 文档 (LaTeX2HTML)]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200882523153649</link>
    <description><![CDATA[<div>随着 <a target="_blank" rel="nofollow" href="http://code.google.com/p/eurasia"  >Eurasia 3.0.0 a5</a> 的临近, 文档的跟进变得越来越重要。这趟, 我决定把 Eurasia3 文档做成标准的 Python 模块文档。做法很简单, 先把文档写成 LaTeX, 然后调用 Python/Doc/tools/mkhowto 脚本编译成 HTML 等文档。<br><br>直接用 LaTeX CJK 来编译中文文档很顺利, 但是 Python 的 mkhowto 脚本好像对 CJK 支持有些问题。我对调试没什么兴趣, 经过分析, 用一个转换脚本了事。步骤如下。<br><br>首先编写 LaTeX 文档, 但是在文档中不要申明使用 CJK 支持。<br><br>% 一个 tex 文件<br>\documentclass{man l}<br>\title{标题}<br>\author{作者}<br>\authoraddress{<br>&nbsp;&nbsp;&nbsp; 邮箱: \email{xxx@gmail.com} \\<br>&nbsp;&nbsp;&nbsp; 项目: \url{http://code.google.com/p/xxx/}<br>}<br>\date{2008}<br>\release{x.x.x} % release version<br>\makeindex<br>\begin{document}<br>...<br>\end{document}<br><br><br>诸如此类, 然后调用 mkhowto 脚本。<br><br>/PATH/TO/PYTHON/SOURCE/Doc/tools/mkhowto xxx.tex<br><br>这样 Python 的 HTML 文档就生成好了。不过文档里的中文是乱码。然后编写一个转换程序, 把乱码转成 UTF-8 中文。<br><br>#!/usr/bin/env python<br>import os, os.path<br>dirname = 'HTML文档目录'<br>for filename in os.listdir(dirname):<br>&nbsp;&nbsp;&nbsp; if filename[-5:].lower() != '.html':<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; contin <br><br>&nbsp;&nbsp;&nbsp; fullname = os.path.join(dirname, filename)<br>&nbsp;&nbsp;&nbsp; data = unicode(unicode(open(fullname).read(), 'utf-8').encode('iso8859-1'), 'utf-8').encode('utf-8')<br>&nbsp;&nbsp;&nbsp; fd = open(fullname, 'w')<br>&nbsp;&nbsp;&nbsp; fd.write(data)<br>&nbsp;&nbsp;&nbsp; fd.close()<br><br>原理是先按 utf-8 编码把乱码文件 decode 成 unicode, 然后 encode 到 iso8859-1, 然后再用 utf-8 decode 到 unicode, 最后用 utf-8 输出。这样乱码文件就还原了。</div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200882523153649</comments>
    <slash:comments>4</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200882523153649</guid>
    <pubDate>Thu, 25 Sep 2008 14:31:53 +0800</pubDate>
    <dcterms:modified>2011-09-26T01:51:30+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[奥运编码器]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820086261470252</link>
    <description><![CDATA[<div>为迎奥运, 特地写了个发帖编码器, 希望还没被封站的各位站长喜欢。<br><br>escape = lambda s: __import__('re').compile(r'(\\u([0-9a-f]{4}))').sub(lambda m: '&amp;#%d;' %int(eval('0x' + m.groups()[1])), repr(s)[2:-1])<br><br>后来看了 est 的回帖, 发现我这个只能算是脱裤子放屁版。以下正解由 est 提供, 达人在此快来瞻仰!<br><br>escape = lambda s: '&amp;#' + ';&amp;#'.join(str(ord(x)) for x in s) + ';'<br><br>这里是效果:<br><br>&amp;#12304;&amp;#38472;&amp;#22825;&amp;#20339;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#36814;&amp;#25509;&amp;#21478;&amp;#19968;&amp;#20010;&amp;#26216;&amp;#26342;&amp;#65292;&amp;#21628;&amp;#21560;&amp;#27745;&amp;#26579;&amp;#31354;&amp;#27668;<br>&amp;#12304;&amp;#21016;&amp;#27426;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#25351;&amp;#26631;&amp;#25913;&amp;#21464;&amp;#21619;&amp;#36947;&amp;#19981;&amp;#21464;&amp;#65292;&amp;#23614;&amp;#27668;&amp;#39128;&amp;#28385;&amp;#19996;&amp;#35199;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#37027;&amp;#33521;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#25105;&amp;#23478;&amp;#22823;&amp;#38376;&amp;#24120;&amp;#25171;&amp;#24320;&amp;#65292;&amp;#22806;&amp;#22320;&amp;#20154;&amp;#20986;&amp;#21435;<br>&amp;#12304;&amp;#23385;&amp;#29141;&amp;#23039;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#25910;&amp;#23481;&amp;#36807;&amp;#23601;&amp;#26377;&amp;#20102;&amp;#26696;&amp;#24213;&amp;#65292;&amp;#20320;&amp;#36824;&amp;#25954;&amp;#26469;&amp;#36825;&amp;#37324;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#23385;&amp;#24742;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#19981;&amp;#31649;&amp;#36828;&amp;#36817;&amp;#37117;&amp;#26159;&amp;#23458;&amp;#20154;&amp;#65292;&amp;#21487;&amp;#26159;&amp;#20998;&amp;#31561;&amp;#32423;<br>&amp;#12304;&amp;#29579;&amp;#21147;&amp;#23439;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#21482;&amp;#35201;&amp;#20320;&amp;#26377;&amp;#20154;&amp;#27665;&amp;#24065;&amp;#65292;&amp;#25105;&amp;#20204;&amp;#27426;&amp;#36814;&amp;#20320;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#38889;&amp;#32418;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#25105;&amp;#23478;&amp;#20303;&amp;#30528;&amp;#27915;&amp;#22823;&amp;#20154;&amp;#65292;&amp;#24320;&amp;#25918;&amp;#33258;&amp;#24049;&amp;#36523;&amp;#20307;<br>&amp;#12304;&amp;#21608;&amp;#21326;&amp;#20581;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#22312;&amp;#25105;&amp;#30340;&amp;#20307;&amp;#20869;&amp;#25773;&amp;#31181;&amp;#65292;&amp;#20026;&amp;#20182;&amp;#30041;&amp;#19979;baby<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#26753;&amp;#21647;&amp;#29738;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#36827;&amp;#20140;&amp;#26242;&amp;#20303;&amp;#37117;&amp;#24471;&amp;#21150;&amp;#35777;&amp;#65292;&amp;#19981;&amp;#36319;&amp;#20320;&amp;#25304;&amp;#31036;<br>&amp;#12304;&amp;#32701;&amp;#27849;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#31532;&amp;#20960;&amp;#27425;&amp;#36827;&amp;#26469;&amp;#27809;&amp;#20851;&amp;#31995;&amp;#65292;&amp;#27809;&amp;#35777;&amp;#36824;&amp;#25304;&amp;#20320;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#25104;&amp;#40857;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#21271;&amp;#20140;&amp;#27426;&amp;#36814;&amp;#20320;&amp;#65292;&amp;#20026;&amp;#20320;&amp;#24320;&amp;#22825;&amp;#36767;&amp;#22320;<br>&amp;#12304;&amp;#20219;&amp;#36132;&amp;#40784;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#20809;&amp;#26045;&amp;#24037;&amp;#36153;&amp;#23601;&amp;#33457;&amp;#20102;&amp;#20960;&amp;#21313;&amp;#20159;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#34081;&amp;#20381;&amp;#26519;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#21271;&amp;#20140;&amp;#27426;&amp;#36814;&amp;#20320;&amp;#65292;&amp;#22312;&amp;#22826;&amp;#38451;&amp;#19979;&amp;#31579;&amp;#27801;&amp;#38138;&amp;#22320;<br>&amp;#12304;&amp;#23385;&amp;#26976;&amp;#12305; &amp;#24178;&amp;#23436;&amp;#27963;&amp;#28378;&amp;#22238;&amp;#32769;&amp;#23478;&amp;#21435;<br>&amp;#12288;&amp;#12288;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#21608;&amp;#31508;&amp;#30021;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#25105;&amp;#23478;&amp;#22823;&amp;#38376;&amp;#24120;&amp;#25171;&amp;#24320;&amp;#65292;&amp;#25910;&amp;#20837;&amp;#26469;&amp;#33258;&amp;#21508;&amp;#22320;<br>&amp;#12304;&amp;#38886;&amp;#21807;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#23601;&amp;#24403;&amp;#25903;&amp;#25345;&amp;#39318;&amp;#37117;&amp;#20154;&amp;#27665;&amp;#65292;&amp;#27809;&amp;#20160;&amp;#20040;&amp;#20102;&amp;#19981;&amp;#36215;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#40644;&amp;#26195;&amp;#26126;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#22825;&amp;#22823;&amp;#22320;&amp;#22823;&amp;#37117;&amp;#26159;&amp;#26379;&amp;#21451;&amp;#65292;&amp;#37027;&amp;#26159;&amp;#22312;&amp;#25918;&amp;#23617;<br>&amp;#12304;&amp;#38889;&amp;#24218;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#20294;&amp;#20320;&amp;#33509;&amp;#26159;&amp;#37329;&amp;#21457;&amp;#30887;&amp;#30524;&amp;#65292;&amp;#25105;&amp;#23601;&amp;#31561;&amp;#24453;&amp;#20320;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#27754;&amp;#23792;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#21271;&amp;#20140;&amp;#27426;&amp;#36814;&amp;#20320;&amp;#65292;&amp;#20351;&amp;#21170;&amp;#35752;&amp;#22909;&amp;#24863;&amp;#21160;&amp;#20320;<br>&amp;#12304;&amp;#33707;&amp;#25991;&amp;#34074;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#35753;&amp;#22823;&amp;#22920;&amp;#37117;&amp;#21152;&amp;#27833;&amp;#21435;&amp;#23398;&amp;#33521;&amp;#35821;<br>&amp;#12288;&amp;#12288;<br>&amp;#12304;&amp;#35885;&amp;#26230;&amp;#12305;&amp;#12288;&amp;#21271;&amp;#20140;&amp;#27426;&amp;#36814;&amp;#20320;&amp;#65292;&amp;#26377;&amp;#22806;&amp;#22269;&amp;#25252;&amp;#29031;&amp;#20102;&amp;#19981;&amp;#36215;<br>&amp;#12304;&amp;#38472;&amp;#22869;&amp;#36805;&amp;#12305;&amp;#12288;&amp;#12288;&amp;#26377;&amp;#32654;&amp;#20803;&amp;#23601;&amp;#20250;&amp;#26377;&amp;#22855;&amp;#36857;<br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820086261470252</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820086261470252</guid>
    <pubDate>Sat, 26 Jul 2008 13:47:00 +0800</pubDate>
    <dcterms:modified>2008-09-10T09:57:02+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[[沈著湖州文史志] 第一章 治水英雄防风王]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820085484747953</link>
    <description><![CDATA[<div><p style="text-align: center;"><img title="[沈著湖州文史志] 第一章 治水英雄防风王 - 沈崴 - 蜻蜓点水 举重若轻" alt="[沈著湖州文史志] 第一章 治水英雄防风王 - 沈崴 - 蜻蜓点水 举重若轻" src="http://travel.people.com.cn/mediafile/200712/11/P200712111830531938013424.jpg"></p>

<br><br>

<div style="font-size: 16px;">
<p>九百多年前, 一位慎姓京官外放湖州。当其所乘官船路过湖州归安县的潞溪时, 不禁为眼前的小桥流水和碧水青山所动, 于是产生了在此颐养天年的念头。没过多久, 致仕后的慎氏果真携家眷来潞溪定居, 过上了世外桃园般的生活, 且 "后人蕃衍多业儒", 成为湖州潞村的一大望族 [1]。慎氏后人中, 有一位中国的考古大家, 他就是慎微之先生。</p>

<p>二十世纪初, 随着西方近代考古学的传入, 黄河流域频频传出重大的考古发现, 一时黄河流域俨然成为中华文化的 "唯一" 发源地。在意识到这种思潮的荒谬之后, 江南史学界开始发掘长江下游的史前文化。出于小时候的经历, 慎微之先生马上把目光投向了离家不远的钱山漾。1934 年夏, 恰逢湖州大旱, 钱山漾水位落至 1857 年以来的最低, 露出多至三分之二的湖底。趁此良机, 慎微之冒暑拾取了大量的石器, 并据此写出巨著《湖州钱山漾石器之发现与中国文化之起源》。距今约 5250 ~ 4150 的良渚文化 [2] 遂浮出水面。</p>

<p>湖杭地区的良渚文化坐实了中华 5000 年的文明史, 同时随着我们在湖州钱山漾发掘出诸多保存完好的丝织品 (距今 4700 年), 中国丝绸的最终发源地也终于尘埃落定。这些文明的证据 [3] 慢慢撩开了历史的重重迷雾, 去伪存真。他们揭示了中华文明的起源, 就在于湖州地区。</p>

<p>因为得天独厚的气候地理条件, 湖州地区成为远古蛮荒时代最适宜人类居住的地方之一, 而太湖、下渚湖等水系则更使湖州成为人类文明诞生的摇篮。早在 10 万年前的旧石器时代, 湖州西苕溪流域就已有古人类生活了 [4]。经过五六千年前的新石器时代 [5], 到 5000 年前的良渚文明时期, 当时中国正处于部落联盟时期, 众古国皆以湖州德清传说中防风国地区 [6] 的部落为盟主。至此湖州地区已经成为中国整个东部和南部的文明中心。</p>

<p>这是一个空前强盛的农业文明。作为日用品的陶器、玉器工艺先进制作精美, 尤以黑陶著称。而且先民早在 5000 年前就已经穿上了丝制的衣服, 并且住在宽畅的九室 "豪宅" 里 [7]。皆令人叹为观止。同时湖州地区水网纵横渔业发达, 先民善于驭风驾舟。"四夷咸来归附", 不仅如此, 湖州地区的先民亦开始向中原地区发展。他们经过安徽、河南一直到达古代富饶的黄土高原, 带去了先进的文明和农作物, 并在那里定居下来。中原地区的华夏族由是形成 [8]。</p>

<p>在部落联盟时代, 作为整个中华文明的基础和根源, 湖州部族遂成为类似于后来周代之东周国一样的宗主国。是为夏之前的第一个朝代, 后来历史的发展也无不契合。</p>

<p>至 4000 年前, 气候变暖冰雪融化, 引发了一场世界范围的大洪水。湖州平原成为一片泽国, 更多的先民开始向北迁徙。据传说, 北方部落由禹带领治水, 而南方则是在防风王 (汪芒氏) 的带领下治水。在这一历史时期, 北方部族逐渐由夏禹统一。于是打破共和制, 构建一个统一王朝的想法开始在禹的思想中形成。根据吕思勉先生的地缘军事学说, 较之浙北平原, 中原地区更易于大规模军事集结, 故中原必更具有侵略性, 北方军事联盟对于南方农业地区的征服终不可避免。而现在禹的面前, 是建立夏王朝最后的障碍, 湖州地区曾经的宗主国, 南方防风国地区强大的部落联盟, 仍然占据着中国的半壁江山。</p>

<p>公元前 2198 年, 夏朝建立的前夜。在禹的努力下曾经席卷天下的洪水开始退却了。禹用的是疏通的方法, 将洪水导向大海。防风国承接的正是最后一段将大水导入东海的工程。防风氏不仅使用疏的方式, 也使用堵的办法, 搬运土石堵住洪水使其改道, 将其引入大海。其间治理了湘溪、英溪、阜溪以及塘泾河, 并且建立河道将下渚湖和东苕溪连通起来。防风王的事迹被传颂到了中原, 华夏族里大家纷纷传说, 在遥远的东方有一个防风王治理洪水非常厉害, 他不仅身材高大是个巨人, 而且力大无比, 能够开山造丘引水入海。现在洪水既退, 作为中原部落联盟的首领, 禹在绍兴茅山召开了一次盛大的庆功大会, 治水立下大功的防风王自然也在邀请之列。</p>

<p>然而庆功大会上离茅山最近的防风王却姗姗来迟, 禹盛怒之下将其杀害 [9]。然而, 防风氏的头颅被砍下后, 却没见出血, 大家正在惊异中, 突然一股白血从防风颈腔冲天而出。禹和各路诸侯都觉得不对劲, 经过调查这才知道当时天目山山洪爆发, 苕溪泛洪, 防风王因为救助被水冲走的百姓和大家一起排洪这才晚到。禹懊悔不已, 在防风国建立防风祠并亲自拜祭。</p>

<p>然而无论如何, 作为诸侯霸主的禹和后来的齐桓公一样大会诸侯, 并在诸侯会议上除掉了南方部落联盟的首领。中原集团遂踏入沃野千里的浙北平原, 中国第一个南北朝时期以北方征服南方而告终。一如秦灭东周国, 位处湖州的宗主国既破, 中国第二个朝代夏便随之建立了。</p>

<p>而防风王汪罔氏的部族为了逃避中原华夏族的军事征服, 开始向浙西和安徽逃亡, 有些则驾船向着日本的方向出海了。随着南方部落联盟核心地区的陷落, 中国南方曾经无比繁荣的良渚文明诸部逐渐解体, 慢慢退出了历史舞台。一个时代结束了。然而防风氏毕竟有功于中华, 无论历史如何书写, 都成为我们无法抹去的历史记忆。对防风王的祭祀载入了夏朝祀典。浙北越人至今祭防风而不祭禹, 称 "祭禹要肚疼"。史载 [10] "越俗, 祭防风神, 奏防风古乐, 截竹三尺, 吹之如皋, 三人披发而舞" 庄严悲凉, 表达了对蒙冤先祖的哀思。</p>

<p>在湖州德清广袤的下渚湖湿地, 凭栏四望, 湖上秋水长天, 一枝枝羽状的芦花花穗, 染着落日余辉, 仿佛金与银在变相辉映, 又像是淡淡血痕, 洇润在素白色的锦缎上。当年的治水英雄告别这里的父老乡亲去会稽赴会时, 面对这故土圣泽, 满湖雪白的芦花和遍地翻滚的金色稻浪, 脸上大概绽开出芦花般灿烂的笑容。</p>

<p>然而哪里想到, 他这是 "壮士一去兮不复还" 的最后微笑 [11]。</p>
</div>

<br><br>

<div style="font-size: 14px; color: rgb(51, 51, 51);">[1]《浙江文物》双月刊, 2006 年第五期《穿西服、打赤足、拎竹篮的 “石头博士” —— 纪念钱山漾遗址发现者慎微之先生》 , 闵泉著 (http://www.zjww.gov.cn/magazine/2006-11-14/4327386.shtml)。这里对该文原文有多次引用。<br>
[2] 于钱山漾后两年后的 1936 年, 同一历史时期的良渚遗迹遂被发现。遂以为命名, 称良渚文化。然良渚文化核心地区实在湖州是为考古界定论, 本文对于湖州 "防风国" 所考亦为佐证。<br>
[3]《中华读书报》, 2005 年 4 月 20 日, 林元锋《文明的证据》(http://www.gmw.cn/01ds/2005-04/20/content_220262.htm)。这里对于文中某些学术认识有所引用。<br>
[4] 溪龙遗存, 2002年10月至11月, 安吉、长兴两地发现旧石器时代文化遗物地点 30 多处, 石制品300多件。<br>
[5] 邱城遗址 (太湖马家浜文化, 距今 6000 年), 安乐遗址 (崧泽文化, 距今 5500 年)。<br>
[6]《路史 - 国名纪》注引《吴兴记》: "吴兴西有风山, 古防风国也。下有风渚, 今在武康东十八里。天宝改曰防风山, 禺山在其东二百步"。<br>
[7] 中华人民共和国国家文物局, 2005 年 6 月 24 日《湖州发现4000年前豪宅, 钱山漾遗址考古发掘结束》(http://www.sach.gov.cn/tabid/300/InfoID/3956/frtid/106/Default.aspx), 报告中称: "除了这些文物之外，考古人员发现一栋大型建筑遗址，这个遗址是一个八室的套间，占地面积达290平方米。…… 这个大房子的发现，充分反映了距今4000年前太湖地区先民们已掌握了高超的建筑空间分隔与组合技术，为中国史前建筑提供了珍贵的资料"。<br>
[8]《〈山海经〉考古》称中国夏朝的主体是先越之民。以稻作、语系、玉葬佐证。这在考古界已经得到证实, 故中原部族乃是由良渚文明即湖州地区向西向北迁徙所得。<br>
[9]《国语 - 鲁语》仲尼曰: "丘问之: 昔禹致群神于会稽之山, 防风氏后至, 禹杀而戮之, 其骨节专车。此为大矣"。<br>
[10] 梁《述异记》。<br>
[11] 网上关于 "防风国"、"防风王" 以及汪姓始祖的著述 (http://ks.cn.yahoo.com/question/1306121627641.html), 原作者暂无考。文末文采飞扬、语颇隽永, 为之倾倒。故原文引用, 稍有改动, 聊表敬意。</div>

<br><br>
<p><img title="[沈著湖州文史志] 第一章 治水英雄防风王 - 沈崴 - 蜻蜓点水 举重若轻" alt="[沈著湖州文史志] 第一章 治水英雄防风王 - 沈崴 - 蜻蜓点水 举重若轻" src="http://www.uzai.com/sightImg/zhejiang/xiazhuhu_map.gif"></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820085484747953</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820085484747953</guid>
    <pubDate>Wed, 4 Jun 2008 20:47:47 +0800</pubDate>
    <dcterms:modified>2009-09-18T15:06:06+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[沈崴路由器建站教程]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820083995420860</link>
    <description><![CDATA[<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img title="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://usa.asus.com/100/images/products/460/460_m.gif"  >    <h2>前言</h2>    <p>尽管在国外有一些闲置的服务器, 但是却不敢拿来建网站。网站这种应用出境率太高, 即使像 fr_eebsd.org 这种良民, 被 GF\/\/ 也是很容易的事情。到时候不仅 $ 打水漂, 可恨连 VPN 都用不了, 上网只能戴套, 实在是划不来。</p>    <p>于是乎我决定利用 ADSL/HTTB 带宽建站。至于服务器, 实在不想和豆瓣的阿北一样用笔记本来做, 一方面耗电, 另一方面笔记本常有爆炸事件, 不敢在无人职守的情况下超长待机。故决定使用 NAS (网络存储服务器, 网盘) 来做。</p>    <p>这里性价比最高的是 Buffalo 的 Linkstation 网盘, 首选的是 LinkStation HD-H120LAN120G 这个型号, 居然拥有高达 400M 的 MIPS CPU 以及  64M 的巨量内存 (耗电 20W 左右)。当然非常不幸的是, LS 120G 全上海断货, 而且奸商奇货可居哄抬物价, 这令 Cr@cker 非常不爽。</p>    <p>最终这直接导致了我选用路由器这种 "难民级" 设备来建站, 鸟枪变炮。于是就有了这篇文章。</p>    <br><br>    <h2>硬件篇</h2>    <p>当然也会有少数人不理解, 路由器怎么可以拿来做网站呢? 是啊, 你一两百块钱买过来的这个小盒子尽管便宜, 却也是一台完整的高性能计算机了, 除了没有显示器和鼠标键盘。当然啦, 只要你愿意, 加个诸如摄像头或者声卡什么的外设还是可以的。</p>    <br>  <center><a rel="nofollow" href="http://neture.homeip.net/digiland/index.php"  ><img title="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://benlau.e-fever.org/modules/xcgal/albums/userpics/10001/normal_200503011129.jpg"  ></a></center>  <br>    <p>大部分的路由器的固件都是可以重新刷过的, 诸如 LinkSys、D-Link、Buffalo、Netgear、ASUS 这些品牌的路由器都在著名固件 "OpenWrt" 支持之列。这里有一份详细的 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://wiki.OpenWrt.org/TableOfHardware"  >支持列表</a>, 请先查阅。</p>    <p>经过研究, 我觉得 ASUS 系列的路由器较为实惠。首选 ASUS WL-HDD 这款 "网络硬盘盒", 他的特点是比起一般的路由器多一个 2.5 IDE 硬盘接口以及一个  USB 1.0 接口, 可以加装一块硬盘和 USB 盘用于存放网站数据。</p>    <p>其次是 ASUS WL-500b (可以升级到 WL-500g) 和 ASUS WL-500g 路由器, 他们使用和 WL-HDD 一样的硬件, 也带有一个 USB 1.0 接口。使之同样成为建站和网络打印服务器的首选。</p>    <p>WL-HDD/500b/500g 售价都在一两百元上下, WL-HDD 稍贵, 我在上海以 248￥ 拿到的货。他们的硬件配置都是 MIPS BCM4702 125MHz CPU、16MB SDR 32bit 内存和 4M 闪存 (耗电 10W)。</p>    <p>另一个版本 WL-500gP 稍贵, 拥有 200MHz CPU, 著名改*机网站 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://neture.homeip.net/digiland/index.php"  >"数&amp;位天堂"</a> 就是构建于 ASUS-WL-500gP 之上。网站上有 WL 全系列硬件配置表, 若要选购以作改机之用, 可以参考。</p>    <br>  <center><a rel="nofollow" href="http://neture.homeip.net/digiland/"  ><img title="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://neture.homeip.net/digiland/img/upload/table2008022001.gif"  ></a><br>(图片来源 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://neture.homeip.net/digiland/index.php"  >"数位+天堂"</a>)</center>  <br>    <p>下面专为 ASUS 的 OLEG 固件开辟一节, 未在其他硬件上测试过, 其他路由器用户可快速掠过, 去到 OpenWrt 固件部分。</p>    <br><br>    <h2>ASUS 专用固件 OLEG</h2>    <p>固件 (Firmware, 韌體) 被保存在路由器闪存中, 通常是一个完整的  Linux 操作系统。将路由器原固件改成自定义固件, 可以实现在原有路由器功能上增删定制任意自己想要的功能, 就像是操作一台完整的电脑一样。</p>    <p>刷新固件, 常用于使路由器自动下载  BT、绕过 ISP (诸如网xx通、电yy信) 的多a用b户c共d享e限f制, 绕过 ISP 的 DNS 域a名b劫c持d等流_氓行为。这里就不详加讨论了, 请诸位自己找资料。</p>    <p>OLEG 是 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://neture.homeip.net/digiland/index.php"  >"数位天*堂"</a> 选用的固件, 是通过 ASUS 官方固件修改而来。门槛较低, 兼容性高, 这里推荐初级 ASUS 用户使用。下面是刷机步骤。</p>    <p style="padding: 10px 25px 10px 30px; background-color: rgb(204, 204, 204); color: rgb(0, 0, 136); font-size: 10pt;"  >  1. 造访 http://oleg.wl500g.info/ , 下载最新的固件 (WL-HDD 用户请下载 1.9.2.7-9 及以前的版本, 其后版本不支持 WL-HDD)。<br>  2. 解压缩 WLxxx-1.9.2.x-x.zip 得到 trx 文件。<br>  3. 访问自己的路由器地址 http://192.168.1.1 (WL-HDD 是 http://192.168.1.220, 推荐使用直接的网线连接而不是无线方式), 登录后找到 "System Setup" 的 "Firmware Upgrade" 项, 上传 trx 文件。<br>  4. 稍候片刻, 等待机器自动重启。<br>  </p>    <br>  <center><img title="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴路由器建站教程 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://neture.homeip.net/digiland/img/upload/wl-500gp_firmware_20080124.gif"  ><br>  (图片来源 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://neture.homeip.net/digiland/index.php"  >"数位+天堂"</a>)<br></center>  <br>    <p>重启后会再次进入管理界面, 设置用户名。这样你就可以通过 telnet 来登入路由器了 (密码: admin)。哇噻, 我的到了一个 Linux Shell!</p>    <p>接下来接入 USB 盘或者插上 IDE 盘, 如果不喜欢命令行的 fdisk 工具, 可以先使用其他工具分区格式化再接入 ASUS WL 设备。然后执行 "fdisk -l", 下面是在我机器 (WL-HDD) 上的显示。</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >Disk /dev/ide/host0/bus0/target0/lun0/disc: 120.0 GB, 120034123776 bytes<br>255 heads, 63 sectors/track, 14593 cylinders<br>Units = cylinders of 16065 * 512 = 8225280 bytes<br><br>                                Device Boot    Start       End    Blocks   Id  System<br>/dev/ide/host0/bus0/target0/lun0/part1               1       14395   115627806   83  Linux<br>/dev/ide/host0/bus0/target0/lun0/part2           14396       14461      530145   82  Linux swap<br>/dev/ide/host0/bus0/target0/lun0/part3           14462       14527      530145   82  Linux swap<br>/dev/ide/host0/bus0/target0/lun0/part4           14528       14593      530145   82  Linux swap<br></pre>  <br>    <p>接下来就是挂接硬盘 (当然, 如果对原装的 4M flash 有信心, 也可以不加硬盘撒):</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  ># mount /dev/ide/host0/bus0/target0/lun0/part1 /opt<br># swapon /dev/ide/host0/bus0/target0/lun0/part2<br># swapon /dev/ide/host0/bus0/target0/lun0/part3<br># swapon /dev/ide/host0/bus0/target0/lun0/part4<br></pre>  <br>    <p>安装 ipkg (硬盘/U 盘已经加载置 /opt 目录):</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  ># mkdir /opt/tmp<br># mkdir /opt/tmp/ipkg<br># wget http://ipkg.nslu2-linux.org/feeds/optware/oleg/cross/stable/ipkg-opt_0.99.163-9_mipsel.ipk<br>ipkg.sh install ipkg-opt_0.99.163-9_mipsel.ipk<br># wget http://ipkg.nslu2-linux.org/feeds/optware/oleg/cross/stable/uclibc-opt_0.9.28-13_mipsel.ipk<br># ipkg.sh install uclibc-opt_0.9.28-13_mipsel.ipk<br># ipkg update<br></pre>  <br>    <p>这样我们就可以像使用 debian apt-get 一样直接通过 "ipkg install xxx" 来安装已经编译好的二进制程序了。</p>    <p>在 http://ipkg.nslu2-linux.org/feeds/optware/oleg/cross/stable/ 位置拥有大量的 ipk 文件, 这些都是 ipkg 包, 实际上, 我们大可不必使用 ipkg 程序来安装这些软件。</p>    <p>ipk 文件实际上是 tgz 格式的, 解包后会得到 data.tar.gz 和 control.tar.gz 两个 tgz 文件 (tgz 套着 tgz? 貌似很奇怪的样子), 而 data.tar.gz 就是二进制程序结构。使用解包的 data.tar.gz 文件, 可以提供一种更为灵活的系统维护形式 (初级用户不推荐)。</p>    <p>好了, 简单的配置就这样了, 请玩家继续深入阅读 OLEG 的相关参考资料。</p>  <p style="padding: 10px 25px 10px 30px; background-color: rgb(204, 204, 204); color: rgb(0, 0, 136); font-size: 10pt;"  >  <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://neture.homeip.net/digiland/viewtopic.php?id=158"  >数.位天堂::ASUS 500 改机讨论区 WL-500g::系列改機基本步驟</a><br>  <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://www.sprayfly.com/wiki/Sprayfly"  >Sprayfly::WL-HDD/500 Setup Guide</a>  </p><p>    <br><br>    </p><h2>OpenWrt 固件</h2>    <p>OpenWrt 固件通常是骇_机族的首选, 基本上你可以自由定制包括 Kernel 在内的所有东西, 这往往给人一种很爽的幻觉。除此之外, OpenWrt 还有一个叫做 DD-WRT 的表兄 (访问其<a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://www.dd-wrt.com"  >主站</a>需_破.墙_) 以及 DebianWRT 的堂兄, 也可以在 OpenWrt 上跑 Gentoo。</p>    <p>其中 DD-WRT 在管理上相当便捷, 玩家也是颇多的, 这里也推荐大家不妨尝试一下。而在路由器上跑 Debian, 就比较诡异了, 而跑 Gentoo 就更是说不出的诡异了。这里我的首选还是 OpenWrt, 因为我需要一个足够小, 占用资源足够少的固件, OpenWrt 定制起来非常方便, 自己编译吧。</p>    <p>当然 OpenWrt 已经有编译版了, 只是想用 OpenWrt 而对定制没有要求的同学可以偷懒了。</p>    <p>这里做得比较漂亮的是 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://porta2030.tossug.org/wiki/Software%3Bzh-tw"  >Hive</a> 版, 安装配置相当方便, 可以通过其站点 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://downloads.hivenet.org/firmware/OpenWrt-brcm-2.4-jffs2-4MB.trx"  >获取</a> 资料。而 OpenWrt 官方也提供编译版 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://downloads.OpenWrt.org/whiterussian/rc6/bin/"  >下载</a>。</p>      <p>下面, 就让我们来建立一个 OpenWrt 固件。首先, 显然你已经有一台运行 Linux 的计算机 (什么, 你是 Windows 用户? 那你来看我的博客做什么?), 然后上到 OpenWrt 官网, <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://www.OpenWrt.org"  >下载</a> 源码 (当然也可以使用 SVN)。</p>    <p>OpenWrt 有两个分支, 较新的是 "Kamikaze(神风? 晕)" 版, 另一个是 "whiterussian(白俄罗斯)" 版 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://downloads.OpenWrt.org/whiterussian/rc6/whiterussian_rc6.tar.bz2"  >下载</a>。这里选用较为稳定的 whiterussian RC6 版本。下面我们开始配置编译。</p>    <br><br>    <h2>编译 OpenWrt</h2>    <p>下面以我的 ASUS WL-HDD 设备为例, 来讲解 OpenWrt 的编译和配置。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ wget http://downloads.OpenWrt.org/whiterussian/rc6/whiterussian_rc6.tar.bz2<br>$ tar -xjf whiterussian_rc6.tar.bz2<br>$ cd whiterussian_rc6.tar.bz2<br>$ make menuconfig<br></pre>  <br>    <p>接下来会出现配置选单, 大部分的选项使用默认即可。可以酌情修改配置, 一般来说只要不是改得太过分, 生成的固件都是可用的。因为我是 ASUS WL-HDD 的盒子, 所以我主要是在系统中取消了 httpd 服务 (后面会提到我将使用 Eurasia3 应用服务器提供 web 服务), 并且将 IDE 硬盘的支持设置为 "内建 ([*] builtin)" 模式。</p><p>  </p><pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(255, 255, 0); background-color: rgb(0, 0, 255);"  >1. OpenWrt Package Selection ---&gt;<br> Busybox Configuration ---&gt;<br>  Networking Utilities ---&gt;<br>   [ ] httpd<br><br>2. Kernel Configuration / Device Support ---&gt;<br> [*] IDE Support, EXT3 filesystem support<br></pre>  <br>    <p>USB 支持可以在系统安装好后使用模块加载 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://wiki.OpenWrt.org/UsbStorageHowto"  >资料</a>。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(255, 255, 0); background-color: rgb(0, 0, 255);"  >3. Target Root Filesystem ---&gt;<br> [*] jffs2<br></pre>  <br>    <p>这里决定了生成映像文件使用的文件格式, 其中 squashfs 是只读的, jffs2 是可写的, 我们通常选择 jffs2 格式, 以后可以直接读取编辑路由器的  flash 存储器。</p>    <p>配置完成后执行编译。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ make V=99<br></pre>  <br>    <p>当编译完成后, 你可以在 whiterussian_rc6/bin 目录下找到生成的 trx 映像。</p><p>    </p><p>比如 OpenWrt-brcm-2.4-jffs2-4M.trx 这个映像, "brcm" 是通用的路由器硬件, jffs2 是文件系统, 4M 是指适用 flash 存储器大小, ASUS WL-HDD/500 的 flash 都是 4M, 适用于这个映像。</p>    <p>Kamikaze 和 Whiterussian 不同, 它生成诸如这样的映像 OpenWrt-brcm47xx-2.6-squashfs-64K.trx, 在硬件型号上可以自由配置。特别诡异的是在 Kamikaze 下 64K 指 4M flash, 而 128K 是指 8M flash 以此类推。</p>    <p>终于, 我们拿到了 trx 映像文件。其中只有 menuconfig 这一步有点工作量。貌似把系统日志部分 (syslogd) 砍掉, 可能会导致路由器重启失败, 需要保留, 其他服务应该都是可以取消的。</p>    <p>至于程序库, 可以等以后手工编译添加进系统。诸如 libpthread、libreadline 这些库是以后运行 Stackless Python 需要的, 对于非常常用的可以编译到镜像里去。</p>    <p>至于OpenWrt SDK 和 Image Builder, 我们在下面的开发中其实并不会用到, 不必选择编译。</p>    <p>在编译过程中, 会去网上拿许多依赖的 package 源码文件。比起 Kamikaze 来, Whiterussian 要下载海量的资源, 如果你网速不够快, 那么可以直接去 OpenWrt 官网上拿 (不推荐, 除非网速真的很慢)。你需要修改 whiterussian_rc6/scripts/download.pl 这个脚本, 清空 "foreach my $mirror (@ARGV) { ... }" 代码块即可。</p>    <p>编译完成以后, 请保留 whiterussian_rc6 目录, 这是我们接下来做交叉编译 (Cross Compiling) 的平台。</p>    <br><br>    <h2>使用 OpenWrt</h2>    <p>将 OpenWrt trx 映像写入路由器, 你需要 whiterussian_rc6/scripts/flash.sh 这个工具。你也可以从 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://downloads.hivenet.org/bin/flash.sh"  >这里</a>下载这个脚本。</p>    <p>现在将路由器调至回复模式, 计算机和路由器直接使用网线连接, 确信能够 ping 到。作好准备工作。</p>    <p>以我的 ASUS WL-HDD 为例, 连好网线以后, 按住 reset 按钮, 同时插上电源, 黄灯开始规律闪烁即进入 flash 回复模式。接下来确认 WL-HDD 在 192.168.1.1 这个位置 (当然如果你已经设置过 nvram, ip 以 nvram 为准), 如果 ip 不是 192.168.1.1, 你需要先修改 flash.sh 文件中关于 ip 的设定。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ apt-get install tftp<br>$ chmod +x flash.sh<br>$ ./flash.sh OpenWrt-brcm-2.4-jffs2-4M.trx asus<br></pre>  <br>    <p>完成 Firmware 上传之后, 程序会回到 shell 下, 等待黄灯熄灭 (即开始更新 Firmware), 再等到 WLAN 绿灯亮起, 此时 Firmware 已经写入机器, 并且机器已经完成重启。恭喜恭喜!</p>    <p>解下来我们可以使用 telnet 192.168.1.1 登录进路由器。进入 Linux Shell 以后, 你可以使用 nvram show/set 命令来显示和设置 nvram, 修改机器 IP 等数据, 重启机器使修改生效。例如:</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >nvram set lan_ipaddr=192.168.0.2<br>nvram commit<br></pre>  <br>    <p>Whiterussian 启动时加载 IDE 硬盘存在 BUG, 你需要修改 /etc/modules.d/20-ide 文件, 调整内核模块的加载顺序如下:</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >ide-core<br>pdc202xx_old<br>ide-detect<br>ide-disk<br></pre>  <br>    <p>重启以后, ide 硬盘就可以被识别出来了。如果编译进了 fdisk, 那么可以用 fdisk -l 来查看硬盘。</p>    <p>和 OLEG 不同, OpenWrt 不用经过配置就可以使用 /etc/init.d 初始化脚本目录, 在里面添加启动脚本挂载硬盘, 并删掉不喜欢的服务。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >#!/bin/sh<br># chmod +x /etc/init.d/S90Example<br>mount /dev/ide/host0/bus0/target0/lun0/part1 /mnt<br>swapon /dev/ide/host0/bus0/target0/lun0/part2<br>swapon /dev/ide/host0/bus0/target0/lun0/part3<br>swapon /dev/ide/host0/bus0/target0/lun0/part4<br>killall logger<br>killall syslogd<br>killall crond<br>killall klogd<br></pre>  <br>    <p>下面使用 free 命令, 看看剩下多少内存留给我们接下来的应用 (果然是寸土寸金啊)。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >              total         used         free       shared      buffers<br>  Mem:        14296         7580         6716            0           56<br> Swap:      1572828            0      1572828<br>Total:      1587124         7580      1579544<br></pre>  <br>    <p>这样, 这个  Linux 系统已经可用了。</p>    <br><br>    <h2>OpenWrt 下的本地编译环境</h2>    <p>在 OpenWrt 下也可以进行本地编译, 你可以 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://www.uclibc.org/downloads/root_fs_mipsel.ext2.bz2"  >下载 root_fs_mipsel.ext2.bz2</a> , 并查阅 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://wiki.openwrt.org/BuildingPackagesHowTo"  >相关资料</a>。</p><p>    </p><p>这里你不必真的在路由器上挂接 root_fs_mipsel.ext2 到文件系统上, 你可以在本地计算机上挂接并拷贝到路由器的 U 盘或者硬盘上。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ mkdir ~/tmp<br>$ mkdir ~/tmp/root<br>$ mount -o loop root_fs_mipsel.ext2 ~/tmp/root<br>$ cd ~/tmp<br>$ tar -cjf root_fs_mipsel.tar.bz2 root<br></pre>  <br>    <p>然后把 root_fs_mipsel.tar.bz2 拷贝到路由器硬盘上解压缩。</p>  <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  ># cd /mnt<br># wget http://192.168.x.x/root_fs_mipsel.tar.bz2 # 如果本机有 HTTP 服务, 那么可以通过 wget 从本机上取得文件<br># tar -xjf root_fs_mipsel.tar.bz2<br></pre>  <br>    <p>这样我们就得到了 /mnt/root 目录, 里面包含了完整的编译环境和需要的库文件。接下来以 /mnt/root 为根 ('/') 目录, 即可使用本地编译环境。</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  ># chroot /mnt/root/ /bin/ash -<br># gcc -v<br># exit<br></pre>  <br>    <p>不过你应该永远避免在路由器上进行本地编译, 首先是速度极慢, 然后诸多依赖也不能满足 (比如 Include 等), 但是这里架设的编译环境也并不是没有用处, 因为在 root_fs_mipsel 的 lib 目录下有许多我们需要的重要的库文件可以直接拿来使用, 省去许多费事的编译。</p><p>    <br><br>    </p><h2>为 OpenWrt 编译 Stackless Python</h2>    <p>很显然, <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://code.google.com/p/eurasia/"  >Eurasia3</a> 才是王道。不过这个 Web 应用服务器依赖于 Stackless Python。找了半天, 也只有 Python 的 ipk 包。好吧, 自己编译吧。</p>    <p>除了高度定制, 自己编译 OpenWrt 映像的另一个好处就是交叉编译环境已经准备好了。现在让我们回到 whiterussian_rc6 目录, 来设定交叉编译环境, 很简单, 你只要在你的 PC 中输入下面几条命令。</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ export PATH=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/usr/bin:/PATH/TO/whiterussian_rc6/staging_dir_mipsel/mipsel-linux-uclibc:/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin:$PATH<br>$ export AR=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-ar<br>$ export AS=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-as<br>$ export LD=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-ld<br>$ export NM=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-nm<br>$ export CC=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-gcc<br>$ export CPP=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-cpp<br>$ export GCC=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-gcc<br>$ export CXX=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-g++<br>$ export RANLIB=/PATH/TO/whiterussian_rc6/staging_dir_mipsel/bin/mipsel-linux-uclibc-ranlib<br>$ export ac_cv_linux_vers=2.4.30<br>$ export CFLAGS="-Os -s"<br></pre>  <br>    <p>现在你的编译环境已经是面向 OpenWrt MIPS 系统的了, 与本地编译唯一的不同, 就是你需要对源代码包的 configure 脚本增加 --host=mipsel-linux 参数。</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ ./configure --host=mipsel-linux<br>$ make<br>$ make install<br></pre>  <br>    <p>大部分 x86 体系的软件包都可以在交叉编译平台上通过编译。不过 Stackless Python 貌似并不支持 MIPS 体系的计算机, 为此我编写了一个补丁, 你可以访问 <a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://www.stackless.com/pipermail/stackless/2008-April/003428.html"  >这个地址</a>, 将邮件中 "# stackless-2.52.mips.xcompile.patch" 以下部分复制出来保存为 stackless-2.52.mips.xcompile.patch 文件。下面我们就可以编译 Stackless Python 了。</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  >$ wget http://www.stackless.com/binaries/stackless-252-export.tar.bz2<br>$ tar -xjf stackless-252-export.tar.bz2<br>$ cat stackless-2.52.mips.xcompile.patch | patch -p0<br>$ cd python-2.52<br>$ export CROSS_COMPILE=yes<br>$ ./configure --prefix=/opt/Stackless-2.5.2 --host=mipsel-linux<br>$ make<br>$ make install<br></pre>  <br>    <p>现在我们在本机的 /opt 下得到了 Stackless-2.5.2 目录, 打包放到路由器的 /opt 目录下, 我们就可以正常使用 Stackless Python 了。</p>    <p>关于在其他版本的 Stackless Python 里如何 H@ck 代码以支持 MIPS 架构, 请仔细阅读 patch 文件。据 Richard Tew 说他对在 Stackless 中加入 MIPS 支持颇感兴趣, 除非他能跑得过 Python 的开发速度 (这好像有点冷~~`)。很显然 Guido 把 Stackless 拒之门外是一个严重错误, 喂喂, 别再鼓捣 Python 3000 什么拉!</p>    <p>现在登入 WL-HDD, 下载 Eurasia3, 编写一个 Eurasia3 (这里使用 svn 版, 我正准备发布的 alpha4 的原型, alpha2 可以在<a style="text-decoration: underline; color: rgb(51, 51, 136);" rel="nofollow" href="http://eurasia.googlecode.com/files/Eurasia-3.0.0a2.tar.gz"  >这里</a>下载) 的测试程序:</p>    <pre style="padding: 10px 25px 10px 30px; font-size: 10pt; color: rgb(0, 255, 0); background-color: rgb(17, 17, 17);"  ># !/opt/Stackless-2.5.2/bin/python2.5<br>from Eurasia.web import config, mainloop<br><br>def controller(client):<br> client.write(<br>  'HTTP/1.0 200 OK\r\n'<br>  'Content-Type: text\r\n'<br>  '\r\n'<br>  'hello world!' )<br><br>config(controller=controller,<br> port=80)<br>mainloop()<br></pre>  <br>    <p>做了一下小测试, hello world 每秒可以达到 40 个以上的请求数, 尽管比起一台普通的 PC 同样的 Eurasia3 程序慢了几百倍, 但是对于一台嵌入式设备而言, 已是颇令人满意了。</p>    <p style="color: rgb(136, 136, 136);"  >  <b>PS:</b>据阿北说他的笔记本是做开发用途, 而不是做了网站, 这里勘下误。<br>  </p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820083995420860</comments>
    <slash:comments>26</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820083995420860</guid>
    <pubDate>Wed, 9 Apr 2008 21:54:20 +0800</pubDate>
    <dcterms:modified>2011-09-23T20:36:52+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[沈崴手把手教你如何设置 EeePC 分辨率]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820081191431975</link>
    <description><![CDATA[<div><div style="text-align: center;"  >  <a target="_blank" href="http://img.blog.163.com/photo/fgaxBPU-Avuhz6XaDTlIxQ==/4239576099216411254.jpg"  ><img title="沈崴手把手教你如何设置 EeePC 分辨率 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴手把手教你如何设置 EeePC 分辨率 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://img.blog.163.com/photo/fgaxBPU-Avuhz6XaDTlIxQ==/4239576099216411254.jpg"  ></a><a target="_blank" href="http://img.blog.163.com/photo/bE9EKpbd--5neceofdYQTQ==/3459890413727963256.jpg"  ><img title="沈崴手把手教你如何设置 EeePC 分辨率 - 沈崴 - 蜻蜓点水 举重若轻"  alt="沈崴手把手教你如何设置 EeePC 分辨率 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://img.blog.163.com/photo/bE9EKpbd--5neceofdYQTQ==/3459890413727963256.jpg"  ></a><br><div style="text-align: left;"  ><br><font size="3"  ><span style="font-weight: bold;"  >设置分辨率</span></font><br><br>$ sudo apt-get install openbox # 这个窗口管理器比较轻盈, 诸位请酌情<br>$ sudo apt-get install vnc4server krdc # 安装 vnc 的服务器和客户端软件<br>$ sudo /etc/init.d/gdm stop # 终止当前的 X 服务<br><br>$ X &amp; # 启动 X, 然后按 Ctrl + Alt + Fn 回到命令行<br>$ export DISPLAY=:0 # 开始操作屏幕 0<br>$ openbox # 使用 openbox 窗口管理器<br><br>$ <a rel="nofollow"><span style="font-family: monospace;"  >vnc4server </span>:1 -depth 16 -geometry 1920x1152 -localhost -dpi 100 # 启用虚拟屏幕 :1<br>$ export DISPLAY=:1 # 开始操作屏幕 1<br>$ gnome-wm # 使用 gnome 窗口管理器<br>$ nautilus &amp; # nautilus 桌面<br>$ gnome-panel &amp; # gnome 菜单<br><br>$ vncpasswd # 设置 vnc 密码<br>$ export DISPLAY=:0<br>$ </a><a rel="nofollow">krdc -fsh localhost:1 # 连接到虚拟屏幕 :1, 然后按 Alt + F7 回到 X 屏幕<br><br>基本上原理就是这样, 大家如果有空的话可以写到 sh 脚本里面去。<br><br><span style="font-weight: bold;"  >好看簿</span>: http://www.haokanbu.com/story/7044/<br><span style="font-weight: bold;"  >参考资料</span>: http://forum.eeeuser.com/viewtopic.php?id=14588<br></a></div></div></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820081191431975</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820081191431975</guid>
    <pubDate>Tue, 19 Feb 2008 13:43:19 +0800</pubDate>
    <dcterms:modified>2011-09-23T20:39:49+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[在网页中实现文件上传进度条]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007112322444302</link>
    <description><![CDATA[<div>好的, 这是一篇让您 "虎须一震" 的文章。相信您已经为显示文件上传进度而头痛很久了。不过先别高兴得太早, 您手上的 Web 框架通常不支持进度条技术。哈哈哈哈。<br><br><span style="font-weight: bold;">得到上传文件的大小</span><br>很好。要显示进度条的关键是得到上传文件的大小。这个问题曾经也让在下晕乎了一下下, 因为我搜了一下 Google, 大家都说要 ActiveX 或者类似 Applet、Flash 这样的插件, 因为据说浏览器没有读取本地文件大小的权限。好了, 别理他们, 我这就告诉你无插件获取上传文件大小的方法。你看文件上传的报文:<br><br><div style="color: rgb(136, 136, 136);">POST / HTTP/1.1<br>Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, application/vnd.ms-powerpoint, */*<br>…<br>Content-Type: multipart/form-data; boundary=---------------------------7d439d362703b2<br>…<br>Cache-Control: no-cache<br><br>-----------------------------7d439d362703b2<br>Content-Disposition: form-data; name="test_file"; filename="xxx"<br>Content-Type: text/plain<br><br>1234abcd!@#$()-=:”<br>-----------------------------7d439d362703b2--</div><br>从 ”-----------------------------7d439d362703b2“ 开始就是 HTTP Body 了, 这部分的长度我们是可以得到的, 不错, 就是 'Content-Length'。很不幸文件的长度就是 Content-Length 减去两个分割线 '-----------------------------7d439d362703b2' 再减去子报文的头部 'Content-Disposition: form-data; name="test_file"; filename="xxx"\nContent-Type: text/plain' 剩下的长度。<br><br>很容易做到不是吗?<br><br><span style="font-weight: bold;">得到已上传数据大小, 并从另一条 HTTP 连接返回进度</span><br>实在没办法的话, 将上传数据写入临时文件, 并且立即 flush。这样你就可以通过 AJAX 定时去获取临时文件的大小, 计算出进度并返回。很好, 恶心得没话说。<br><br>略好的方法是使用应用服务器建立两个可以互相通信的线程, 建立两条长连接, 一条负责上传, 一条负责返回上传进度。上传线程可以累加已上传内容的大小, 供另一个反馈线程使用。当然协作线程会好很多, 否则你的应用可能只能支持不到 10 个用户同时上传文件。<br><br><span style="font-weight: bold;">恭喜您</span><br>显然您的 Web 框架不支持进度条显示, 马上升级你的技术吧。<br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007112322444302</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007112322444302</guid>
    <pubDate>Sun, 23 Dec 2007 14:24:44 +0800</pubDate>
    <dcterms:modified>2007-12-24T13:28:59+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Eurasia3, 我把恶魔带临人间了吗?]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007102133552397</link>
    <description><![CDATA[<div>前日打包了 Eurasia 3 的预览版, 在我的机器上得到了每秒 4790 个请求 (rps) 的速度 (未优化), 而经过这两天的改进, Eurasia3 已经达到 5500+ rps 的速度 (作弊模式下 wfile 直写可达 10000 rps)。<br><br>根据 <a target="_blank" rel="nofollow" href="http://blog.opensource.org.cn/hdcola/2007/10/django-1.html"  >HD 的文章 "Django 的几种运行方法性能对比"</a> , 同样的 "Hello world!" 程序在同等配置的机器上, Django<span style="font-weight: bold;"  > </span>每秒最多能处理 806 个请求。我同时测试了 Cherrypy3, 同样的程序也是 800 - 900 rps 的速度 (Cherrypy3 使用手工极限加速, 使用同等加速手段 Eurasia3 常规模式可达 7500+ rps)。<br><br>基本上, 对于最简单的 echo 应用, Eurasia3 在性能上已经是 Django 等老框架的 6 倍以上。这可能是 Django 等原始框架唯一的一个能和 Eurasia3 进行数值对比, 差距不算太大的地方。<br><br><span style="font-weight: bold;"  >Eurasia 项目页面</span><br style="font-weight: bold;"  ><a target="_blank" rel="nofollow" href="http://code.google.com/p/eurasia"  >http://code.google.com/p/eurasia</a><br><br><span style="font-weight: bold;"  >Eurasia 邮件列表</span><br><a target="_blank" rel="nofollow" href="http://groups.google.com/group/eurasia-users"  >http://groups.google.com/group/eurasia-users</a><br><br><span style="font-weight: bold;"  >Eurasia 3.0.0 预览报告</span><br><a target="_blank" rel="nofollow" href="http://groups.google.com/group/eurasia-users/browse_thread/thread/310b19fb3497ee67"  >http://groups.google.com/group/eurasia-users/browse_thread/thread/310b19fb3497ee67</a><br><br>Eurasia 3.0.0 Preview, 可以从:  <br> &nbsp; &nbsp;<a target="_blank" rel="nofollow" href="http://eurasia.googlecode.com/files/Eurasia-3.0.0-preview.tar.gz"  >http://eurasia.googlecode.com/files/Eurasia-3.0.0-preview.tar.gz</a> 下  <br> 载。  <br> <p>本次发布仍然使用 Python 标准库 asyncore.py 的算法, 优化阶段还未开始, 性能尚待提高。  <br> 这里提供部分简单功能的预览, 及简单的基准测试 (Apache ab)。欢迎讨论。  <br> </p><p>代码一, "hello world!"  <br> -------------------------------------------------------  <br> 代码:  <br> </p><p>#!/usr/bin/env python2.5  <br> #import psyco; psyco.full()  <br> </p><p>from web import Response, config, poll  <br> </p><p>def controller(req):  <br> &nbsp; &nbsp; &nbsp; &nbsp; resp = Response(req)  <br> &nbsp; &nbsp; &nbsp; &nbsp; resp['Content-Type'] = 'text/plain'  <br> &nbsp; &nbsp; &nbsp; &nbsp; print &gt;&gt; resp, 'hello world!'  <br> &nbsp; &nbsp; &nbsp; &nbsp; resp.close()  <br> </p><p>config(controller=controller, port=8080)  <br> while True:  <br> &nbsp; &nbsp; &nbsp; &nbsp; poll()  <br> </p><p>-------------------------------------------------------  <br> 基准测试 1:  <br> </p><p>$ ab -c 1021 -n 10000 '<a target="_blank" rel="nofollow" href="http://localhost:8080/%27"  >http://localhost:8080/'</a>  <br> </p>Server Software:  <br><p> Server Hostname: &nbsp; &nbsp; &nbsp; &nbsp;localhost  <br> Server Port: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8080  <br> </p><p>Document Path: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/  <br> Document Length: &nbsp; &nbsp; &nbsp; &nbsp;13 bytes  <br> </p><p>Concurrency Level: &nbsp; &nbsp; &nbsp;1021  <br> Time taken for tests: &nbsp; 2.84486 seconds  <br> Complete requests: &nbsp; &nbsp; &nbsp;10000  <br> Failed requests: &nbsp; &nbsp; &nbsp; &nbsp;0  <br> Write errors: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0  <br> Total transferred: &nbsp; &nbsp; &nbsp;1770885 bytes  <br> HTML transferred: &nbsp; &nbsp; &nbsp; 130065 bytes  <br> Requests per second: &nbsp; &nbsp;4797.35 [#/sec] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 212.826 [ms] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 0.208 [ms] (mean, across all concurrent  <br> requests)  <br> Transfer rate: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;829.46 [Kbytes/sec] received  <br> </p><p>Connection Times (ms)  <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min &nbsp;mean[+/-sd] median &nbsp; max  <br> Connect: &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp;1 &nbsp; 3.5 &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp;24  <br> Processing: &nbsp; &nbsp; 9 &nbsp; 26 &nbsp; 3.4 &nbsp; &nbsp; 26 &nbsp; &nbsp; 230  <br> Waiting: &nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; 25 &nbsp; 3.4 &nbsp; &nbsp; 25 &nbsp; &nbsp; 228  <br> Total: &nbsp; &nbsp; &nbsp; &nbsp; 25 &nbsp; 27 &nbsp; 4.7 &nbsp; &nbsp; 27 &nbsp; &nbsp; 231  <br> </p><p>Percentage of the requests served within a certain time (ms)  <br> &nbsp; 50% &nbsp; &nbsp; 27  <br> &nbsp; 66% &nbsp; &nbsp; 27  <br> &nbsp; 75% &nbsp; &nbsp; 27  <br> &nbsp; 80% &nbsp; &nbsp; 27  <br> &nbsp; 90% &nbsp; &nbsp; 28  <br> &nbsp; 95% &nbsp; &nbsp; 28  <br> &nbsp; 98% &nbsp; &nbsp; 45  <br> &nbsp; 99% &nbsp; &nbsp; 50  <br> &nbsp;100% &nbsp; &nbsp;231 (longest request)  <br> </p><p>-------------------------------------------------------  <br> 基准测试 2, 使用 psyco.full() 优化:  <br> </p><p>$ ab -c 1021 -n 10000 '<a target="_blank" rel="nofollow" href="http://localhost:8080/%27"  >http://localhost:8080/'</a>  <br> </p>Server Software:  <br><p> Server Hostname: &nbsp; &nbsp; &nbsp; &nbsp;localhost  <br> Server Port: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8080  <br> </p><p>Document Path: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/  <br> Document Length: &nbsp; &nbsp; &nbsp; &nbsp;13 bytes  <br> </p><p>Concurrency Level: &nbsp; &nbsp; &nbsp;1021  <br> Time taken for tests: &nbsp; 1.519026 seconds  <br> Complete requests: &nbsp; &nbsp; &nbsp;10000  <br> Failed requests: &nbsp; &nbsp; &nbsp; &nbsp;0  <br> Write errors: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0  <br> Total transferred: &nbsp; &nbsp; &nbsp;1770708 bytes  <br> HTML transferred: &nbsp; &nbsp; &nbsp; 130052 bytes  <br> Requests per second: &nbsp; &nbsp;6583.17 [#/sec] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 155.093 [ms] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 0.152 [ms] (mean, across all concurrent  <br> requests)  <br> Transfer rate: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1138.23 [Kbytes/sec] received  <br> </p><p>Connection Times (ms)  <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min &nbsp;mean[+/-sd] median &nbsp; max  <br> Connect: &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp;1 &nbsp; 4.0 &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp;25  <br> Processing: &nbsp; &nbsp;10 &nbsp; 18 &nbsp; 3.6 &nbsp; &nbsp; 19 &nbsp; &nbsp; 239  <br> Waiting: &nbsp; &nbsp; &nbsp; &nbsp;9 &nbsp; 17 &nbsp; 3.5 &nbsp; &nbsp; 17 &nbsp; &nbsp; 237  <br> Total: &nbsp; &nbsp; &nbsp; &nbsp; 18 &nbsp; 20 &nbsp; 5.6 &nbsp; &nbsp; 20 &nbsp; &nbsp; 241  <br> </p><p>Percentage of the requests served within a certain time (ms)  <br> &nbsp; 50% &nbsp; &nbsp; 20  <br> &nbsp; 66% &nbsp; &nbsp; 20  <br> &nbsp; 75% &nbsp; &nbsp; 20  <br> &nbsp; 80% &nbsp; &nbsp; 20  <br> &nbsp; 90% &nbsp; &nbsp; 21  <br> &nbsp; 95% &nbsp; &nbsp; 21  <br> &nbsp; 98% &nbsp; &nbsp; 46  <br> &nbsp; 99% &nbsp; &nbsp; 47  <br> &nbsp;100% &nbsp; &nbsp;241 (longest request)  <br> </p><p>代码 2: Eurasia3 自带 Demo  <br> -------------------------------------------------------  <br> 启动 demo:  <br> &nbsp; &nbsp; $ ./demo start  <br> </p><p>功能:  <br> &nbsp; &nbsp;使用了逻辑调度器, 每 0.1 秒对协程进行一次调度。  <br> &nbsp; &nbsp;使用了 session, 在测试中为每个请求建立一份 session (共计 10000 份)。  <br> </p><p>-------------------------------------------------------  <br> 基准测试:  <br> </p><p>$ ab -c 1021 -n 10000 '<a target="_blank" rel="nofollow" href="http://localhost:8080/%27"  >http://localhost:8080/'</a>  <br></p>Server Software:  <br><p> Server Hostname: &nbsp; &nbsp; &nbsp; &nbsp;localhost  <br> Server Port: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;8080  <br> </p><p>Document Path: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/  <br> Document Length: &nbsp; &nbsp; &nbsp; &nbsp;8 bytes  <br> </p><p>Concurrency Level: &nbsp; &nbsp; &nbsp;1021  <br> Time taken for tests: &nbsp; 8.923888 seconds  <br> Complete requests: &nbsp; &nbsp; &nbsp;10000  <br> Failed requests: &nbsp; &nbsp; &nbsp; &nbsp;0  <br> Write errors: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0  <br> Total transferred: &nbsp; &nbsp; &nbsp;2521500 bytes  <br> HTML transferred: &nbsp; &nbsp; &nbsp; 80688 bytes  <br> Requests per second: &nbsp; &nbsp;1120.59 [#/sec] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 911.129 [ms] (mean)  <br> Time per request: &nbsp; &nbsp; &nbsp; 0.892 [ms] (mean, across all concurrent  <br> requests)  <br> Transfer rate: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;275.89 [Kbytes/sec] received  <br> </p><p>Connection Times (ms)  <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min &nbsp;mean[+/-sd] median &nbsp; max  <br> Connect: &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp;252 823.2 &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp;3011  <br> Processing: &nbsp; 130 &nbsp;186 &nbsp;89.0 &nbsp; &nbsp;170 &nbsp; &nbsp; 921  <br> Waiting: &nbsp; &nbsp; &nbsp;129 &nbsp;182 &nbsp;89.1 &nbsp; &nbsp;165 &nbsp; &nbsp; 915  <br> Total: &nbsp; &nbsp; &nbsp; &nbsp;143 &nbsp;438 877.6 &nbsp; &nbsp;176 &nbsp; &nbsp;3929  <br> </p>Percentage of the requests served within a certain time (ms)  <br> &nbsp; 50% &nbsp; &nbsp;176  <br> &nbsp; 66% &nbsp; &nbsp;180  <br> &nbsp; 75% &nbsp; &nbsp;185  <br> &nbsp; 80% &nbsp; &nbsp;191  <br> &nbsp; 90% &nbsp; &nbsp;221  <br> &nbsp; 95% &nbsp; 3223  <br> &nbsp; 98% &nbsp; 3419  <br> &nbsp; 99% &nbsp; 3916  <br> &nbsp;100% &nbsp; 3929 (longest request)<br><br><br>附录 (机器配置):<br><br><p>$ cat /proc/version  <br> Linux version 2.6.20-16-generic (root@terranova) (gcc version 4.1.2  <br> (Ubuntu 4.1.2-0ubuntu4)) #2 SMP Sun Sep 23 19:50:39 UTC 2007  <br> </p><p>$ cat /proc/cpuinfo  <br> processor &nbsp; &nbsp; &nbsp; : 0  <br> vendor_id &nbsp; &nbsp; &nbsp; : AuthenticAMD  <br> cpu family &nbsp; &nbsp; &nbsp;: 15  <br> model &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 75  <br> model name &nbsp; &nbsp; &nbsp;: AMD Athlon(tm) 64 X2 Dual Core Processor 3600+  <br> stepping &nbsp; &nbsp; &nbsp; &nbsp;: 2  <br> cpu MHz &nbsp; &nbsp; &nbsp; &nbsp; : 2009.283  <br> cache size &nbsp; &nbsp; &nbsp;: 256 KB  <br> physical id &nbsp; &nbsp; : 0  <br> siblings &nbsp; &nbsp; &nbsp; &nbsp;: 2  <br> core id &nbsp; &nbsp; &nbsp; &nbsp; : 0  <br> cpu cores &nbsp; &nbsp; &nbsp; : 2  <br> fdiv_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> hlt_bug &nbsp; &nbsp; &nbsp; &nbsp; : no  <br> f00f_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> coma_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> fpu &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : yes  <br> fpu_exception &nbsp; : yes  <br> cpuid level &nbsp; &nbsp; : 1  <br> wp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: yes  <br> flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge  <br> mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext  <br> fxsr_opt lm 3dnowext 3dnow pni cx16 lahf_lm cmp_legacy svm cr8legacy  <br> ts fid vid ttp tm stc  <br> bogomips &nbsp; &nbsp; &nbsp; &nbsp;: 4021.64  <br> clflush size &nbsp; &nbsp;: 64  <br> </p><p>processor &nbsp; &nbsp; &nbsp; : 1  <br> vendor_id &nbsp; &nbsp; &nbsp; : AuthenticAMD  <br> cpu family &nbsp; &nbsp; &nbsp;: 15  <br> model &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : 75  <br> model name &nbsp; &nbsp; &nbsp;: AMD Athlon(tm) 64 X2 Dual Core Processor 3600+  <br> stepping &nbsp; &nbsp; &nbsp; &nbsp;: 2  <br> cpu MHz &nbsp; &nbsp; &nbsp; &nbsp; : 2009.283  <br> cache size &nbsp; &nbsp; &nbsp;: 256 KB  <br> physical id &nbsp; &nbsp; : 0  <br> siblings &nbsp; &nbsp; &nbsp; &nbsp;: 2  <br> core id &nbsp; &nbsp; &nbsp; &nbsp; : 1  <br> cpu cores &nbsp; &nbsp; &nbsp; : 2  <br> fdiv_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> hlt_bug &nbsp; &nbsp; &nbsp; &nbsp; : no  <br> f00f_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> coma_bug &nbsp; &nbsp; &nbsp; &nbsp;: no  <br> fpu &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : yes  <br> fpu_exception &nbsp; : yes  <br> cpuid level &nbsp; &nbsp; : 1  <br> wp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: yes  <br> flags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge  <br> mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext  <br> fxsr_opt lm 3dnowext 3dnow pni cx16 lahf_lm cmp_legacy svm cr8legacy  <br> ts fid vid ttp tm stc  <br> bogomips &nbsp; &nbsp; &nbsp; &nbsp;: 4018.57  <br> clflush size &nbsp; &nbsp;: 64  <br> </p>$ cat /proc/meminfo  <br> MemTotal: &nbsp; &nbsp; &nbsp;2075004 kB  <br> MemFree: &nbsp; &nbsp; &nbsp; 1841156 kB  <br> Buffers: &nbsp; &nbsp; &nbsp; &nbsp; 10448 kB  <br> Cached: &nbsp; &nbsp; &nbsp; &nbsp; 173656 kB  <br> SwapCached: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 kB  <br> Active: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;95236 kB  <br> Inactive: &nbsp; &nbsp; &nbsp; 107744 kB  <br> HighTotal: &nbsp; &nbsp; 1178496 kB  <br> HighFree: &nbsp; &nbsp; &nbsp; 973204 kB  <br> LowTotal: &nbsp; &nbsp; &nbsp; 896508 kB  <br> LowFree: &nbsp; &nbsp; &nbsp; &nbsp;867952 kB  <br> SwapTotal: &nbsp; &nbsp; 6080560 kB  <br> SwapFree: &nbsp; &nbsp; &nbsp;6080560 kB  <br> Dirty: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 kB  <br> Writeback: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 kB  <br> AnonPages: &nbsp; &nbsp; &nbsp; 18968 kB  <br> Mapped: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8952 kB  <br> Slab: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;14340 kB  <br> SReclaimable: &nbsp; &nbsp; 6168 kB  <br> SUnreclaim: &nbsp; &nbsp; &nbsp; 8172 kB  <br> PageTables: &nbsp; &nbsp; &nbsp; &nbsp;844 kB  <br> NFS_Unstable: &nbsp; &nbsp; &nbsp; &nbsp;0 kB  <br> Bounce: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 kB  <br> CommitLimit: &nbsp; 7118060 kB  <br> Committed_AS: &nbsp; 513260 kB  <br> VmallocTotal: &nbsp; 114680 kB  <br> VmallocUsed: &nbsp; &nbsp; 11708 kB  <br> VmallocChunk: &nbsp; &nbsp;67544 kB<br>  </div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007102133552397</comments>
    <slash:comments>15</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007102133552397</guid>
    <pubDate>Wed, 21 Nov 2007 15:35:52 +0800</pubDate>
    <dcterms:modified>2011-09-25T11:21:01+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[攀岩的乐趣]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200710186445910</link>
    <description><![CDATA[<div>攀岩很刺激。我在阳朔看到了, 人可以爬到将自己摔死的高度。当然我也试过, 这里顺便说一下, 我手无缚鸡之力。<br><br>因为家族遗传, 身材比较魁梧, 因此家里严禁锻炼臂力, 防止变成倒三角型的肌肉男。我当然痛恨这种有勇无谋的形象, 因此我取而代之投戎从笔。从此, 臂力就比较贫弱了, 这导致后来只能从事一些简单劳动, 画几幅画, 写一点诗, 编两首曲, 或者比如程序来混口饭吃。当然了, 玩攀岩的都知道, 其实并不需要什么臂力。好吧, 我恐高。<br><br>我不知道有什么理由可以不恐高。爬到高处然后把自己摔死, 匹夫也。于是乎后来我去了华山, 辛苦大家来赶黄金周, 这让我明白了两个道理。一, 其实并没有人真的恐高; 二, 在黄金周睡觉好过出来旅游。<br><br>我回忆了一下, 老家吴兴郡乃是天下所谓极限运动之都, 脸皮也就厚了起来, 纵然手无缚鸡之力, 亦或恐高, 攀个岩恐怕也不是什么难事。另一方面, 对大众装逼运动我通常都没有什么好感, 比如轮滑。作为表示, 我踩着滑板背着琴从中穿过, 一个豚跃飞出校门, 并在空中弹出一个漂亮的和铉, 绝尘而去。<br><br>我行驶在钱塘县无人的郊外上, 自鸣得意地想, 作为一个成熟的上国男人, 是内敛的。大隐于市, 掩人耳目, 岂能炫技于市井。正得意间, 后面警车作响, 交警喝道, 此路不能行滑板, 且卸板步行! 心中一惊, 遂使绝技, 加速至时速数百夺高速而走。警望尘兴叹。<br><br>对应另一个装逼运动攀岩, 我似乎更喜欢爬山, 你选择一个坡度, 擎着树干藤蔓就开始往上爬, 你能看到奇花异草和毒蛇猛兽, 渴饮露水饥食花果, 得自然趣味。我自鸣得意地想, 对于一个成熟的上国男人, 攀岩是不合适的。西方蛮夷更喜欢征服, 他登山是要征服一个山头, 攀岩亦如是。而真正的中国人, 寻求天人合一, 在山间以甘泉泡上一杯绿茶, 得道成仙, 知天运命。<br><br>相反, 另一项极限运动却是颇值得称道的。译名城市疾走, 或曰跑酷。它很可以装逼, 但是它和某些貌似很惊险刺激, 却又需要昂贵安全器械的极限运动不同, 没有任何禁锢和形式。喜欢装逼的人仍然可以抛开那根绳子赤手爬到雪线以上, 也可以简单到绕西湖跑上十圈, 也可以像火箭一样穿过闹市步行街而不碰到任何人。<br><br>很简单, 不是吗? 当然, 我这里并不是要推广爬山或是疾走什么的。本文的主旨是告诉大家攀岩的乐趣, 好了, 回到数年前的攀岩现场, 这时我已经绑好了绳子。<br><br>我很快地攀了上去, 到了上面便有些恐高, 于是就下来了。<br><br><embed allowScriptAccess="never" allowNetworking="internal"       type="application/x-shockwave-flash" src="http://www.youtube.com/v/rsDYf4-JKTA" style="margin: 0px auto 10px; display: block; text-align: center;" autostart="0" loop="0" height="355" width="425">&nbsp;<br><br><embed allowScriptAccess="never" allowNetworking="internal"       type="application/x-shockwave-flash" src="http://www.youtube.com/v/3KSr1pozm6Y" style="margin: 0px auto 10px; display: block; text-align: center;" autostart="0" loop="0" height="355" width="425">&nbsp;</div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200710186445910</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200710186445910</guid>
    <pubDate>Sun, 18 Nov 2007 18:04:45 +0800</pubDate>
    <dcterms:modified>2007-11-18T20:38:47+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[欲购从速]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200710143739204</link>
    <description><![CDATA[<div><center><embed allowScriptAccess="never" allowNetworking="internal"       src="http://player.youku.com/player.php/sid/XNzE2MDQw/v.swf" style="display: block; width: 450px; height: 327px;" autostart="0" loop="0"><br /><embed allowScriptAccess="never" allowNetworking="internal"       src="http://player.youku.com/player.php/sid/XODExMjQ3Ng==/v.swf" style="display: block; width: 450px; height: 327px;" autostart="0" loop="0"></center></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200710143739204</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200710143739204</guid>
    <pubDate>Wed, 14 Nov 2007 15:07:39 +0800</pubDate>
    <dcterms:modified>2007-11-14T15:17:41+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[在网页中实现单击图片立即上传文件]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820077133835626</link>
    <description><![CDATA[<div><p>点击图片弹出文件浏览框, 选择文件点击确定便立即上传文件 ── 这被认为是一种不可能实现的技术。因为本博是变态的, 所以这里当然要讲解一下了。不过江湖凶险, 本博还是建议大伙不要轻易尝试。</p><p style="text-align: center;"><a href="http://img.blog.163.com/photo/QlauM5nQBwYQYtpnu9URmw==/486388759756826806.jpg" target="_blank"><img src="http://img.blog.163.com/photo/UZN0-zYXCR8ovG2z5R7m4g==/482448110082881358.jpg"></a></p>
<br>
<p>好了, 下面我们就根据这张例图, 从左到右一步一步地讲解。</p>
<br>
<h3>第一步, 找一张很帅很帅的图片</h3>
<p>我们需要一张很帅的图片作为上传按钮, 这是所有步骤中最关键和最为困难的一步。花了九牛二虎之力, 在下终于找到了一张举世无双的帅气图片 (见上面的例图), 无疑我们已经成功了 99%。</p>
<br>
<h3>第二、第三、第四步</h3>
<p>使用浮动层把透明的文件上传控件 (的按钮部分) 覆盖到图片上。这样用户去点图片, 其实点到的是文件上传控件的 "浏览按钮"。这样, 用户的感觉好像是点击了这个图片才弹出文件选择框的。</p>
<br>
<h3>设定文件上传控件的 onchange 事件, 实现选定文件立即上传</h3>
<p>设置文件上传控件的 "onchange" 事件, 立即调用文件上传表单 (form) 的 "submit()" 方法。这样用户使用文件选择框选择好文件, 单击确定, 文件上传过程就立即开始了。</p>
<br>
<h3>使用透明文件上传按钮盖住图片的关键</h3>
<ul>
<li>我们只需要文件上传控件的按钮部分, 如果无法隐藏文件上传控件左半边的字符输入框部分, 就把他移出屏幕。</li>
<li>如果文件上传控件不够大, 不能完全覆盖图片, 就修改控件的字体大小, 增加 font-size 就可以搞大文件上传控件按钮的大小。</li>
<li>如果还是不够大, 就用两个文件上传控件来覆盖图片。</li>
</ul>
<br>
<p style="text-align: center;">当然上述技巧都相当地恶心。这也是博主忠告诸位不要轻易尝试的原因。</p>
<br>
<h3>代码</h3>
<pre>&lt;html&gt;<br>&lt;head&gt;<br>&lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"&gt;<br>&lt;title&gt;upload.html, 一个文件上传按钮, 用于 iframe 嵌入&lt;/title&gt;<br>&lt;script language="JavaScript"&gt;<br>window.do_upload = function(n) {<br> if(document.getElementById('upload').value == '')<br>  return;<br><br> document.getElementById('upload_display').style.display = 'none';<br> document.getElementById('uploading').style.display = '';<br><br> var l = filename.split(/[\/\\]/), filename = l[l.length - 1];<br><br> // TODO: 本窗口将被用于提交文件,<br> //  请在父窗口 ( window.parent) 再生成一个文件上传按钮<br><br> document.forms[n].submit();<br>};<br>&lt;/script&gt;<br>&lt;/head&gt;<br>&lt;body style="padding: 0px; margin: 0px; vertical-align: middle; text-align: center;"&gt;<br>&lt;span id="upload_display"&gt;<br>&lt;img src="http://9.douban.com/mpic/s2356949.jpg"<br> style="position: absolute; left: 0px; top: 0px;"/&gt;<br>&lt;form action="upload.cgi" method="post" enctype="multipart/form-data"&gt;<br> &lt;input id="upload" name="upload" type="file" onchange="do_upload(0)"<br>  style="position: absolute; top: 0px; font-size: 44px; left: -640px; -moz-opacity:0; filter:alpha(opacity: 0); opacity: 0;" /&gt;<br>&lt;form action="upload.cgi" method="post" enctype="multipart/form-data"&gt;<br> &lt;input id="upload" name="upload" type="file" onchange="do_upload(1)"<br>  style="position: absolute; top: 60px; font-size: 44px; left: -640px; -moz-opacity:0; filter:alpha(opacity: 0); opacity: 0;" /&gt;<br>&lt;/form&gt;<br>&lt;/span&gt;<br><br>&lt;span id="uploading" style="display: none; font-size: 12px; color: #961;"&gt;uploading ...&lt;/span&gt;<br><br>&lt;/body&gt;<br>&lt;/html&gt;<br></pre>

<br>
<h3>最后一步, 使用 iframe 在需要上传的地方嵌入这个页面</h3>
<p>&lt;iframe src="upload.html" border="0" frameborder="no" style="width: 124px; height: 124px;"&gt;&lt;/iframe&gt;</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820077133835626</comments>
    <slash:comments>17</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820077133835626</guid>
    <pubDate>Wed, 1 Aug 2007 15:38:35 +0800</pubDate>
    <dcterms:modified>2007-08-01T15:59:03+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[清廉战士片头]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007627102714340</link>
    <description><![CDATA[<div><a style="color: rgb(153, 51, 51);" rel="nofollow" href="http://www.cnlzyx.cn/"  >清廉战士</a>无疑是今年夏天最接近于空调的网游神作, 在下抢先一步安装了这个今年最值得期待的网游。尽管无论在 Wine 还是在 XP 虚拟机上都跑不起来, 我还是在一堆 ".bak" 和 "Thumbs.db" 文件中找到了片头动画。"雷电满怀骄傲地邀请您体验这段冒险, 这年春天, 世界的命运在你的掌握之中 ..."。<a style="color: rgb(153, 51, 51);" rel="nofollow" href="http://www.cnlzyx.cn/"  >中国廉政文化游戏网</a>, 您太有才了! <br><br><br>  <div style="padding-left: 100px;"  ><embed height="350" allowNetworking="internal" width="425" allowScriptAccess="never" invokeurls="false" src="http://www.youtube.com/v/WTr3Kkgzqpo" type="application/x-shockwave-flash" wmode="transparent"  ></div></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007627102714340</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007627102714340</guid>
    <pubDate>Fri, 27 Jul 2007 22:27:14 +0800</pubDate>
    <dcterms:modified>2011-09-26T19:56:30+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[漂亮的回旋踢 (实时视频)]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200761354220263</link>
    <description><![CDATA[<div><img title="漂亮的回旋踢 (实时视频) - 沈崴 - 蜻蜓点水 举重若轻"  alt="漂亮的回旋踢 (实时视频) - 沈崴 - 蜻蜓点水 举重若轻"  src="http://img.blog.163.com/photo/UVCW2HIA8xcsWSQfz6Pf4g==/348184546191252269.jpg"  >  <br><br>  (过两亿了, 有客留言有 PS 的可能, 故下面录像为证)  <br><br>  <embed height="350" allowNetworking="internal" width="425" allowScriptAccess="never" invokeurls="false" src="http://www.youtube.com/v/x2TNmcfAQIc" type="application/x-shockwave-flash" wmode="transparent"  >  <br><br>  (闯关过 20 亿实时视频, 试了两次)  <br><br>  <a rel="nofollow" href="http://www.ywlt.com/flash/0bells.swf"  ><b>这个游戏在这里</b></a></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200761354220263</comments>
    <slash:comments>15</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200761354220263</guid>
    <pubDate>Fri, 13 Jul 2007 17:42:20 +0800</pubDate>
    <dcterms:modified>2011-10-01T15:25:05+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[手机收看土豆视频指南]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200754112553654</link>
    <description><![CDATA[<div><p>好了, 不要误会, 我不是在线看的意思。目前流量还不算太便宜 (昨天刚充了 100￥ 今天又欠费了 ……)。</p>  <p>今天我们只需要简单地把土豆网的视频下载下来, 然后用手机来看就可以了。</p>  <div style="margin-left: 160px;"  ><img title="手机收看土豆视频指南 - 沈崴 - 蜻蜓点水 举重若轻"  alt="手机收看土豆视频指南 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://www.nokia.com.cn/cn/images/phones/models/n5300/features/img_n5300_features.jpg"  ></div>  <h3>首先安装 ffmpeg</h3>  <p><b>1. 安装编译环境</b></p>  <pre>sudo apt-get install build-essential<br>sudo apt-get install dpkg-dev libimlib2-dev texi2html liblame-dev libfaad2-dev libmp4v2-dev libfaac-dev libxvidcore4-dev debhelper libogg-dev libvorbis-dev liba52-dev libdts-dev libsdl1.2-dev libraw1394-dev libdc1394-13-dev libtheora-dev libgsm1-dev</pre>  <p><b>2. 得到 ffmpeg 源码</b></p>  <pre>cd /usr/local/src # 任意你喜欢的目录<br>apt-get source ffmpeg<br>cd ffmpeg-0.cvs20060823<br></pre>  <p><b>3. 下载 amr 支持</b></p>  <pre>wget http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip<br>wget http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-510.zip<br></pre>  <p>解压缩 26204-510.zip 把里面的文件放到 libavcodec/amrwb_float 目录下。<br>  解压缩 26104-510.zip 把里面的文件放到 libavcodec/amr_float 目录下。  </p>  <p><b>4. 编译 ffmpeg</b></p>  <p>在此之前, 你可能需要把原来的 ffmpeg 包卸载掉。</p>  <pre>./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-faadbin --enable-dts --enable-pp --enable-faad --enable-faac --enable-x264 --enable-pthreads --disable-ffserver<br>make<br>make install</pre>  <p>ffmpeg 是手机视频的关键, 请务必搞定本步骤再继续。</p>  <a rel="nofollow" href="http://blogger.rukker.org/2006/07/12/enable-mp3-and-amr-support-in-ffmpeg-ubuntudebian/"  >本节参见 Enable mp3 and amr support in ffmpeg</a><br><br><br>  <h3>一个下载土豆网在线视频的工具</h3>  <p><b>1. 大喊三声 "感谢 Yi.Huang 大师"</b></p>  <p>大师 Yi.Huang 是上帝派来拯救人类的, 这是他的神迹之一 ……</p>  <p><b>2. 下载某种工具</b></p>  <pre>wget http://huangyilib.googlecode.com/svn/trunk/tudou_dl.py</pre>  <p><b>3. 现在你已经可以下载土豆网的视频到本地来了</b></p>  <p>假如 http://www.tudou.com/programs/view/AmYV7YnHqBU/ 是视频地址, 那么</p>  <pre>python tudou_dl.py http://www.tudou.com/programs/view/AmYV7YnHqBU/</pre>  <p>这样你就可以得到视频的下载地址, 然后你就可以把它下载下来了。</p>  <p>他是一个 flv 格式的视频文件。</p>  <a rel="nofollow" href="http://codeplayer.blogspot.com/2007/01/tudou.html"  >本节请参见大师 Yi.Huang 的 Blog</a><br><br><br>  <h3>把 flv 转换成手机的 3gp 格式</h3>  <p><b>1. 你可以执行命令</b></p>  <pre>ffmpeg -i 输入文件.flv -s 176×144 -vcodec h263 -r 25 -b 200 -ab 64 -acodec aac 输出文件.3gp</pre>  <p><b>请注意其中的 "-acodec aac" 参数</b>这是以 aac 编码声音。这适合我的 Nokia 5300 手机。你也可以使用 "-acodec mp3" 这个参数 (在 Nokia 5300 中使用该参数无法正常播放声音)。</p>  <p><b>2. 你还可以 ……</b></p>  <p>下载这个脚本</p>  <pre>wget http://blog.fakap.net/mp3toflv/flvto3gp.sh</pre>  <p>不过这个脚本输出的 3gp 视频也可能存在声音不正常的情况, 你可以手工修改下面这行代码的声音参数:</p>  <pre>ffmpeg -i $1 -s 176×144 -vcodec h263 -r 25 -b 200 -ab 64 -acodec mp3  -ac 1 -ar 8000 $1.3gp</pre>  <p>"-acodec mp3  -ac 1 -ar 8000" 这三个是声音参数。你可以只设定 -acodec XXX。</p>  <a rel="nofollow" href="http://blog.mypapit.net/2007/04/ffmpeg-based-batch-flv-to-3gp-converter-scripts.html"  >本节请参见 FFMpeg based FLV to 3gp batch converter scripts</a>  <br><br><br>  <h3>我准备抽空把事情搞得更好玩一些</h3>  <p>1. 很显然, 我们需要一个 GUI 来自动化一切。</p>  <p>2. 我们需要支持更多的在线视频网站, 并且持续跟踪。<br>在线视频网站可能会试图通过修改视频下载策略来避免被用户下载, 但是这对任何一个 Python 玩家来讲都是徒劳的。相对于某些人的举手之劳而言, 网站的更动成本就太高了。</p>  <p>3. 或许我还会考虑一下 Windows 用户。</p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200754112553654</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200754112553654</guid>
    <pubDate>Tue, 5 Jun 2007 00:11:52 +0800</pubDate>
    <dcterms:modified>2011-09-23T20:05:58+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[我們只選賤的]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007414854684</link>
    <description><![CDATA[<div><img src="http://photo8.yupoo.com/20070430/233748_320990734.jpg"><br><br><img src="http://photo6.yupoo.com/20070430/233752_1513583898.jpg"><br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007414854684</comments>
    <slash:comments>6</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007414854684</guid>
    <pubDate>Tue, 1 May 2007 16:08:54 +0800</pubDate>
    <dcterms:modified>2007-05-01T16:08:54+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[我們只選貴的]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007311112622304</link>
    <description><![CDATA[<div><img src="http://photo7.yupoo.com/20070410/221021_517158637.jpg"><br><br><img src="http://photo7.yupoo.com/20070410/221025_1118981903.jpg"><br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007311112622304</comments>
    <slash:comments>9</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007311112622304</guid>
    <pubDate>Wed, 11 Apr 2007 11:26:22 +0800</pubDate>
    <dcterms:modified>2007-04-11T11:26:22+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Eurasia3 作者声明, 将抛弃 Python 转而使用 Lua 和 Ruby]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820072232303647</link>
    <description><![CDATA[<div><img src="http://swl.ent.163.com/imagebz/1134491276775.jpg" style="margin-left: 80px;"><br><br>

&nbsp;&nbsp;&nbsp;&nbsp;自从 Pre alpha 之后, 著名的 Python 开源框架 Euraisa3 的作者 William Shen 宣布将抛弃 Python 转而使用更为强大的 Lua 和 Ruby  重写 Eurasia3。<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;── "Python 令人绝望, 为了获得更快的执行效率, 并突显我的牛叉。我将使用 Lua 构建底层核心, 并且使用 Ruby 构建华丽的拱顶。"<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;── "国内的 Pythoner, 你们已经有 Django 了, 所以你们实际上已经不再需要其他框架了。我联系过 TurboGears 的作者, 试图说服他们解散开发团队 …… 恰好他们也正有此意。"<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;"毫无疑问我需要被追捧, 或许这在 Windows 社区或者初学者社区里将更容易实现一些。"<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;── 在接受采访时 William Shen 如是答道。<br><br>

&nbsp;&nbsp;&nbsp;&nbsp;在问到使用 Lua 和 Ruby 技术后 Eurasia3 将会有哪些进步时 William Shen 慷慨回答说, 除了 Pypy 谁也不相信 Python 的执行效率会比 C 快 10 倍、比 C++ 快 100 倍, 所以他决定放弃这个不切实际的想法。<br>
&nbsp;&nbsp;&nbsp;&nbsp;而牛人们普遍任为 Lua 的执行效率要比 Python 快 4 倍以上, 为了向牛人兼容, 所以将使用 Lua, 因此 Eurasia3 的速度理论上将提高 4 倍以上。<br>
&nbsp;&nbsp;&nbsp;&nbsp;── 但是使用 Lua 以后框架实际上只获得了原有速度的 1/10, 而且看上去已经使用了所有的优化手段, "事实上, 我使用 C 和汇编替代了大部分 Lua 的代码, 这当然得感谢 Lua 对 C 的完美支持"。William Shen 补充到。<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;最后记者询问新的 Eurasia3 将于何时发布。William Shen 答道他目前每天正在烧香感谢 Ruby 的高开发效率。William Shen 说最近他感觉良好, 他使用 Ruby 进行网页开发, 获得了超过 JavaScript 10 倍的开发效率, 并且使用 Ruby 代替 C 语言只花了 1/10 的时间就 "基本" 实现了 Apache 和 Linux 操作系统。因为 Ruby 更面向对象, 所以他正在编写 Ruby 版的 Plone ── 很显然 William Shen 已经是世界上最多产的开源软件作者 "之一"。<br>
&nbsp;&nbsp;&nbsp;&nbsp;── 但是目前还没有发布 Lua、Ruby 版 Eurasia3 的时间表, "这不是 Ruby 的问题, 因为框架的很多特性都不是面向对象的, 显然框架的设计思想有问题"。William 补充道, 而且他纠正记者 Euraisa3 已经不被使用, 框架现在的名字是 "Lua   and Ruby on Euraisa"。<br><br>
<p style="color: rgb(136, 136, 136);">相关链结:<a href="http://eishn.blog.163.com/blog/static/652318200721462524781/">Eurasia3 Pre Alpha! (Eurasia3 Alpha 版预发布)</a></p></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820072232303647</comments>
    <slash:comments>10</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820072232303647</guid>
    <pubDate>Sun, 1 Apr 2007 23:57:54 +0800</pubDate>
    <dcterms:modified>2007-04-02T00:51:51+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3]]></title>	
    <link>http://eishn.blog.163.com/blog/static/652318200721462524781</link>
    <description><![CDATA[<div><img title="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  alt="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  style="width: 268px; height: 201px;"  src="http://pulolesu.game-server.cc/dream/hokuto/21.jpg"  ><img title="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  alt="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  style="width: 269px; height: 201px;"  src="http://pulolesu.game-server.cc/dream/hokuto/11.jpg"  ><br><img title="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  alt="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  style="width: 269px; height: 197px;"  src="http://pulolesu.game-server.cc/dream/hokuto/30.jpg"  ><a rel="nofollow" href="http://eurasia.svn.sourceforge.net/viewvc/eurasia/"  ><img title="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  alt="PRE ALPHA! 史上最无聊之 Web Framework －－  Eruasia 3 - 沈崴 - 蜻蜓点水 举重若轻"  style="padding-left: 60px;"  src="http://images.sourceforge.net/sfx/sfx_logo2.png"  ></a><br>  <br><br>  <center>  <h1>WHAT'S THE HELL !</h1>  WSGI、TurboGears、Django、Pylons、CherryPy、web.py …… 这个世界太美好了。<br>  …… 而过于完美正是残缺的开始, 所以, Eurasia3 出现了。<br><br>  <h1>别以为所有框架都是可以用的</h1>  Eurasia3 不是面向对象的, Eurasia3 也不支持代码复用, Eurasia3 不仅无法也不支持扩展。<br>  Euraisa3 永远无法支持 WSGI。<br>  在 Eurasia3 里面, 你需要手工接受用户请求的每一个字节, 手工解析 URL, 手工处理 Cookie。<br>  Eurasia3 无法支持 Session, Eurasia3 不推荐使用页面模板, Eurasia3 不带数据库支持。<br>  凡是其他框架有的功能, Eurasia3 基本上都不提供。<br><br>  <h1>Eurasia3 的开发效率?</h1>  快速开发是不可能的, 在 Eurasia3 中实现 Hello world 需要 300 行代码。<br>  Eurasia3 推荐你从 Socket 层开始编写你的应用, 包括一个 HTTP 服务器。<br>  一旦你决定使用 Eurasia3, 你的工作效率将会成倍下降。<br><br>  <h1>Eurasia3 的运行效率</h1>  基于 Eurasia3 的程序会用完你所有的 CPU 以及内存。<br>  不用怀疑了, Eurasia3 的 CPU 占用率就是 100%。<br>  <h1>谁会使用 Eurasia3?</h1>  脑残、黑客、时间宽裕者、原教旨主义者以及我的盲目崇拜者。<br><br>  </center></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/652318200721462524781</comments>
    <slash:comments>10</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/652318200721462524781</guid>
    <pubDate>Wed, 14 Mar 2007 19:18:01 +0800</pubDate>
    <dcterms:modified>2011-09-25T08:51:35+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[[Python 一招鲜系列] 守护进程一招鲜]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820072574234114</link>
    <description><![CDATA[<div><img title="[Python 一招鲜系列] 守护进程一招鲜 - 沈崴 - 蜻蜓点水 举重若轻"  alt="[Python 一招鲜系列] 守护进程一招鲜 - 沈崴 - 蜻蜓点水 举重若轻"  style="width: 528px; height: 395px;"  src="http://cndesk.com/Pics/GenericPics/4_Game/29_djyx/678_sh/CNDESK_20wde1m0612210005.jpg"  >  <br><br>  <a style="font-size: 12px; color: rgb(102, 102, 102);" rel="nofollow" href="http://www.mangbar.com/bar/docview/bd18e8290f7bfbb9010f7f7f7d6201d9"  >更多精彩请访问 Pythoner 在 Mangbar 的营地</a><br>  <a style="font-size: 12px; color: rgb(102, 102, 102);" rel="nofollow" href="http://www.mangbar.com/task/doclist/5d023b210fa2cc84010fa30b21d00014"  >Python 一招鲜系列文章综览</a>  <br><br>  <pre># server.py<br>while True:<br>&nbsp;&nbsp;&nbsp;continue<br><br>好了现在我们已经有了一个服务器了, 接下来要做的事情就是让他跑到后台去。<br><br><br><br><br><br><br>第一章, 原理<br><br>本章仅作了解就可以了, 因为这些细节性的东西实在是无聊,<br>所以我强烈推荐你直接跳到第二章。<br><br>&nbsp;&nbsp;&nbsp;当然, 如果你有足够的耐心和能力, 还是看下去吧 ……<br><br>通常我们把后台进程叫做 "守护进程"、"精灵进程", 或者 daemon。<br>在 Unix 下, 我们使用 fork 实现。<br><br>&nbsp;&nbsp;&nbsp;import os<br>&nbsp;&nbsp;&nbsp;def daemonize():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 首先 fork 出两个进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid = os.fork()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# pid 非零的是父进程,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 父进程就是你用命令启动的那个程序。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid != 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 接着我们退出父进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 这样你的命令行程序就退出了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 父进程退出后, 子进程就被系统托管了<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 这时子进程就转入后台执行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os._exit(0)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 子进程开始<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 我们在这里启动后台程序 (服务器)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.system('python server.py')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 当然, 你永远不会使用 os.system 来启动一个程序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# os.system 会启动 python、server.py 还有你不希望看到的 sh 进程<br><br>当然, 真正能用的 daemonize 程序还要作更多的事情,<br>这些都被记载在典籍《Unix 高级环境编程》中。<br><br>我归纳了一下, 分别是一下几个方面。<br><br>&nbsp;&nbsp;&nbsp;1. 切换程序的身份。<br>&nbsp;&nbsp;&nbsp;   请看 Apache 的设计, 在使用 root 得到 80 端口后旋即转换成 nobody (www-data) 用户。<br>&nbsp;&nbsp;&nbsp;   很明显, 使用 root 身份执行一个程序是危险的, 后台程序的身份不应该是 root。<br><br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;最实用的选择是: 当配置文件里没有说明以何身份执行时,<br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;就以当前用户的身份启动后台进程。<br><br>&nbsp;&nbsp;&nbsp;2. 自定义部分信号处理程序。<br><br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;如果不是必须, 依我看还是不要做太多信号处理,<br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;否则你的服务器很可能将只能吃到 kill -9 才可退出了, 这显然很蠢。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果你不想看到太多的 undead, 处理 SIGCHLD 是必须的。<br><br>&nbsp;&nbsp;&nbsp;3. 重定向 stdin、stdout 和 stderr。<br>&nbsp;&nbsp;&nbsp;   标准输入输出对 daemon 进程而言没有意义, 因为后台进程是没有终端可供使用的。<br><br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;注意, 这里是重定向而不是关闭, 这样可以避免程序在 print 的时候出错。<br><br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;我们通常会将 stdout、stderr 重定向到日志文件。<br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;/dev/nul 是选择之一。<br>&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;stdin 是没有意义的。<br><br>&nbsp;&nbsp;&nbsp;4. setsid(), umask(), chdir() 逐一 google。这里不赘述了。<br><br>&nbsp;&nbsp;&nbsp;5. 把 pid 写到 xxx.pid 文件中去。<br>&nbsp;&nbsp;&nbsp;   当我们需要结束后台进程的时候, 我们就可以从 pid 文件中得到子进程的 pid,<br>&nbsp;&nbsp;&nbsp;   然后 kill PID。<br><br>目前, Python 最好的 Daemon 库依然是 Zope 的 zdaemon,<br>欲了解健壮的 Daemon 实现, 可以阅读 zdaemon 的源代码。<br>当然, 阅读 zdaemon 源码是比较痛苦的, 我自己也比较痛恨 zdaemon 的编码风格。<br><br>&nbsp;&nbsp;&nbsp;我痛恨一切没有必要的, 过度的 OO 设计。<br><br>zdaemon 的贡献是它引入了 "进程控制器" 这个概念, 它的 daemonize 使用了两次 fork。<br><br>&nbsp;&nbsp;&nbsp;# zdaemon.py<br>&nbsp;&nbsp;&nbsp;import os<br>&nbsp;&nbsp;&nbsp;def zdaemonize():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 首次 fork, 进入后台<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid = os.fork()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid != 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os._exit(0)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 第二次 fork<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid = os.fork()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 父进程, Daemon 管理器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid != 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 启动进程管理器服务器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 这里, manager_server 是假想的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import manager_server<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;manger_server.serve_forever()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 子进程, 启动后台服务<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.system('python server.py')<br><br>进程管理器 manger_server 通常是一个 TCP 服务, 他使用 Unix Socket 与外界交互。<br>这样, pid 文件就变成了 Unix Socket 文件。<br>你通过 Unix Socket (TCP Socket) 接口对进程管理器发送控制指令,<br>比如 'start'、'status' 和 'stop',<br>进程管理器再对他的子进程 (后台守护进程) 发送控制信号, 启动或者关闭守护进程。<br><br>通过进程管理器, 后台进程的控制就和后台进程的运行逻辑分开了。<br><br>zdaemon 也有一个致命缺点, 其过度对象化的设计, 使封装层次失控,<br>加上采用了底层的 Unix Socket, 使其代码量过度膨胀。<br><br>&nbsp;&nbsp;&nbsp;人类能够理解的代码行数是有限制的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;－－《Unix 编程艺术》<br><br>&nbsp;&nbsp;&nbsp;所以 Python 的语法决定了 Python 能够编写出目前最复杂的程序。<br>&nbsp;&nbsp;&nbsp;代码量失控是 Python 的最大敌人, 这说明我们可能正在用 Java 写 Python。<br><br>为此我修改了 zdaemon, 将它实现在 270 行代码中。<br>用 Local XMLRPC Server (Unix Socket) 取代 zdaemon 的 Socket 底层,<br>为我赢得了不少行数。<br><br>同样, 在编写 Local XMLRPC Server 的时候, 再次遇到 Python 标准库 SimpleXMLRPCServer.py<br>的过度封装问题, 有兴趣的话大家可以阅读第三章 Local XMLRPC Server 的实现部分,<br><br>&nbsp;&nbsp;&nbsp;过度向对象实际上就是完全无法重用, 这是一个典型的例子。<br><br>使用 XMLRPC Server 的额外好处,<br>就是让我们可以更方便地增加除了 start、stop、status 这种控制命令。<br><br>&nbsp;&nbsp;&nbsp;daemon = Daemon(...)<br>&nbsp;&nbsp;&nbsp;daemon.register_function(...)<br><br>&nbsp;&nbsp;&nbsp;不过, 额外的控制命令, 通常是不需要的。<br><br>我的 daemon 程序 (daemon.py) 源码放在第三章中,<br>同样, 阅读源码是一件枯燥的事情, 你可以忽略掉第三章。<br>但是第二章是必须理解的。<br><br><br><br><br><br><br>第二章、使用 daemon.py 的通用范例<br>&nbsp;&nbsp;&nbsp;你可以不用修改就用于你的项目<br><br>#!/usr/bin/env python2.5<br># -*- coding: utf-8 -*-<br><br>import os, sys<br>from os import fork<br>from time import sleep<br>from sys import stderr, stdout<br>from socket import error as SocketError<br>from traceback import print_exc<br><br>import schema # 载入配置信息, 还记得《配置文件》一招鲜吗?<br>import pyetc  # ... 要不要复习一下 :)<br><br>from daemon import Daemon, ServerProxy, Fault, \<br>&nbsp;&nbsp;&nbsp;error as DaemonError<br><br>## #<br><br>def usage():<br>&nbsp;&nbsp;&nbsp;print '使用方法: %s start|stop|status' %sys.argv[0]<br><br>def start():<br>&nbsp;&nbsp;&nbsp;# 读取配置文件<br>&nbsp;&nbsp;&nbsp;# demo.conf<br>&nbsp;&nbsp;&nbsp;pyetc.load(schema.ETC('demo.conf'), env=schema.env)<br>&nbsp;&nbsp;&nbsp;conf = schema.config.daemon<br>&nbsp;&nbsp;&nbsp;# ... 请见《配置文件一招鲜》最后一个范例<br><br>&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 创建 Daemon 对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon = Daemon(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address = conf.address, # 进程控制器地址/pid 文件位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;program = conf.program, # 后台进程程序位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;verbose = conf.verbose  # 调试<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器已经启动'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 启动后台进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;daemon(arg1, arg2, ...)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;参数 arg1, arg2 ... 将被用于启动后台进程,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;这里相当于命令行:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;program.py arg1 arg2 ...<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon()<br><br>&nbsp;&nbsp;&nbsp;except DaemonError, msg:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器未启动, 原因是: ', msg<br><br>&nbsp;&nbsp;&nbsp;except:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print_exc(file=stderr)<br><br>def stop():<br>&nbsp;&nbsp;&nbsp;pyetc.load(schema.ETC('demo.conf'), env=schema.env)<br>&nbsp;&nbsp;&nbsp;conf = schema.config.daemon<br><br>&nbsp;&nbsp;&nbsp;# 取得进程控制器<br>&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon = ServerProxy(conf.address)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon.stop()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程已经退出'<br><br>&nbsp;&nbsp;&nbsp;except SocketError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器未启动'<br><br>&nbsp;&nbsp;&nbsp;except Fault:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器已被强制关闭'<br><br>&nbsp;&nbsp;&nbsp;except:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print_exc(file=stderr)<br><br>def status():<br>&nbsp;&nbsp;&nbsp;pyetc.load(schema.ETC('demo.conf'), env=schema.env)<br>&nbsp;&nbsp;&nbsp;conf = schema.config.daemon<br><br>&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon = ServerProxy(conf.address)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;status = daemon.status()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if status == 'running':<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程 "%s" 正在运行' %conf.program<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif status == 'stopped':<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdout.write( ('进程管理器正在运行, 但是进程 "%s" 已经停止, '<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'正在停止进程管理器 ... '<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;) %conf.program )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stop()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器正在运行, 进程状态未知'<br><br>&nbsp;&nbsp;&nbsp;except SocketError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器未启动'<br><br>&nbsp;&nbsp;&nbsp;except:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print_exc(file=stderr)<br><br>## #<br><br># 解析参数<br><br>if len(sys.argv) != 2:<br>&nbsp;&nbsp;&nbsp;usage()<br><br>elif sys.argv[1] == 'start':<br>&nbsp;&nbsp;&nbsp;start()<br><br>elif sys.argv[1] == 'stop':<br>&nbsp;&nbsp;&nbsp;stop()<br><br>elif sys.argv[1] == 'status':<br>&nbsp;&nbsp;&nbsp;status()<br><br>else: usage()<br><br><br><br><br><br><br>第三章、附件: daemon.py<br><br>import os, sys<br>from httplib import HTTP, HTTPConnection<br>from pwd import getpwnam, getpwuid<br>from signal import signal as setsignal, SIGCHLD, SIGTERM<br>from sys import stderr, stdout<br>from urllib import urlopen<br>from SocketServer import UnixStreamServer<br>from socket import socket, error as SocketError, \<br>&nbsp;&nbsp;&nbsp;AF_UNIX, SOCK_STREAM<br>from SimpleXMLRPCServer import SimpleXMLRPCDispatcher, \<br>&nbsp;&nbsp;&nbsp;SimpleXMLRPCRequestHandler, SimpleXMLRPCServer<br>from xmlrpclib import Fault, Transport, dumps as xmlrpc_dumps, \<br>&nbsp;&nbsp;&nbsp;_Method as _XMLRPCMethod, ServerProxy as ServerProxy_N___G<br>from os import execv, chdir, chmod, fork, geteuid, getpid, \<br>&nbsp;&nbsp;&nbsp;kill, setgid, setuid, umask, unlink, waitpid, \<br>&nbsp;&nbsp;&nbsp;error as OSError, WNOHANG<br><br>class error(Exception): pass<br><br>class nul:<br>&nbsp;&nbsp;&nbsp;write = staticmethod(lambda s: None)<br>&nbsp;&nbsp;&nbsp;flush = staticmethod(lambda  : None)<br>&nbsp;&nbsp;&nbsp;read  = staticmethod(lambda n: ''  )<br><br>class UnixStreamXMLRPCServer(UnixStreamServer, SimpleXMLRPCDispatcher):<br>&nbsp;&nbsp;&nbsp;def __init__(self, address, requestHandler=SimpleXMLRPCRequestHandler,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none=False, encoding=None):<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.logRequests = False<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UnixStreamServer.__init__(self, address, requestHandler)<br><br>class Daemon:<br>&nbsp;&nbsp;&nbsp;def __init__(self, **args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address      =           args[ 'address'             ]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none   =       args.get( 'allow_none', True    )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encoding     =       args.get( 'encoding'  , 'utf-8' )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.verbose =       args.get( 'verbose'   , False   )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.stdout  =       args.get( 'stdout'    , nul     )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.stderr  =       args.get( 'stderr'    , nul     )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerProxy(address).ping()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except SocketError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise error, 'Another daemon is already up using socket %s' %repr(address)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if isinstance(address, str):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlink(address)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.manager = UnixStreamXMLRPCServer(address,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none=allow_none, encoding=encoding)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pidfile = address<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.manager = SimpleXMLRPCServer(address,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none=allow_none, encoding=encoding)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pid     = None<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.running = True<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.program       =     args[ 'program'             ]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DaemonizeTools.setuid(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user       = args.get( 'user'      , None    )  )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SignalTools.setsignals(self)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DaemonizeTools.daemonize(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;directory  = args.get( 'directory' , None    ),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;umask      = args.get( 'umask'     , 022     )  )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.register_function = lambda *args: (<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.manager.register_function(*args) )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.register_function(lambda: self.stop()  , 'stop'  )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.register_function(lambda: self.status(), 'status')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.register_function(lambda: True         , 'ping'  )<br><br>&nbsp;&nbsp;&nbsp;def __call__(self, *args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not self.verbose:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DaemonizeTools.close_files(self.stdout, self.stderr)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;del self.stdout, self.stderr<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid = fork()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid != 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pid = pid<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while self.running:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.manager.handle_request()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return pid<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(3, 100):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.close(i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execv(sys.executable, tuple(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[sys.executable, self.program] + list(args) ) )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError, err:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &gt;&gt; stderr, ( 'can\'t exec %r: %s\n'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;% (self.program, err) )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os._exit(127)<br><br>&nbsp;&nbsp;&nbsp;def status(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not self.pid:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'stopped'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 'running'<br><br>&nbsp;&nbsp;&nbsp;def stop(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not self.pid:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.running = False<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if hasattr(self, 'pidfile'):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlink(self.pidfile)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise error, 'no subprocess running'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kill(self.pid, SIGTERM)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.running = False<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if hasattr(self, 'pidfile'):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unlink(self.pidfile)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br><br>class UnixStreamHTTPConnection(HTTPConnection):<br>&nbsp;&nbsp;&nbsp;def connect(self):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.sock = socket(AF_UNIX, SOCK_STREAM)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.sock.connect(self.host)<br><br>class UnixStreamHTTP(HTTP):<br>&nbsp;&nbsp;&nbsp;_connection_class = UnixStreamHTTPConnection<br><br>class UnixStreamTransport(Transport):<br>&nbsp;&nbsp;&nbsp;def make_connection(self, host):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return UnixStreamHTTP(host)<br><br>class UnixStreamServerProxy_NG:<br>&nbsp;&nbsp;&nbsp;def __init__(self, uri, transport=None, encoding=None, verbose=0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none=0, use_datetime=0):<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__host = uri<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__handler = '/RPC2'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not transport:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__transport = UnixStreamTransport(use_datetime=use_datetime)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__encoding = encoding<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__verbose = verbose<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__allow_none = allow_none<br><br>&nbsp;&nbsp;&nbsp;def __request(self, methodname, params):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;request = xmlrpc_dumps(params, methodname, encoding=self.__encoding,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow_none=self.__allow_none)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = self.__transport.request(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.__host, self.__handler, request,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;verbose=self.__verbose )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(response) == 1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = response[0]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return response<br><br>&nbsp;&nbsp;&nbsp;def __getattr__(self, name):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return _XMLRPCMethod(self.__request, name)<br><br>def ServerProxy(address, **args):<br>&nbsp;&nbsp;&nbsp;if isinstance(address, str):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return UnixStreamServerProxy_NG(address, **args)<br><br>&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host, port = address<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host = (host, '127.0.0.1')[host == '0.0.0.0']<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ServerProxy_N___G('http://%s:%d' %(host, port), **args)<br><br>class DaemonizeTools:<br>&nbsp;&nbsp;&nbsp;@staticmethod<br>&nbsp;&nbsp;&nbsp;def setuid(**args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user = args['user']<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if user is None:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uid = int(user)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except ValueError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pwrec = pwd.getpwnam(user)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except KeyError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise error, 'username %r not found' % user<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uid = pwrec[2]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pwrec = pwd.getpwuid(uid)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except KeyError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise error, 'uid %r not found' % user<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;euid = geteuid()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if euid != 0 and euid != uid:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise error, 'only root can change users'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setgid(pwrec[3])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setuid(uid)<br><br>&nbsp;&nbsp;&nbsp;@staticmethod<br>&nbsp;&nbsp;&nbsp;def daemonize(**args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid = fork()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid != 0:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os._exit(0)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if args['directory']:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chdir(args['directory'])<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError, err:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &gt;&gt; stderr, ( 'can\'t chdir into %r: %s'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;% (args['directory'], err) )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &gt;&gt; stderr, ( 'set current directory: %r'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;% args['directory'] )<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.setsid()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;umask(args['umask'])<br><br><br>&nbsp;&nbsp;&nbsp;@staticmethod<br>&nbsp;&nbsp;&nbsp;def close_files(stdout, stderr):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.close(0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.stdin = sys.__stdin__ = nul<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.close(1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.stdout = sys.__stdout__ = stdout<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.close(2)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.stderr = sys.__stderr__ = stderr<br><br>class SignalTools:<br>&nbsp;&nbsp;&nbsp;daemon = None<br><br>&nbsp;&nbsp;&nbsp;@staticmethod<br>&nbsp;&nbsp;&nbsp;def setsignals(daemon):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SignalTools.daemon = daemon<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setsignal(SIGCHLD, SignalTools.sigchild)<br><br>&nbsp;&nbsp;&nbsp;@staticmethod<br>&nbsp;&nbsp;&nbsp;def sigchild(sig, frame):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pid, sts = waitpid(-1, WNOHANG)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if pid == SignalTools.daemon.pid:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SignalTools.daemon.pid = None<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except OSError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return <br></pre></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820072574234114</comments>
    <slash:comments>9</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820072574234114</guid>
    <pubDate>Mon, 5 Mar 2007 19:42:34 +0800</pubDate>
    <dcterms:modified>2011-09-24T15:52:53+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[[Python 一招鲜系列] 配置文件一招鲜]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007236721876</link>
    <description><![CDATA[<div><img title="[Python 一招鲜系列] 配置文件一招鲜 - 沈崴 - 蜻蜓点水 举重若轻"  alt="[Python 一招鲜系列] 配置文件一招鲜 - 沈崴 - 蜻蜓点水 举重若轻"  src="http://aniston.bokee.com/inc/5572f33e020000oi.jpg"  >    <br><br>    <a style="font-size: 12px; color: rgb(102, 102, 102);" rel="nofollow" href="http://www.mangbar.com/bar/docview/bd18e8290f7bfbb9010f7f7f7d6201d9"  >更多精彩请访问 Pythoner 在 Mangbar 的营地</a><br>  <a style="font-size: 12px; color: rgb(102, 102, 102);" rel="nofollow" href="http://www.mangbar.com/task/doclist/5d023b210fa2cc84010fa30b21d00014"  >Python 一招鲜系列文章综览</a><br>    <br><br>    <pre>毫无疑问, 你需要配置文件。据说配置文件能让你的系统变得可定制。<br>让系统变得可定制, 有三大思潮, 这决定了三种配置文件的格式:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 图形界面配置工具。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   微机和 Windows 开始流行之后, 我们的用户再也不是黑客了,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   或许你的用户永远不会打开你的配置文件, 你需要给他一个图形工具, 并且帮他换尿布。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   在人类永远不会阅读配置文件的情况下, 让系统变得更简洁的方法就是使用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   机器最容易理解的格式来存储配置, 通常这是一个二进制文件。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   Pickle 是 Python 中的典型选项。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   几十年后, 有人开始以为使用机器和人都能理解 (或者都不能理解) 的格式是一个好主意, 这样就有了 XML。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   在这里, 我只想告诉大家:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XML 确实是好东西, 但是在绝大多数情况下你其实并不真的需要他。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   而在 Zope/Plone 中, 配置被大规模地保存在 ZODB 数据库中。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   这样就产生了第一种配置文件类型, 他是人类不可读的。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 常规格式的配置文件, 有著名的 httpd.conf 和 INI 等。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   基本上, INI 很弱, 而且 INI 的支持库并没有提供诸如值验证甚至设置变量默认值的功能,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   因此, 除非项目非常小你不应该使用 INI 格式。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;而在任何时候都不使用 INI 格式, 有助于你养成良好的习惯。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   httpd.conf Like 的配置文件, 是配置文件格式的巅峰之作。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   在 Python 中 ZConfig (位于 Zope2/Zope3 中) 提供了对于此种格式的支持。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   我这里有一份入门简介:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://eishn.blog.163.com/blog/static/65231820069310828642/<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   它只是入门介绍, 你需要阅读文档、源码或者范例才能完全了解 ZConfig 的工作方式。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   尽管并不容易, 但是理解 ZConfig 会帮助你快速掌握配置文件的设计哲学。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   常规的配置文件设计和解析过于复杂, 因此你可以仅作了解。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 使用 Python 本身来作为配置文件。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   Why not? 目前有许多 C 程序正在使用 Python 作为配置文件,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   而 Lighttpd 的配置文件也已经八九不离十了。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   这里是一个例子:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# demo_conf.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host = '127.0.0.1'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port = 8080<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# demo.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import demo_conf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print demo_conf.host, demo_conf.port<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   利用 Python 脚本作为配置文件, 在程序实现上简单, 无须格式转换, 而且功能强大。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   这个方案已经开始向传统的配置文件格式宣战。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   最后我修改了原定准备介绍 ZConfig 的计划, 今天着重来介绍这个方案。<br><br><br>下面, 就让我们来设计自己的配置文件格式。<br><br>要搞清楚如何设计一个配置文件, 我们首先需要搞清楚系统中有哪些数据类型是需要配置的,<br>并且弄清楚他们在多大程度上是可以配置的。<br><br>根据经验, 一个系统中可以定制的数据有三种:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. "静态" 数据, 在 C 语言中, 是用 #define 定义的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   此类数据仅在开发期具有动态性, 一旦系统完成开发, 此类数据就是静态的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   此类数据的变化频率最低。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   Python 程序员通常将变量名大写, 并且放在 "config.py" 中, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   通过 import config 导入使用。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. "默认" 配置, 这是项目配置部分最大的乱源。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   默认配置是一种用户可以在配置文件中修改的数据, 他们不是必须的, 他们有默认值。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   你很快就会发现许多 "默认" 配置实际上用户永远不会去修改他,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   在这种情况下, 这些默认配置实际上是上面所说的 "静态" 数据, 应该写入 "config.py"。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   而另一些则是常用配置, 只是带有默认值而已, 这些数据应该写入 "etc" 配置文件中。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   显而易见, 一个变量不能同时存在于 config.py 和 etc 配置文件中。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   问题在于搞清楚一个变量是属于 "静态" 数据还是 "默认" 配置是困难和不确定的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   这最终导致你的配置文件定义朝令夕改, 而你的项目则风雨飘摇。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 配置项, 毫无疑义地应该放在配置文件中。在系统投入使用后, 这是变化频率最高的数据类型。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   在配置文件中, 你又将面临另一大挑战, 就是变量类型验证。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   变量类型验证之所以讨厌, 就是因为你要同时判断一个配置变量是否存在、类型是否匹配或者是否越界,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   并且是否给以默认值。最后最糟糕的是你还需要回答一个问题:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值是否需要写在配置文件中。<br><br>为了解决所有这些问题, 人们发明了 Schema。<br>和传统配置文件不同, 使用 Python 作为配置文件, Schema 的编写具有相当大的灵活性。<br>而且 Schema 能帮助你把 Python 格式的配置文件变得更加可读。<br>下面我就演示一下在 Python 作为配置文件格式时 Schema 的写法。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/ETC/demo_conf.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置文件<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import schema<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Server(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host = '127.0.0.1',<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port = 8080<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/ETC/schema.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config = {}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def Server(**args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config['host'] = args.get('host', '0.0.0.0') # 有默认值<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config['port'] = int(args.get('port', 8080)) # 带验证<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except ValueError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ValueError, '你必须是整型'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/BIN/demo.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import sys<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.path.append(r'/PATH/TO/ETC')<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import schema, demo_conf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print schema.config['host'], schema.config['port']<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br>好了, 接下来我们需要把 demo_conf.py 变得更像一个配置文件,<br>因为 "import schema" 不像是一个配置文件中应该有的东西, 我们要让 "Server" 成为预导入的变量。<br>最后, 我们还要把 demo_conf.py 变成 demo.conf。<br><br>这样继 PyQt4 一招鲜之后, 我们又要再次接触到自定义导入技术。<br>这次我们将使用类似的技术, 也是一个导入钩子 (hook), 不同的是, 这次我们不将钩子挂接到 Python 解释器。<br><br><br>################################################################## # -BOF-<br># pyetc.py<br><br># Python 格式的配置文件支持库<br>#<br>import sys, os.path<br><br>Module = type(sys) # 故技重演<br>modules = {}       # 缓存已经导入的 etc (配置) 模块<br><br><br># 导入任意符合 Python 语法的文件<br># 用法:<br># module = pyetc.load(完整文件路径并包含扩展名, 预载入变量, 自定义返回模块类型)<br>#<br>def load(fullpath, env={}, module=Module):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;code = open(fullpath).read()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except IOError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ImportError, 'No module named  %s' %fullpath<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename = os.path.basename(fullpath)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return modules[filename]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except KeyError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = module(filename)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__module_class__ = module<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__file__ = fullpath<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__dict__.update(env)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec compile(code, filename, 'exec') in m.__dict__<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modules[filename] = m<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m<br><br># 移除已经导入的模块<br># 用法:<br># module = unload(module)<br>#<br>def unload(m):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename = os.path.basename(m.__file__)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;del modules[filename]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return None<br><br># 重新导入模块<br># 用法:<br># module = pyetc.reload(module)<br>#<br>def reload(m):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fullpath = m.__file__<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;code = open(fullpath).read()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except IOError:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ImportError, 'No module named  %s' %fullpath<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env = m.__dict__<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;module_class = m.__module_class__<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filename = os.path.basename(fullpath)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = module_class(filename)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__file__ = fullpath<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__dict__.update(env)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.__module_class__ = module_class<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec compile(code, filename, 'exec') in m.__dict__<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modules[filename] = m<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m<br><br>################################################################## # -EOF-<br><br><br>下面就让我们来尝试一下。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/ETC/demo.conf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置文件<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host = '127.0.0.1'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port = 8080<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# demo.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import pyetc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conf = pyetc.load(r'/PATH/TO/ETC/demo.conf')<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print conf.host, conf.port<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br>最后是一个较为完整的例子:<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/ETC/demo.conf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 服务器选项<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Server(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port = 8080 # 监听 8080 端口<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 进程控制器选项<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Daemon(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 使用 Socket 发布进程控制器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address = ('0.0.0.0', 10080),<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 使用文件发布进程控制器<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address = var('demo.pid'),<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 服务器进程<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;program = bin('server.py'),<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 调试开关<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;verbose = True<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/BIN/schema.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 路径工具<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import sys, os.path<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DEMO_HOME = r'/PATH/TO/DEMO'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ETC = lambda filename: os.path.join(DEMO_HOME, 'etc', filename)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VAR = lambda filename: os.path.join(DEMO_HOME, 'var', filename)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BIN = lambda filename: os.path.join(DEMO_HOME, 'bin', filename)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Config(dict):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 可以像属性一样访问字典的 Key<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dict.key 等同于 dict[key]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def __getattr__(self, name):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self[name]<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置默认值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config = Config({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'server': Config({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'port': 8080 # 服务器使用 8080 端口<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}),<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'daemon': Config({<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'address': VAR('daemon.pid'), # pid 文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'program': BIN('server.py' ), # 服务器程序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'verbose': True<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置接口 (不带验证)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def Server(**args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config['server'].update(args)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def Daemon(**args):<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config['daemon'].update(args)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 配置文件 "demo.conf" 可见的变量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env = {'Server': Server, 'Daemon': Daemon,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'etc': ETC, 'var': VAR, 'bin': BIN}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br><br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# /PATH/TO/BIN/demo.py<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 这里启动一个 Daemon 管理器,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 注意: 这里的 daemon.py 是一个假想库, 无须理会<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;import pyetc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from daemon import Daemon<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def start():<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 读取配置文件<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# demo.conf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pyetc.load(schema.ETC('demo.conf'), env=schema.env)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conf = schema.config.daemon<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 创建 Daemon 对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon = Daemon(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;address = conf.address, # 进程控制器地址/pid 文件位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;program = conf.program, # 后台进程程序位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;verbose = conf.verbose  # 调试<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '进程管理器已经启动'<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;daemon()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if __name__ == '__main__':<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start()<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# -EOF-<br></pre></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007236721876</comments>
    <slash:comments>7</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007236721876</guid>
    <pubDate>Sat, 3 Mar 2007 18:07:21 +0800</pubDate>
    <dcterms:modified>2011-09-23T21:16:45+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[笔记本无耻地换成 Beryl 了]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820071137373160</link>
    <description><![CDATA[<div>这里直接借用 Youtube 上玩家 djpatterson 的视频了。哦, Beryl 看上去完全没有占用什么资源, 各位放心大胆地用吧!<br><br>  <center><embed allowNetworking="internal" style="display: block;" allowScriptAccess="never" loop="0" invokeurls="false" src="http://www.youtube.com/v/cFBWmkXbA4c" type="application/x-shockwave-flash" wmode="transparent"  ></center><br>  <a style="font-size: 10px; color: rgb(136, 136, 136);" rel="nofollow" href="http://www.youtube.com/watch?v=cFBWmkXbA4c"  >http://www.youtube.com/watch?v=cFBWmkXbA4c</a><br><br><span style="color: rgb(255, 0, 0);"  >  把效果设置为 "所有效果使用随机" 看起来是个好主意 !</span><br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820071137373160</comments>
    <slash:comments>3</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820071137373160</guid>
    <pubDate>Tue, 13 Feb 2007 19:55:41 +0800</pubDate>
    <dcterms:modified>2011-09-25T16:33:26+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Eurasia3 高并发模型逐渐成型]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007030349490</link>
    <description><![CDATA[<div><img style="width: 559px; height: 443px;" src="http://eishn.plonespace.net/images/e3om0.jpg"><br><br>从 CherryPy3 开始, 我从 WSGI 的反叛者转变为实践者。我欣赏 web.py 的精简, 但是我愿意作得更聪明些。<br>经过两周的实践, 实验性的模型已经初步展现出来, 当然目前还远未成熟。经过后续更为深入的设计, 第一个版本将会出现在 SourceForge 上。<br><br>Eurasia3 参数:<br>1. 在普通 PC 上可以达到每秒 2000 个以上的 CGI 响应, 5 － 6 倍于 CherryPy3。<br>2. 应用逻辑使用协作线程模型 (yield), 简化开发, 每秒可以进行百万次线程调度。<br>3. Comet 特性, 服务器和客户端双向通信, 双向线程调度器 (Scheduler)。<br>4. 可彻底降解的 JavaScript 客户端模板。<br>5. JavaScript 控制下的 Flash 特效 (计划中)。<br>6. 基于 Plone 的后台数据库及后台管理 (PloneDBMS)。<br></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007030349490</comments>
    <slash:comments>4</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007030349490</guid>
    <pubDate>Tue, 30 Jan 2007 15:04:09 +0800</pubDate>
    <dcterms:modified>2007-01-30T15:06:28+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[广州徒步旅游江北暴走攻略]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007030111035948</link>
    <description><![CDATA[<div><img style="width: 683px; height: 512px;" src="http://antredefer.free.fr/images_fichiers/starcraft/starcraft-01.jpg"><br><br>来广州三年了, 活动范围仅限天河区, 所以俺改变了。我计划横穿广州, 因此我制定并实施了两天的暴走计划。<br><br><img src="http://eishn.plonespace.net/images/gbbz12.jpg"><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第一天, 中山环市线 (天河科韵路→火车站)</span></font><br>级别要求: 入门级暴走玩家<br>耗时: 2-3 倍步行速度, 两小时至两个半小时行程<br><br>起点站天河棠下 (科韵路)[H]<span> → </span>沿中山大道西天河路[亨] <span>→ </span>途径天河公园[景] <span>→ </span>石牌[食] <span>→ </span>师大暨大[景] <span>→</span> 岗顶[商] <span>→</span> 广州体育场[景] <span>→</span> 天河城[商] <span>→</span> 东山广场[商] <span>→ </span>后段经过环市东路[通] <span>→</span> 环市西路[承] <span>→</span> 到终点广州火车站[亨]。<br><br>因为没有用地图做计划, 后段环市中路至环市西路较为荒凉。纯属暴走之乐耳。从火车站坐车返程, 将沿原路返回, 驱车再游堪称爽极。<br><br>好了, 练手就练到这里吧。<br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第二天, 黄埔中山线 (员村四横路→黄沙大道)</span></font><br>级别要求: 中级暴走玩家<br>路程: 2-2.5 倍步行速度, 六至八小时行程<br><br>起点站天河员村四横路[H]<span> → 沿黄埔大道中[亨] </span><span> → 途径天河公园[景] </span><span> → 暨南大学[达] </span><span> → 马场[驱] </span><span> → 石牌[食] </span><span> → 经黄埔大道西至东风东路[通] </span><span> → 广东工业大学[业] </span><span> → 烈士陵园[陵] </span><span> → 中山纪念堂[堂] </span><span> → 至东风西路折往海珠北路[变]</span><span> → 状元坊[商] </span><span>→ 海珠广场[趋] </span><span>→ 现在我们看到珠江了[珠] </span><span>→ 往北京路者北[折] </span><span>→ 北京路步行街[商] </span><span>→ 在文明路吃晚饭[食] </span><span>→ 广东省博物馆[博] </span><span>→ 经文德路返回中山四路[返] </span><span>→ 中山五路中山六路中山七路[畅] </span><span>→ 陈家祠[景] </span><span>→ 上下九步行街[商] </span><span>→ 经过长寿路到荔枝湾路[趋] </span><span>→ 至如意坊终点站[亨]<br><br>这次暴走经过了两个公交车全程, 故</span><span>返程须经东山转车, 坐完一个起点站和终点站。本线娱乐性相当高, 途径景点极多, 推荐中午稍作休息即出发, 这样可以欣赏到傍晚的珠江江景和</span><span>上下九</span><span>北京路夜景。本次步行横穿天河、东山、越秀、荔湾四区, 可以看到各地不同的景致。<br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">旅游线路</span></font><br>经过两天试探, 我得到了一条以天河科韵路为起点北京路为目的地的最佳的旅游线路。<br>步行经中山大道至天河城转中山五路至上下九北京路游珠江返。公交则乘科韵路 541 至博物馆下 (地铁由陈家祠或公园前下)。总体而言, 沿地铁线步行是比较明智的, 因为你总能得到比较繁华的地方。</span><span></span><span></span><span><br></span></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007030111035948</comments>
    <slash:comments>12</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007030111035948</guid>
    <pubDate>Tue, 30 Jan 2007 12:32:19 +0800</pubDate>
    <dcterms:modified>2007-01-30T14:26:37+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[秒杀技 Python JSON Encoder]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820070181041204</link>
    <description><![CDATA[<div><a target="_blank" href="http://eishn.blog.163.com/album/prevPhoto.do?photoId=_fks_67dyiWk0oDqEPpw0iyURiw=="><img src="http://img.blog.163.com/photo/LTeh07zZWgLjS-3Q2UssUA==/4020307092358384149.jpg"></a><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">"Json 不需要 decoder", 在第一次见到 Json 的时候我如是想到</span></font><br><br>如果 Json decoder 对宿主有安全隐患, 那么是可以抛弃的, 服务器毕竟不是客户机。<br>如果我们能让 Json decoder 完全安全, 我们已经损失了太多效率, 服务器毕竟不是客户机。<br>所以, Json 不需要 decoder。<br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">"Python 不需要 Json 支持库", 今天我如是想到</span></font><br><br>只要解决了字符串 escape 问题, 任何人都可以手工生成 Json 报文, 而手工生成 Json, 不超过一行代码。<br>在 Python 中, 不超过一行代码, 就是原子操作, 不需要封装, 比如正则表达式。<br>这时, 用户能够自己控制系统粒度。在字符串 escape 问题解决的前提下, 随手开发一个 Json 库也是几分钟的事情。<br>在 Python 中, 几分钟可以搞定的, 不需要封装, 因为只有程序库的作者最熟悉程序库, 既然用户的学习成本大于编写成本那么就让用户去写。<br>所以, Python 不需要 Json 支持库。<br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">秒杀技, Python JSON Encoder</span></font><br><br>json = lambda s, encoding = sys.getdefaultencoding(): repr(unicode(s, encoding))[1:]<br>现在, 我可以在没有提供 Json 支持的 Python 免费主机上建立 Json 应用了。<br><br style="font-style: italic;"><span style="font-style: italic; font-weight: bold;">补注:</span><br style="font-style: italic;"><span style="font-style: italic;">据说最后那行代码很容易令人摸不着头脑, 你不妨把 json() 换成 (string) escape() 来理解。</span><br style="font-style: italic;"><span style="font-style: italic;">如果你用 escape 来定义这行代码, 你只能得到 escape;</span><br style="font-style: italic;"><span style="font-style: italic;">如果你用 json 来命名, 你得到了 JSON。</span></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820070181041204</comments>
    <slash:comments>10</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820070181041204</guid>
    <pubDate>Thu, 18 Jan 2007 11:17:15 +0800</pubDate>
    <dcterms:modified>2007-04-02T00:01:54+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Python 历史书·GUI 部]]></title>	
    <link>http://eishn.blog.163.com/blog/static/65231820070662457738</link>
    <description><![CDATA[<div><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第一章、世界的形成</span></font><br><br>太初, 只是一片混沌。大师图灵沉睡在这片漫无边际的黑暗中。先知书《编程之道》说, 有一天, 大师梦见自己变成了一台机器, 浑然不知是机器梦见了自己还是自己梦见了机器。他醒来, 天地就分开了。无数巨大的计算机从天而降, 秩序由此建立。<br><br>又过了一千年, 第一批人类从原始的混沌之梦中醒来。没有人知道大师的去处, 他们好奇地围绕在那些巨大的机器周围, 他们相信这些机器是世界秩序的源泉并奉之为神明。太古的机器也许诺给他们无穷的力量, 帮助他们把世界变得更为繁荣。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第二章、诸神的黄昏</span></font><br><br>九百年后, 当世界变得足够繁荣的时候, 那些来自于远古的巨大机器就离开了。这时第二批人类才从混沌中醒来, 他们对过去一无所知, 以为这个世界本应如此。他们用泥土和金属塑造了自己的偶像, 取名微机, 并顶礼膜拜。<br><br>他们对微机的狂热, 让最初的圣人们非常忧虑, 又感到无能为力。在意识到人类将不可避免地滑向混乱的深渊之后, 他们建立了自己的神殿, 将最后的信仰和古老的力量保护起来。异教徒嘲笑他们, 并向他们发动了圣战。那些异教徒人数众多, 守卫阵营也发生了叛变和分裂, 圣人们不能抵抗, 他们离开神殿, 在世界各地建立了诸多被称为学院的据点, 来自于太古的神圣力量在那里得以保存下来。<br><br>之后, 在人类的狂热中, 世界经历了一段混乱不堪的历史, 在战火中诞生了许多人类最为古老的王国。一切都平静下来, 世界被微机统治。但是先知不屑地说, 世界其实仍然运转在太古的神力之下, 人类被自己的幻觉所欺骗。在合适的时候, 诸神会回来修复大地的伤痕。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第三章、新大陆的诞生</span></font><br><br>又过了八十年, 关于新大陆的传言开始流传。两年后, 学院 MIT 开始向海外探险, 他们最终发现了一块全新的大陆。这是一块神秘的未知之地, 所以他们把它命名为 X。不久之后, 贪婪的人类蜂拥而至, 传说在那里他们看到了巨大的彩色云彩, 于是, 人们将新大陆重新命名为 GUI。<br><br>为了统治这块新生的大陆, 古老的王国 IBM 和 HP 组成了 Motif 联军和 Sun 帝国为首的 Openlook 联军在那里进行了激烈的争夺。他们全然不知一股来自于宇宙深处, 令人难以置信的邪恶力量已经悄然来到这个世界。它将燃烧这片新大陆, 并将恐怖播向整个世界。恶魔贪婪的目光注视着人类的征伐, 野蛮和仇恨的力量让它迅速成长。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第四章、Redmond 帝国崛起</span></font><br><br>IBM 和 HP 的 Motif 联军终于悲剧性地取得了最终的胜利。但是, 他们发现一个叫做 Redmond 的邪教组织很快便让他们的努力付之东流。人们无法忍受 Motif 阵营的高额赋税, 纷纷拜倒在 Redmond 的诱惑之下。恶魔首领比尔答应让人们过上更为富庶的生活, 并分享他们在新大陆的权力。只有少数人看穿了 Redmond 的邪恶本质, 他的承诺是以人们放弃自由为代价的。通过使用邪恶的催眠魔法, Redmond 让人们生活在幻境下, 敢于抵抗 Redmond 的部队纷纷放下武器, 成为没有思想唯命是从的附庸。当人们觉醒时, 一切已经太晚了。<br><br>IBM 帝国受到了 Redmond 的迷惑和欺骗, Redmond 说服他一起来统治这块大陆。最后 Redmond 背弃了盟约, 不费吹灰之力便击败了 IBM。旧大陆的远征军只得黯然退出 GUI 世界。新大陆上仅存的智者则在 Redmond 帝国之外继续抵抗以维护他们传统的荣耀, 这是新大陆少数没有被 Redmond 侵蚀的净土, 那里有着一个古老的名字, X。<br><br>与此同时, 远古大陆上的人们正在忙于互相征战, 全然不知遥远的新大陆上 Redmond 帝国燃烧的魔爪正在伸向他们。Redmond 志得意满, 但是比尔万万没有想到, 拥有远古神力的圣人集团已经悄然插手此事, 那些正义的骑士在黑暗之中遁形, 没有人知道他们的去向和使命。他们被后人称为黑客。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第五章、世界的分裂</span></font><br><br>诸神离开时留下了一件名为 Unix 的神器。它具有让世界重归平衡的魔力, 古代圣人们小心地保守着这个秘密。在微机圣战中, 圣人集团发生了分裂, 神器从此分成几块散落到世界各地。<br><br>随着时间的推移, 人们开始传说, 得到 Unix 就能取得整个世界。为了争夺 Unix, 几百年间大国纷争不断。最后 Unix 的碎片落入了几个大国之手。<br><br>直到有一天, Redmond 的邪恶法师打开了通往古大陆的魔法通道, 恶魔们从窗口中呼啸而出, 所有人才发现世界真正的危险已经来到。<br><br>先知 Stallman 早已警告过人们即将到来的一切, 只有释放 Unix 的法力, 才能拯救人类免于灾难。世俗王国不以为然, 只有黑客们意识到事态的严重性。因为 Unix 已经失散, 所以黑客们将远古神力注入一个新的容器。在危急关头, 英雄 Linus 赶到, 他吟唱着早已失传的祷文将神器高高举起, 来自于远古的愤怒瞬间穿越陆地和天空, 恶魔们落荒而逃, 撤回 GUI 世界。<br><br>Unix 重生了。<br><br>出于对 Unix 的恐惧, Redmond 的法师祭出黑暗的 F.U.D 法术, 巨大的阴云笼罩在 Redmond 帝国的周围, 严密地防守着神圣力量的侵入。从此世界分成了两个部分, 在 Unix 保护下的远古大陆, 以及 Redmond 魔爪下的 GUI 世界。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第六章、Trolltech 的建立</span></font><br><br>回到 1992 年, GUI 世界不满于 Motif 联军统治又不愿和 Redmond 妥协的人们组成了 Qt 阵营。两年后他们建立了自己的首都 Trolltech。不久之后, 远征军被击败, Redmond 横扫了整片大陆。Qt 阵营一直保持着中立, 这使得 Trolltech 免于战火, 屹立至今。<br><br>这时, 关于世界的拯救者, 黑客们已经潜入 GUI 世界的传言已经愈演愈烈。许多游击派别的出现似乎证明了这一点。<br><br>1996 年, 贤者 Matthias Ettrich 出现在 Trolltech。他说服 X 之地上的游击部队和 Qt 阵营一起建立了强大的 KDE 联军。随着 KDE 部队的迅速壮大, 黑客们开始试图说服 Trolltech 带领 KDE 联军向 Redmond 帝国宣战, 为 GUI 世界重获自由而战。<br><br>但是 Trolltech 仍然保持中立, 这让部分狂热的黑客愤怒, 他们相信 Trolltech 已经受到了 Redmond 的腐蚀。失望的黑客 Miguel De Icazza 建立了 GNOME 联军, 公然向 KDE 宣战。一场争夺 X 之地的圣战就此开始, 至今已经持续了整整十年。<br><br><br><font style="font-family: 黑体;" size="3"><span style="font-weight: bold;">第七章、PyQt4</span></font><br><br>在故事的结局, Trolltech 终于被说服, Qt 部队愿意加入自由阵营。KDE 和 GNOME 联军携手向 Redmond 帝国发起了冲击, 横扫整片大陆。Redmond 帝国内, 人们开始觉醒, 纷纷起来为自由而战。Redmond 帝国轰然倒塌, 只剩下垂死挣扎的余党。<br><br>在最后的阶段, 远方守护着 Unix 魔力的 Python 阵营也加入进来。他们和 Qt 部队会师, 这些最为温和的战士已经在思索着一切结束之后, 将如何去治愈世界的伤痕 ……<br><br>2007 年, 游侠沈崴经过 Python 在 Mangbar 的营地, 贤者 Tomz 和 Andelf 邀请他向众人叙说他在各地的见闻, 于是便有了这本历史书。</div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/65231820070662457738</comments>
    <slash:comments>12</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/65231820070662457738</guid>
    <pubDate>Sat, 6 Jan 2007 18:24:57 +0800</pubDate>
    <dcterms:modified>2007-01-06T18:24:57+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[[授权直播] 比尔·云风传奇 (1、2)]]></title>	
    <link>http://eishn.blog.163.com/blog/static/6523182007040112090</link>
    <description><![CDATA[<div><p style="font-weight: bold; font-family: 黑体;"  ><font size="3"  >第一掌、比尔·云风刚出生便会说话</font></p><span><p><span>比尔·云风刚出生便会说话</span>, 邻居描述, 刚落地时他就向东南方向走了七步, 每走一步地上就出现一个 "at" 符号，只见他七步之后, 伸左手指天, 伸右手指地, 开口说道: " 2D/3D 唯我独尊" ……<br></p><p style="font-weight: bold; font-family: 黑体;"  ><font size="3"  >第二张、《徐庶走马荐比尔，刘玄德三顾茅庐》</font></p><p>徐庶: "主公不必难过, 五步之内必有芳草, 远来的和尚, 未必念得了真经, 蜀国如要上市, 庶愿保举一人"。</p><p>刘备: "知  道是你好朋友诸葛孔明, 这人人品不行, 我面试过。他要我联伊抗美, 与基地组织共出奇兵占领 Nasdaq 机房, 奉股市而令不臣, 控制所有上市公司。靠! 备乃  仁义之团队, 向来讲求信誉, 强调共赢, 怎忍心做此等伤天害理之事"。</p><p>徐庶: "是是是, 主公是讲求信誉, 力主双赢的仁义团队, 但是我要推荐的另有其人"。</p><p>"哦, 应届生? 现在何处? 开口多少?", "这人复姓比尔, 双名云风, 家住荆州长沙郡, 现在幽州雪碧九游戏当差。"。</p><p>备: "哦, 没听过"。</p><p>庶: "这位好汉十  八般语言门门精通, 上能构架操作系统; 下能设计嵌入芯片!"。</p><p>备: "有这种怪人?"。</p><p>庶: "不当如此, 此人左手提一百二十斤混铁鼠标, 右手抱三百五十斤工  学键盘, 竞争对手虽有千军万马, 近不得他办公桌一步! 三十六小时持续编码依旧气定神闲, 体力耐力无人能及"<span>。</span></p><p><span></span>刘备: "赞! 是块加班的好料, 想起来了, 水  镜先生也向我推荐过, 说他 '手握设计无数种, 胸中代码千万行' 他在雪碧九拿多少?"。</p><p>徐庶: "XXX"。</p><p>刘备: "大伯如何?"。</p><p>徐庶: "至少再多 500 元"。</p><p>  刘备: "恩, 只要他证明他的能力, 再多 600 都不在乎, 我们向来尊重人才, QQ、MSN、Mail 统统给我"。</p><p>徐庶: "听说他最近 ADSL 欠费, 手机停  机, 就连 EMail 都发不出去, 主公要见, 恐怕只有亲自前往"。</p><p>刘备: "如此说来，备当前往看看" ……</p><p><br><span style="font-style: italic; font-weight: bold;"  >《比尔云风传奇》由林爷正版授权连载, </span><a style="font-style: italic; font-weight: bold;" target="_blank" rel="nofollow" href="http://www.joynb.net/blog/index.php"  >欢迎访问 "林爷 Inside" 网站</a> (http://www.joynb.net/blog/)。<br></p></span></div>]]></description>
	    <author><![CDATA[沈崴]]></author>
	    <comments>http://eishn.blog.163.com/blog/static/6523182007040112090</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://eishn.blog.163.com/blog/static/6523182007040112090</guid>
    <pubDate>Thu, 4 Jan 2007 12:11:20 +0800</pubDate>
    <dcterms:modified>2011-09-24T23:11:55+08:00</dcterms:modified>
  </item>    
 </channel>
</rss>
