﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Thronds</title><link>http://www.cppblog.com/thronds/</link><description>一问你会什么
二问你做出过什么
三问你为了什么</description><language>zh-cn</language><lastBuildDate>Thu, 16 Apr 2026 17:12:30 GMT</lastBuildDate><pubDate>Thu, 16 Apr 2026 17:12:30 GMT</pubDate><ttl>60</ttl><item><title>终端VI支持gb2312[转]--字符编码的纠结</title><link>http://www.cppblog.com/thronds/archive/2009/06/02/86497.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Mon, 01 Jun 2009 18:23:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/06/02/86497.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/86497.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/06/02/86497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/86497.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/86497.html</trackback:ping><description><![CDATA[<br>
<div id=art style="MARGIN: 15px; LINE-HEIGHT: 150%" width="560"><span class=postbody>修改.vimrc文件，让其支持 gb2312就行</span><br>"设定文件编码类型，彻底解决中文编码问题 <br>let &amp;termencoding=&amp;encoding <br>set fileencodings=utf-8,gbk,ucs-bom,cp936 <br><span class=postbody><br>略微查了一下.vimrc中添加内容的含意，这篇文章有相关解释。 <br><a href="http://blog.dawnh.net/comment.php?type=trackback&amp;entry_id=59" target=_blank><u><font color=#0000ff>http://blog.dawnh.net/comment.php?type=trackback&amp;entry_id=59</font></u></a> <br>内容如下： <br><br>vim中编辑不同编码的文件时需要注意的一些地方 <br>此文讲解的是vim编辑多字节编码文档（中文）所要了解的一些基础知识，注意其没有涉及gvim，纯指字符终端下的vim。 <br>vim编码方面的基础知识： <br><br>1，存在3个变量： <br>encoding----该选项使用于缓冲的文本(你正在编辑的文件)，寄存器，Vim 脚本文件等等。你可以把 'encoding' 选项当作是对 Vim 内部运行机制的设定。 <br>fileencoding----该选项是vim写入文件时采用的编码类型。 <br>termencoding----该选项代表输出到客户终端（Term）采用的编码类型。 <br>2，此3个变量的默认值： <br>encoding----与系统当前locale相同，所以编辑文件的时候要考虑当前locale，否则要设置的东西就比较多了。 <br>fileencoding----vim打开文件时自动辨认其编码，fileencoding就为辨认的值。为空则保存文件时采用encoding的编码，如果没有修改encoding，那值就是系统当前locale了。 <br>termencoding----默认空值，也就是输出到终端不进行编码转换。 <br><br>由此可见，编辑不同编码文件需要注意的地方不仅仅是这3个变量，还有系统当前locale和、文件本身编码以及自动编码识别、客户运行vim的终端所使用的编码类型3个关键点，这3个关键点影响着3个变量的设定。 <br>如果有人问：为什么我用vim打开中文文档的时候出现乱码？ <br>答案是不确定的，原因上面已经讲了，不搞清楚这3个关键点和这3个变量的设定值，出现乱码是正常的，倒是不出现乱码那反倒是凑巧的。 <br><br>再来看一下常见情况下这三个关键点的值以及在这种情况下这3个变量的值： <br>1，locale----目前大部分Linux系统已经将utf-8作为默认locale了，不过也有可能不是，例如有些系统使用中文locale zh_CN.GB18030。在locale为utf-8的情况下，启动vim后encoding将会设置为utf-8，这是兼容性最好的方式，因为内部处理使用utf-8的话，无论外部存储编码为何都可以进行无缺损转换。locale决定了vim内部处理数据的编码，也就是encoding。 <br>2，文件的编码以及自动编码识别----这方面牵扯到各种编码的规则，就不一一细讲了。但需要明白的是，文件编码类型并不是保存在文件内的，也就是说没有任何描述性的字段来记录文档是何种编码类型的。因此我们在编辑文档的时候，要么必须知道这文档保存时是以什么编码保存的，要么通过另外的一些手段来断定编码类型，这另外的手段，就是通过某些编码的码表特征来断定，例如每个字符占用的字节数，每个字符的ascii值是否都大于某个字段来断定这个文件属于何种编码。这种方式vim也使用了，这就是vim的自动编码识别机制了。但这种机制由于编码各式各样，不可能每种编码都有显著的特征来辨别，所以是不可能 100%准确的。对于我们GB2312编码，由于其中文是使用了2个acsii值高于127的字符组成汉字字符的，因此不可能把gb2312编码的文件与 latin1编码区分开来，因此自动识别编码的机制对于gb2312是不成功的，它只会将文件辨识为latin1编码。此问题同样出现在gbk，big5 上等。因此我们在编辑此类文档时，需要手工设定encoding和fileencoding。如果文档编码为utf-8时，一般vim都能自动识别正确的编码。 <br><br>3，客户运行vim的终端所使用的编码类型----同第二条一样，这也是一个比较难以断定的关键点。第二个关键点决定着从文件读取内容和写入内容到文件时使用的编码，而此关键点则决定vim输出内容到终端时使用的编码，如果此编码类型和终端认为它收到的数据的编码类型不同，则又会产生乱码问题。在 linux本地X环境下，一般终端都认为其接收的数据的编码类型和系统locale类型相符，因此不需关心此方面是否存在问题。但如果牵涉到远程终端，例如ssh登录服务器，则问题就有可能出现了。例如从1台locale为GB2310的系统（称作客户机）ssh到locale为utf-8的系统（称作服务器）并开启vim编辑文档，在不加任何改动的情况下，服务器返回的数据为utf-8的，但客户机认为服务器返回的数据是gb2312的，按照 gb2312来解释数据，则肯定就是乱码了，这时就需要设置termencoding为gb2312来解决这个问题。此问题更多出现在我们的 windows desktop机远程ssh登录服务器的情况下，这里牵扯到不同系统的编码转换问题。所以又与windows本身以及ssh客户端有很大相关性。在 windows下存在两种编码类型的软件，一种是本身就为unicode编码方式编写的软件，一种是ansi软件，也就是程序处理数据直接采用字节流，不关心编码。前一种程序可以在任何语言的windows上正确显示多国语言，而后一种则编写在何种语言的系统上则只能在何种语言的系统上显示正确的文字。对于这两种类型的程序，我们需要区别对待。以ssh客户端为例，我们使用的putty是unicode软件，而secure CRT则是ansi 软件。对于前者，我们要正确处理中文，只要保证vim输出到终端的编码为utf-8即可，就是termencoding=utf-8。但对于后者，一方面我们要确认我们的windows系统默认代码页为cp936（中文windows默认值），另一方面要确认vim设置的termencoding= cp936。 <br><br>最后来看看处理中文文档最典型的几种情况和设置方式： <br><br>1，系统locale是utf-8（很多linux系统默认的locale形式），编辑的文档是GB2312或GBK形式的（Windows记事本默认保存形式，大部分编辑器也默认保存为这个形式，所以最常见），终端类型utf-8（也就是假定客户端是putty类的unicode软件） <br>则vim打开文档后，encoding=utf-8（locale决定的），fileencoding=latin1（自动编码判断机制不准导致的），termencoding=空（默认无需转换term编码），显示文件为乱码。 <br>解决方案1：首先要修正fileencoding为cp936或者euc-cn（二者一样的，只不过叫法不同），注意修正的方法不是:set fileencoding=cp936，这只是将文件保存为cp936，正确的方法是重新以cp936的编码方式加载文件为:edit ++enc=cp936，可以简写为:e ++enc=cp936。 <br>解决方案2：临时改变vim运行的locale环境，方法是以LANG=zh_CN vim abc.txt的方式来启动vim，则此时encoding=euc-cn（locale决定的），fileencoding=空（此locale下文件编码自动判别功能不启用，所以fileencoding为文件本身编码方式不变，也就是euc-cn），termencoding=空（默认值，为空则等于encoding）此时还是乱码的，因为我们的ssh终端认为接受的数据为utf-8，但vim发送数据为euc-cn，所以还是不对。此时再用命令: set termencoding=utf-8将终端数据输出为utf-8，则显示正常。 <br><br>2，情况与1基本相同，只是使用的ssh软件为secure CRT类ansi类软件。 <br><br>vim打开文档后，encoding=utf-8（locale决定的），fileencoding=latin1（自动编码判断机制不准导致的），termencoding=空（默认无需转换term编码），显示文件为乱码。 <br><br>解决方案1：首先要保证运行secure CRT的windows机器的默认代码页为CP936，这一点中文windows已经是默认设置了。其他的与上面方案1相同，只是要增加一步，:set termencoding=cp936 <br><br>解决方案2：与上面方案2类似，不过最后一步修改termencoding省略即可，在此情况下需要的修改最少，只要以locale为zh_CN 开启 vim，则encoding=euc-cn，fileencoding和termencoding都为空即为encoding的值，是最理想的一种情况。 <br><br><br>可见理解这3个关键点和3个参数的意义，对于编码问题有很大助力，以后就可以随心所欲的处理文档了，同时不仅仅是应用于vim，在其他需要编码转换的环境里，都可以应用类似的思路来处理问题解决问题。</span> </div>
<a href="http://blog.chinaunix.net/u/8111/showart_498103.html">http://blog.chinaunix.net/u/8111/showart_498103.html</a>
<img src ="http://www.cppblog.com/thronds/aggbug/86497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-06-02 02:23 <a href="http://www.cppblog.com/thronds/archive/2009/06/02/86497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>101条伟大的计算机编程名言</title><link>http://www.cppblog.com/thronds/archive/2009/05/26/85799.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Tue, 26 May 2009 07:52:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/05/26/85799.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/85799.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/05/26/85799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/85799.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/85799.html</trackback:ping><description><![CDATA[<p>计算机</p>
<p>&nbsp;&nbsp;&nbsp; 1、&#8220;计算机没什么用。他们只会告诉你答案。&#8221;—— (巴勃罗&#183;毕加索，画家)</p>
<p>&nbsp;&nbsp;&nbsp; 2、&#8220;计算机就跟比基尼一样，省去了人们许多的胡思乱想。&#8221;—— (萨姆&#183;尤因，作<br>家)</p>
<p>&nbsp;&nbsp;&nbsp; 3、&#8220;他们拥有计算机，他们也还可能拥有其他的大规模杀伤性武器。&#8221;—— (珍内特<br>&#183;雷诺，美国前女司法部长)</p>
<p>&nbsp;&nbsp;&nbsp; 4、&#8220;跟计算机工作酷就酷在这里，它们不会生气，能记住所有东西，还有，它们不会<br>喝光你的啤酒。&#8221;—— (保罗&#183;利里，吉他手)</p>
<p>&nbsp;&nbsp;&nbsp; 5、&#8220;如果汽车能赶上计算机的发展周期的话，一辆今天的劳斯莱斯仅值100美元，每<br>加仑要跑100万英里，每年还得爆炸一次，把里面的人杀个精光。&#8221;—— (Robert X. Cri<br>ngely，技术作家)</p>
<p>&nbsp;&nbsp;&nbsp; 计算机智能</p>
<p>&nbsp;&nbsp;&nbsp; 6、&#8220;计算机总是越来越智能的。科学家告诉我们说不久它们就能跟我们对话了。（这<br>里的&#8220;它们&#8221;，我指的是&#8220;计算机&#8221;。我怀疑科学家永远都不能跟我们对话。）&#8221;—— (<br>Dave Barry，幽默作家)</p>
<p>&nbsp;&nbsp;&nbsp; 7、&#8220;我最近注意到，在共同文化中，那种对计算机变得智能化并最终掌控世界的妄想<br>恐惧症几乎彻底消失了。据我所知，这跟MS-DOS的发布基本是同步的。&#8221;—— (Larry De<br>Luca)</p>
<p>&nbsp;&nbsp;&nbsp; 8、&#8220;计算机会不会思考这个问题就像问潜水艇会不会游泳一样。&#8221;—— (Edsger W.<br>&nbsp;Dijkstra，图灵奖获得者)</p>
<p>&nbsp;&nbsp;&nbsp; 9、&#8220;活了一百年却只能记住30M字节是荒谬的。你知道，这比一张压缩盘还要少。人<br>类境况正在变得日趋退化。&#8221;—— (Marvin Minsky，人工智能研究的奠基人)</p>
<p>&nbsp;&nbsp;&nbsp; 信任</p>
<p>&nbsp;&nbsp;&nbsp; 10、&#8220;这座城市的中央计算机告诉你的？R2D2，你不该相信一台陌生的计算机！&#8221;—<br>— (C3PO，星球大战中的翻译机器人)</p>
<p>&nbsp;&nbsp;&nbsp; 11、&#8220;永远不要相信一台不能扔掉一扇窗户*的计算机&#8221;—— (斯蒂夫&#183;沃兹尼亚克，<br>苹果联合创始人) —— *译者：暗指微软的wINDOWS操作系统</p>
<p>&nbsp;&nbsp;&nbsp; 硬件</p>
<p>&nbsp;&nbsp;&nbsp; 12、&#8220;硬件:计算机系统中可被踢的部分。&#8221;—— (Jeff Pesis)<br>软件</p>
<p>&nbsp;&nbsp;&nbsp; 13、&#8220;今天大部分的软件都很像上百万块砖堆叠在一起组成的埃及金字塔，缺乏结构<br>完整性，只能靠强力和成千上万的奴隶完成。&#8221;—— (阿伦&#183;凯，图灵奖获得者，面向对<br>象创始人)</p>
<p>&nbsp;&nbsp;&nbsp; 14、&#8220;我终于明白&#8216;向上兼容性&#8217;是怎么回事了。这是指我们得保留所有原有错误。<br>&#8221;—— (Dennie van Tassel)</p>
<p>&nbsp;&nbsp;&nbsp; 操作系统</p>
<p>&nbsp;&nbsp;&nbsp; 15、&#8220;有两样重要产品出自伯克利：LSD和BSD*。我们不相信这是个巧合。&#8221;—— (J<br>eremy S. Anderson)—— *译者：LSD是一种药力至强的迷幻剂，BSD-BSD（Berkeley Sof<br>tware Distribution，伯克利软件套件）是Unix的衍生系统</p>
<p>&nbsp;&nbsp;&nbsp; 16、&#8220;2038年1月19日，凌晨3点14分07秒&#8221;—— (UNIX中的世界末日*&#8211;1970年1月1号<br>之后的2^32秒)—— *译者：word跟world同音，UNIX用有符号整形数（WORD）表示时间，<br>所以最多只能计时2^31秒，原文的2^32应为错误。</p>
<p>&nbsp;&nbsp;&nbsp; 17、&#8220;每个操作系统都差不多&#8230; 我们都一样的烂。&#8221;—— (微软的高级副总裁布莱恩<br>&#183;瓦伦蒂尼这样描述操作系统的安全状况，2003)</p>
<p>&nbsp;&nbsp;&nbsp; 18、&#8220;微软有出了新版本，Windows XP,据大家说是&#8216;有史以来最稳定的Windows&#8217;，<br>&nbsp;对我而言, 这就好像是在说芦笋是&#8216;有史以来发音最清脆的蔬菜一样&#8217; &#8220;—— (Dave B<br>arry)</p>
<p>&nbsp;&nbsp;&nbsp; 互联网</p>
<p>&nbsp;&nbsp;&nbsp; 19、&#8220;互联网？那个东西还在吗？&#8221; —— (Homer Simpson)</p>
<p>&nbsp;&nbsp;&nbsp; 20、&#8220;网络就像是个母夜叉。我每转到一处都会看见小个的按钮命令我提交*。&#8221;——<br>&nbsp;(Nytwind)—— *译者注：Submit：提交，另一层意思是要求屈服</p>
<p>&nbsp;&nbsp;&nbsp; 21、&#8220;想想看吧，已经有一百万只猴子坐在一百万台打字机旁，可Usenet就是比不上<br>莎士比亚。&#8221;—— (Blair Houghton)</p>
<p>&nbsp;&nbsp;&nbsp; 软件产业</p>
<p>&nbsp;&nbsp;&nbsp; 22、&#8220;计算机软件产业最为惊人的成就，是其持续不断地放弃硬件产业的惊人成果和<br>稳定性。&#8221;—— (Henry Petroski)</p>
<p>&nbsp;&nbsp;&nbsp; 23、&#8220;真正的创新经常来自于那些贴近市场、但无力拥有市场的的小型初创公司。&#8221;<br>—— (Timm Martin)</p>
<p>&nbsp;&nbsp;&nbsp; 24、&#8220;人们常说，伟大的科学学科就像是站在其它巨人肩膀上的巨人。人们也说过，<br>软件产业正如站在其他侏儒脚上的侏儒。&#8221;—— (Alan Cooper，交互设计之父)</p>
<p>&nbsp;&nbsp;&nbsp; 25、&#8220;这无关比特、字节和协议，而关乎利润和损益。&#8221;—— (郭士纳，IBM前CEO)</p>
<p><br>&nbsp;&nbsp;&nbsp; 26、&#8220;我们是微软。反抗是徒劳的。你会被同化的。&#8221;—— (保险杠贴纸)</p>
<p>&nbsp;&nbsp;&nbsp; 软件演示</p>
<p>&nbsp;&nbsp;&nbsp; 27、&#8220;不管演示在彩排的时候有多好，一旦在观众面前展示时，演示不出错的几率与<br>观众人数成反比，与投入的金钱总额成正比。&#8221;—— (Mark Gibbs)</p>
<p>&nbsp;&nbsp;&nbsp; 软件专利</p>
<p>&nbsp;&nbsp;&nbsp; 28、&#8220;专利大多数都是垃圾。浪费时间去阅读这些专利是愚蠢的。只有专利持有人才<br>会这么干，还得强迫自己才会看。&#8221;—— (Linus Torvalds，LINUX创始人)</p>
<p>&nbsp;&nbsp;&nbsp; 复杂性</p>
<p>&nbsp;&nbsp;&nbsp; 29、&#8220;控制复杂性是计算机编程的本质。&#8221;—— (Brian Kernigan)</p>
<p>&nbsp;&nbsp;&nbsp; 30、&#8220;复杂性杀死一切。它把程序员的生活给搞砸了，它令产品难以规划、创建和测<br>试，带来了安全挑战，并导致最终用户和管理员沮丧不已。&#8221;—— (Ray Ozzie)</p>
<p>&nbsp;&nbsp;&nbsp; 31、&#8220;进行软件设计有两种方式。一种是让它尽量简单，让人看不出明显的不足。另<br>一种是弄得尽量复杂，让人看不出明显的缺陷。&#8221;—— (C.A.R. Hoare)</p>
<p>&nbsp;&nbsp;&nbsp; 32、&#8220;好的软件的作用是让复杂的东西看起来简单。&#8221; —— (Grady Booch，UML创始<br>人之一)</p>
<p>&nbsp;&nbsp;&nbsp; 易用性</p>
<p>&nbsp;&nbsp;&nbsp; 33、&#8220;不管那些计算机书籍如何宣称，只需记住，你并非&#8216;傀儡&#8217;。真正的傀儡是那<br>些无法设计出易于使用的硬件和软件的那些人，尽管他们是技术专家，因为这是普通消费<br>者赖以生活的东西。&#8221;—— (Walter Mossberg，科技专栏记者)</p>
<p>&nbsp;&nbsp;&nbsp; 34、&#8220;软件供应商在努力尝试让他们的软件更&#8216;易于操作&#8217;&#8230; 迄今为止，他们最好的<br>办法就是翻出所有的老手册，然后在封面盖上&#8216;易于操作&#8217;这几个字。&#8221;—— (比尔&#183;盖<br>茨)</p>
<p>&nbsp;&nbsp;&nbsp; 35、&#8220;有个老套的故事说有人希望他的计算机能像他的电话机一样好用。他的愿望实<br>现了，因为我已经不知道该如何使用自己的电话了。&#8221;—— (Bjarne Stroustrup，C++之<br>父)</p>
<p>&nbsp;&nbsp;&nbsp; 用户</p>
<p>&nbsp;&nbsp;&nbsp; 36、&#8220;任何一个傻瓜都会用电脑。很多都会。&#8221;—— (Ted Nelson)</p>
<p>&nbsp;&nbsp;&nbsp; 37、&#8220;只有两个行业把客户称为&#8216;用户&#8217;*。&#8221;—— (Edward Tufte，信息设计大师)<br>&nbsp;—— *译者注：一个是计算机设计，另一个是毒品交易，computer design and drug de<br>aling—— 程序员</p>
<p>&nbsp;&nbsp;&nbsp; 38、&#8220;程序员在跟宇宙赛跑，他们在努力开发出更大更好的傻瓜程序，而宇宙则努力<br>培养出更大更好的白痴。到目前为止，宇宙领先。&#8221;—— (Rich Cook)</p>
<p>&nbsp;&nbsp;&nbsp; 39、&#8220;你们当中很多人都知道程序员的美德。当然啦，有三种：那就是懒惰、急躁以<br>及傲慢。&#8221;—— (Larry Wall，Perl发明者)</p>
<p>&nbsp;&nbsp;&nbsp; 40、&#8220;程序员的问题是你无法预料他在做什么，直到为时已晚。&#8221;—— (Seymour Cr<br>ay，超级计算机之父)</p>
<p>&nbsp;&nbsp;&nbsp; 41、&#8220;那就是这些自认为痛恨计算机的人的真实面目。他们实际上真正痛恨的是糟糕<br>的程序员。&#8221;—— (拉瑞&#183;尼文，科幻作家)</p>
<p>&nbsp;&nbsp;&nbsp; 42、&#8220;很长时间以来我一直困惑不已，为什么一些又贵又先进的东西会一点用都没有<br>。直到我突然想起，计算机不就是一台愚蠢之至却拥有难以置信的做聪明事能力的机器嘛<br>，而程序员不就是聪明绝顶却拥有难以置信的干蠢事的能力的人嘛。一句话，他们简直就<br>是天生绝配。&#8221;—— (比尔&#183;布莱森，旅游文学作家)</p>
<p>&nbsp;&nbsp;&nbsp; 43、&#8220;不像学学涂涂画画也能让某人成为专家级画家，计算机科学教育不会让任何人<br>成为一名编程大师。&#8221;—— (埃里克&#183;雷蒙，开源运动领袖)</p>
<p>&nbsp;&nbsp;&nbsp; 44、&#8220;一个程序员是经历以下事情后仍能证明自己是严格的专家的人：他可以历经数<br>不清的捶打，可取材于无关紧要的文档，用上面的争议数据作出模糊假设，并以此计算出<br>测微精度的无数片面理解的答案,并由一个不可靠、脑袋充满质疑、公开宣称要让一个倒霉<br>透顶、没有指望、毫无防备,要求第一时间获得信息的部门狼狈不堪、令人生厌的人使用一<br>台准确度有问题的仪器去实施。&#8221;—— (IEEE网格新闻杂志)</p>
<p>&nbsp;&nbsp;&nbsp; 45、&#8220;运气好的黑客能用几个月的时间 - 生产出一个小规模的开发团体（比如说，7<br>-8人）历尽艰辛一起工作了一年多才能做出来的东西。IBM经常报告说某些程序员的生产力<br>要比其它工人高百倍，甚至更多。&#8221;—— (Peter Seebach，黑客)</p>
<p>&nbsp;&nbsp;&nbsp; 46、&#8220;最好的程序员跟好的程序员相比可不止好那么一点点。这种好不是一个数量级<br>的，取决于标准怎么定：概念创造性、速度、设计的独创性或者解决问题的能力。&#8221;——<br>&nbsp;(兰德尔&#183;E&#183;斯特劳斯，科技作家)</p>
<p>&nbsp;&nbsp;&nbsp; 47、&#8220;伟大的车工值得给他几倍于普通车工的薪水，但一个伟大的软件代码作家，其<br>价值则要等同于一个普通的软件写手的价格的1万倍。&#8221;—— (比尔&#183;盖茨)<br>&nbsp;编程</p>
<p>&nbsp;&nbsp;&nbsp; 48、&#8220;就算它工作不正常也别担心。如果一切正常，你早该失业了。&#8221; —— (Moshe<br>r的软件工程定律)</p>
<p>&nbsp;&nbsp;&nbsp; 49、&#8220;靠代码行数来衡量开发进程就好比用重量来衡量飞机制造的进度。&#8221;—— (比<br>尔&#183;盖茨)</p>
<p>&nbsp;&nbsp;&nbsp; 50、&#8220;写代码的社会地位比盗墓的高，比管理的低。&#8221;—— (杰拉尔&#183;德温伯格，软<br>件与系统思想家)</p>
<p>&nbsp;&nbsp;&nbsp; 51、&#8220;首先学习计算机科学及理论。接着形成自己编程的风格。然后把这一切都忘掉<br>，尽管改程序就是了。&#8221;—— (George Carrette，杰出软件工程师,开源推广者)</p>
<p>&nbsp;&nbsp;&nbsp; 52、&#8220;先解决问题再写代码。&#8221;—— (John Johnson)</p>
<p>&nbsp;&nbsp;&nbsp; 53、&#8220;乐观主义是编程行业的职业病；用户反馈则是治疗方法。&#8221;—— (Kent Beck)</p>
<p><br>&nbsp;&nbsp;&nbsp; 54、&#8220;迭代者为人，递归者为神。&#8221;—— (L. Peter Deutsch)</p>
<p>&nbsp;&nbsp;&nbsp; 55、&#8220;布尔值最好的一点是，就算你错了，也顶多错了一位而已。&#8221;—— (无名氏)</p>
<p><br>&nbsp;&nbsp;&nbsp; 56、&#8220;数组的下标是从0开始好还是从1开始好呢？我的0.5的折衷方案，以我之见，没<br>有经过适当考虑就被否决掉了。&#8221;—— (Stan Kelly-Bootle)</p>
<p>&nbsp;&nbsp;&nbsp; 编程语言</p>
<p>&nbsp;&nbsp;&nbsp; 57、&#8220;只有两种编程语言：一种是天天挨骂的，另一种是没人用的。&#8221;—— (Bjarne<br>&nbsp;Stroustrup，C++之父)</p>
<p>&nbsp;&nbsp;&nbsp; 58、&#8220;PHP是不合格的业余爱好者创建的，他们犯做了个小恶；Perl是娴熟而堕落的专<br>家创建的，他们犯了阴险狡诈的大恶。&#8221;—— (Jon Ribbens)</p>
<p>&nbsp;&nbsp;&nbsp; 59、&#8220;COBOL的使用摧残大脑；其教育应被视为刑事犯罪。&#8221;—— (E.W. Dijkstra)</p>
<p><br>&nbsp;&nbsp;&nbsp; 60、&#8220;把良好的编程风格教给那些之前曾经接触过BASIC的学生几乎是不可能的。作为<br>可能的程序员，他们已精神残废，无重塑的可能了。&#8221;—— (E. W. Dijkstra)</p>
<p>&nbsp;&nbsp;&nbsp; 61、&#8220;我想微软之所以把它叫做.Net，是因为这样它就不会在Unix的目录里显示出来<br>了。&#8221;—— (Oktal)</p>
<p>&nbsp;&nbsp;&nbsp; 62、&#8220;没有一种编程语言能阻止程序员写出糟糕的程序来，不管这种语言结构有多良<br>好。&#8221;—— (Larry Flon)</p>
<p>&nbsp;&nbsp;&nbsp; 63、&#8220;计算机语言设计犹如在公园里漫步。我是说侏罗纪公园。&#8221;—— (Larry Wall<br>)</p>
<p>&nbsp;&nbsp;&nbsp; C/C++</p>
<p>&nbsp;&nbsp;&nbsp; 64、&#8220;搞了50年的编程语言的研究，我们难道就以C++告终啦？&#8221;—— (Richard A.<br>O&#8217;Keefe)</p>
<p>&nbsp;&nbsp;&nbsp; 65、&#8220;写C或者C++就像是在用一把卸掉所有安全防护装置的链锯。&#8221;—— (Bob Gray<br>)</p>
<p>&nbsp;&nbsp;&nbsp; 66、&#8220;在C++里你想搬起石头砸自己的脚更为困难了，不过一旦你真的做了，整条腿都<br>要报销。&#8221;—— (Bjarne Stroustrup)</p>
<p>&nbsp;&nbsp;&nbsp; 67、&#8220;C++ : 友人可造访你的私有成员之地也。&#8221;—— (Gavin Russell Baker)——<br>&nbsp;译者：Friends：C++的友元，是一种定义在类外部的普通函数，但它需要在类体内进行说<br>明，为了与该类的成员函数加以区别，在说明时前面加以关键字friend。友元不是成员函<br>数，但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率，但是，它破<br>坏了类的封装性和隐藏性，使得非成员函数可以访问类的私有成员。</p>
<p>&nbsp;&nbsp;&nbsp; 68、&#8220;罗马帝国灭亡的其中一个主要原因是他们没有0 - 这样他们就没法给自己的C程<br>序指明成功退出的路径了。&#8221;—— (Robert Firth)</p>
<p>&nbsp;&nbsp;&nbsp; Java</p>
<p>&nbsp;&nbsp;&nbsp; 69、&#8220;Java从许多方面来说就是C++&#8211;。&#8221;—— (Michael Feldman)</p>
<p>&nbsp;&nbsp;&nbsp; 70、&#8220;说Java好就好在运行于多个操作系统之上，就好像说肛交好就好在不管男女都<br>行。&#8221;—— (Alanna)</p>
<p>&nbsp;&nbsp;&nbsp; 71、&#8220;好吧，Java也许是编程语言的好榜样。但Java应用则是应用程序的坏榜样。&#8221;<br>—— (pixadel)</p>
<p>&nbsp;&nbsp;&nbsp; 72、&#8220;要是Java真的有垃圾回收的话，大部分程序在执行的时候就会把自己干掉了。<br>&#8221;—— (Robert Sewell)</p>
<p>&nbsp;&nbsp;&nbsp; 开源</p>
<p>&nbsp;&nbsp;&nbsp; 73、&#8220;软件就像性事：免费/自由更好。&#8221;—— (Linus Torvalds)</p>
<p>&nbsp;&nbsp;&nbsp; 74、&#8220;唯一对免费软件感到害怕的人，是自己的产品还要不值钱的人。&#8221;—— (Davi<br>d Emery)</p>
<p>&nbsp;&nbsp;&nbsp; 代码</p>
<p>&nbsp;&nbsp;&nbsp; 75、&#8220;好代码本身就是最好的文档。&#8221;—— (Steve McConnell)</p>
<p>&nbsp;&nbsp;&nbsp; 76、&#8220;你自己的代码如果超过6个月不看，再看的时候也一样像是别人写的。&#8221;——<br>(伊格尔森定律)</p>
<p>&nbsp;&nbsp;&nbsp; 77、&#8220;前面90%的代码要占用开发时间的前90%。剩下的10%的代码要占用开发时间的另<br>一90%。&#8221;—— (Tom Cargill)</p>
<p>&nbsp;&nbsp;&nbsp; 软件开发</p>
<p>&nbsp;&nbsp;&nbsp; 78、&#8220;好的程序员会用脑，但是好的向导救我们于样样都要想到。&#8221;—— (Francis<br>Glassborow)</p>
<p>&nbsp;&nbsp;&nbsp; 79、&#8220;在软件里面，我们鲜有有意义的需求。就算有，衡量成功的唯一尺度也取决于<br>我们的解决方案是否解决了客户对问题是什么的观念的转变。&#8221;—— (Jeff Atwood)</p>
<p>&nbsp;&nbsp;&nbsp; 80、&#8220;想想我们计算机程序的糟糕现状吧，很显然软件开发仍是黑箱艺术，还不能称<br>之为工程学科。&#8221;—— (Bill Clinton，前美国总统)</p>
<p>&nbsp;&nbsp;&nbsp; 81、&#8220;没有伟大的团队就没有伟大的软件，可大部分的软件团队举止就像是支离破碎<br>的家庭。&#8221;—— (吉姆&#183;麦卡锡，微软VC++总监)</p>
<p>&nbsp;&nbsp;&nbsp; 调试</p>
<p>&nbsp;&nbsp;&nbsp; 82、&#8220;一旦我们开始编程，就会惊讶地发现让程序正常没想象中那么简单。调试不可<br>避免。那一刻我认记忆犹新，当时我就意识到，从今往后我生活的大部分时间都要花在寻<br>找自己程序的错误上面了。&#8221;—— (莫里斯&#183;威尔克斯 调试探索, 1949)</p>
<p>&nbsp;&nbsp;&nbsp; 83、&#8220;调试难度本来就是写代码的两倍。因此，如果你写代码的时候聪明用尽，根据<br>定义，你就没有能耐去调试它了。&#8221;—— (Brian Kernighan)</p>
<p>&nbsp;&nbsp;&nbsp; 84、&#8220;如果调试是除虫的过程，那么编程就一定是把臭虫放进来的过程。&#8221;—— (Ed<br>sger W. Dijkstra)</p>
<p>&nbsp;&nbsp;&nbsp; 质量</p>
<p>&nbsp;&nbsp;&nbsp; 85、&#8220;我才不管它能不能在你的机器上运行呢！我们又没装到你的机器上！&#8221;—— (<br>Vidiu Platon，罗马尼亚的微软最佳学生合作伙伴MSP)</p>
<p>&nbsp;&nbsp;&nbsp; 86、&#8220;编程就像性一样：一时犯错，终生维护。&#8221;—— (Michael Sinz)</p>
<p>&nbsp;&nbsp;&nbsp; 87、&#8220;有两种写出无错程序的办法；只有第三种有用。&#8221;—— (Alan J. Perlis)</p>
<p>&nbsp;&nbsp;&nbsp; 88、&#8220;软件质量与指针算法不可兼得。&#8221;—— (Bertrand Meyer)</p>
<p>&nbsp;&nbsp;&nbsp; 89、&#8220;如果麦当劳像软件公司那样运作的话，每一百个巨无霸就会有一个令你食物中<br>毒，而他们的回应是，&#8216;真对不起，这是一张额外附送两个的赠券。&#8217; &#8220;—— (Mark Mi<br>nasi)</p>
<p>&nbsp;&nbsp;&nbsp; 90、&#8220;永远要这样写代码，好像最终维护你代码的人是个狂暴的、知道你住在哪里的<br>精神病患者。&#8221;—— (Martin Golding)</p>
<p>&nbsp;&nbsp;&nbsp; 91、&#8220;是人都会犯错，不过要想把事情彻底搞砸还得请电脑出马。&#8221;—— (Paul Ehr<br>lich)</p>
<p>&nbsp;&nbsp;&nbsp; 92、&#8220;计算机比人类历史上的任何发明都更快速地导致你犯更多的错误&#8211;可能除了手<br>枪和龙舌兰酒是例外。&#8221;—— (Mitch Radcliffe)</p>
<p>&nbsp;&nbsp;&nbsp; 预测</p>
<p>&nbsp;&nbsp;&nbsp; 93、&#8220;能发明的东西都发明出来了。&#8221;—— (查尔斯&#183;杜埃尔, 美国专利局局长，18<br>99年)</p>
<p>&nbsp;&nbsp;&nbsp; 94、&#8220;我认为全球市场约需5台计算机。&#8221;—— (托马斯&#183;沃森, IBM董事长, 约1948<br>年)</p>
<p>&nbsp;&nbsp;&nbsp; 95、&#8220;看上去我们已经到达了利用计算机技术可能获得的极限了，尽管下这样的结论<br>得小心，因为不出五年这听起来就会相当愚蠢。&#8221; —— (约翰&#183;冯&#183;诺伊曼,约1949年)</p>
<p><br>&nbsp;&nbsp;&nbsp; 96、&#8220;但这又有什么好处呢？&#8221;—— (IBM先进计算机系统部的工程师对微芯片的评论<br>, 1968年)</p>
<p>&nbsp;&nbsp;&nbsp; 97、&#8220;我们没有理由让每一个人在家都拥有一台电脑。&#8221;—— (肯&#183;奥尔森,数据设备<br>公司（DEC）总裁，1977年)</p>
<p>&nbsp;&nbsp;&nbsp; 98、&#8220;640K对每一个人来说都已足够。&#8221;—— (比尔&#183;盖茨,1981年)</p>
<p>&nbsp;&nbsp;&nbsp; 99、&#8220;Windows NT的RAM寻址空间可达2G，这比任何应用程序所需都要多。&#8221; —— (<br>微软, 谈及Windows NT的开发时所言, 1992年)</p>
<p>&nbsp;&nbsp;&nbsp; 100、&#8220;我们永远也无法真正成为无纸化社会，直到掌上电脑一族发布擦我1.0*（Wip<br>eMe 1.0）为止。&#8221;—— (安迪?皮尔逊，商界领袖) *译者注：意思是说难道你大便不用纸<br>吗？</p>
<p>&nbsp;&nbsp;&nbsp; 101、&#8220;长此以往，除了按键的手指外，人类的肢体将全部退化。&#8221;—— (弗兰克?劳<br>埃德?赖特，建筑师)■</p>
<img src ="http://www.cppblog.com/thronds/aggbug/85799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-05-26 15:52 <a href="http://www.cppblog.com/thronds/archive/2009/05/26/85799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zz自动登录telnet执行若干command</title><link>http://www.cppblog.com/thronds/archive/2009/04/18/80393.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Sat, 18 Apr 2009 13:18:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/04/18/80393.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/80393.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/04/18/80393.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/80393.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/80393.html</trackback:ping><description><![CDATA[<div><font size=3>在网上找到一篇文章，讲在UNIX下自动登录telnet（<u><span style="FONT-SIZE: 12pt; COLOR: blue"><a href="http://www.linuxeden.com/forum/t138058.html"><font color=#336699>http://www.linuxeden.com/forum/t138058.html</font></a></span></u><u><span style="FONT-SIZE: 12pt; COLOR: blue">）</span></u>。这个例子很不错，下边对其进行分析。</font></div>
<table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 492.7pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=657>
            <div><span style="FONT-SIZE: 10pt; COLOR: black">#===========autotelnet.sh============== <br>#!/bin/bash<br><br>tmptty=`tty` #</span><span style="FONT-SIZE: 10pt; COLOR: black">取得当前的</span><span style="FONT-SIZE: 10pt; COLOR: black">tty</span><span style="FONT-SIZE: 10pt; COLOR: black">值<br></span><span style="FONT-SIZE: 10pt; COLOR: black">tmptty=`basename $tmptty` #</span><span style="FONT-SIZE: 10pt; COLOR: black">去掉</span><span style="FONT-SIZE: 10pt; COLOR: black">tty</span><span style="FONT-SIZE: 10pt; COLOR: black">的绝对路径<br></span><span style="FONT-SIZE: 10pt; COLOR: black">tmpname=`whoami` #</span><span style="FONT-SIZE: 10pt; COLOR: black">取得当前执行程序的用户名<br></span><span style="FONT-SIZE: 10pt; COLOR: black">ip=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">10.22.33.44</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> #</span><span style="FONT-SIZE: 10pt; COLOR: black">目标主机地址<br></span><span style="FONT-SIZE: 10pt; COLOR: black">inp1=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ABC^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> #</span><span style="FONT-SIZE: 10pt; COLOR: black">主机的用户名，注意</span><span style="FONT-SIZE: 10pt; COLOR: black">^M</span><span style="FONT-SIZE: 10pt; COLOR: black">必须在</span><span style="FONT-SIZE: 10pt; COLOR: black">UNIX</span><span style="FONT-SIZE: 10pt; COLOR: black">下重装用以下方法输入才能用！！<br></span><span style="FONT-SIZE: 10pt; COLOR: black">#</span><span style="FONT-SIZE: 10pt; COLOR: black">方法为按住</span><span style="FONT-SIZE: 10pt; COLOR: black">ctrl</span><span style="FONT-SIZE: 10pt; COLOR: black">键按</span><span style="FONT-SIZE: 10pt; COLOR: black">v</span><span style="FONT-SIZE: 10pt; COLOR: black">键，不放</span><span style="FONT-SIZE: 10pt; COLOR: black">ctrl</span><span style="FONT-SIZE: 10pt; COLOR: black">键，再按</span><span style="FONT-SIZE: 10pt; COLOR: black">shift</span><span style="FONT-SIZE: 10pt; COLOR: black">键和</span><span style="FONT-SIZE: 10pt; COLOR: black">m</span><span style="FONT-SIZE: 10pt; COLOR: black">键，完成后全部放开<br></span><span style="FONT-SIZE: 10pt; COLOR: black">inp2=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ABC^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> #</span><span style="FONT-SIZE: 10pt; COLOR: black">主机的密码，注意必须有</span><span style="FONT-SIZE: 10pt; COLOR: black">^M<br>inp3=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ls^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> #</span><span style="FONT-SIZE: 10pt; COLOR: black">其他进入后的命令，可无或用</span><span style="FONT-SIZE: 10pt; COLOR: black">ls</span><span style="FONT-SIZE: 10pt; COLOR: black">之类的命令代替，注意必须有</span><span style="FONT-SIZE: 10pt; COLOR: black">^M<br>inp4=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">pwd^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> #</span><span style="FONT-SIZE: 10pt; COLOR: black">命令</span><span style="FONT-SIZE: 10pt; COLOR: black">4</span><span style="FONT-SIZE: 10pt; COLOR: black">，同上<br></span><span style="FONT-SIZE: 10pt; COLOR: black">#--------------------------<br><br>inputfile=in #</span><span style="FONT-SIZE: 10pt; COLOR: black">导入文件管道用的，不要改，这个值没有任何关系<br></span><span style="FONT-SIZE: 10pt; COLOR: black">outputfile=out.log #</span><span style="FONT-SIZE: 10pt; COLOR: black">最终导出的文件<br></span><span style="FONT-SIZE: 10pt; COLOR: black">rm -fr $inputfile <br>rm -fr $outputfile <br>mknod $inputfile p <br>touch $outputfile <br><br>#file de</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">script</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ion 7 for out and 8 for in </span><span style="FONT-SIZE: 10pt; COLOR: black">使用</span><span style="FONT-SIZE: 10pt; COLOR: black">7</span><span style="FONT-SIZE: 10pt; COLOR: black">作为输入管道，</span><span style="FONT-SIZE: 10pt; COLOR: black">8</span><span style="FONT-SIZE: 10pt; COLOR: black">作为输入<br></span><span style="FONT-SIZE: 10pt; COLOR: black">exec 7&lt;&gt;$outputfile <br>exec 8&lt;&gt;$inputfile <br><br>telnet $ip &lt;&amp;8 &gt;&amp;7 &amp; <br><br>sleep 2; echo $inp1 &gt;&gt; $inputfile #</span><span style="FONT-SIZE: 10pt; COLOR: black">看得懂吧<br></span><span style="FONT-SIZE: 10pt; COLOR: black">sleep 2; echo $inp2 &gt;&gt; $inputfile <br>sleep 2; echo $inp3 &gt;&gt; $inputfile #</span><span style="FONT-SIZE: 10pt; COLOR: black">如果没有其他命令，这行和下一行可以去掉<br></span><span style="FONT-SIZE: 10pt; COLOR: black">sleep 2; echo $inp4 &gt;&gt; $inputfile <br><br>tail -f $outputfile &amp; </span><span style="FONT-SIZE: 10pt; COLOR: black">强制在屏幕上显示任何输入输出<br></span><span style="FONT-SIZE: 10pt; COLOR: black"><br>while true #</span><span style="FONT-SIZE: 10pt; COLOR: black">正常情况下已经进入目标主机了，可以输入任何命令，所有的一切输入输出都会被记录</span><span style="FONT-SIZE: 10pt; COLOR: black"> <br>do <br>read str <br>if [[ $str = </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">quit</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> || $str = </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">exit</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> ]] <br>then echo $str &gt;&gt; $inputfile exit <br>else echo $str &gt;&gt; $inputfile <br>fi <br>done <br><br>#</span><span style="FONT-SIZE: 10pt; COLOR: black">退出时自动杀掉相关进程<br></span><span style="FONT-SIZE: 10pt; COLOR: black">ps -ef | grep telnet | grep -v grep | grep -v telnetd | grep $tmptty | grep $tmpname | awk </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">{print </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> kill -9</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">, $2}</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> | sh<br>ps -ef | grep tail | grep -v grep | grep -v telnetd | grep $tmptty | grep $tmpname | awk </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">{print </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> kill -9</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">, $2}</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> | sh</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div><font size=3>这段代码实现的功能是在UNIX<span>系统上执行这个<strong onmouseover='isShowAds = true;isShowAds2 = true;ads.Move(this,"","%u5FAE%u8F6F%u6700%u4F73%u811A%u672C%u8BED%u8A00%u793A%u4F8B%uFF0C%u9605%u8BFB%u8BF7%u70B9%u51FB%u3002","20295","脚本","%u811A%u672C","http%3A//go.microsoft.com/%3Flinkid%3D6331215")' style="FONT-WEIGHT: normal; CURSOR: hand; COLOR: #0000ff; TEXT-DECORATION: underline" onclick='javascript:window.open("http://rad.17luntan.com/ClickPortal/WebClick.aspx?id=20295&amp;k=%u811A%u672C&amp;siteid=95d6d193-1fb9-4fc0-8708-b7ceb3276924&amp;url=http%3A//iamliujianfeng.bokee.com/viewdiary.12107831.html&amp;gourl=http%3A//go.microsoft.com/%3Flinkid%3D6331215&amp;parm=E597DF415C11D759D30BCC37737F1307523F540DB74FDF8B&amp;alliedsiteid=0");' onmouseout="isShowAds = false;isShowAds2 = false;">脚本</strong>，自动登录到脚本中变量</span>&lt;ip&gt;声明使用的主机上，并用脚本中&lt;inp1&gt;变量和&lt;inp2&gt;的值分别作为用户名和密码进行身份验证。然后，用户可以在控制台上输入任何命令，这些命令会被发送到远端主机执行。因此，我猜测这个脚本的作用和SecureCRT等TELNET工具提供的自动登录的功能是一样的。</font></div>
<div>&nbsp;</div>
<div><font size=3>这个例子的主要原理是这样的：用后台方式启动一个telnet进程。将这个进程的输入重定向到一个管道文件in，向这个管道文件追加要执行的指令，也就是将指令传送到telnet进程中执行；同时，将这个进程的输出重定向至一个日志文件out.log中，tail &#8211;f这个日志文件，就是实时刷新telnet的输出。</font></div>
<div>&nbsp;</div>
<div><font size=3>这里有几个细节问题需要说明一下：</font></div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span><font size=3>1、&nbsp;</font></span><font size=3>向管道文件写入要执行的命令时，必须有一个结束标志，告诉telnet启动的shell进程这是一个完整的命令，可以执行了。这个结束标志就是&#8221; ^M&#8221;。这个东西的输入还很复杂。按照作者的说明，要在UNIX系统上，按住Ctrl键后按v键，松开v键保持Ctrl键不放，然后按下Shift键后再按M键，然后同时放开Ctrl Shilf和M三个键。在实际使用中发现，不需要Shift键，放开v键之后直接按m键即可；</font></div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span><font size=3>2、&nbsp;</font></span><font size=3>在重定向telnet后台进程的输入时，因为要控制输入内容的速度（要等到出现login以后才能输入用户名），所以不能采用文件中直接保存用户名、密码及所有要执行指令的方式，要求in文件是空的。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span><font size=3>3、&nbsp;</font><font size=3>在重定向telnet后台进程的输入、输出时，必须使用文件描述符。具体原因还不清楚，但用文件名称进行重定向就不行；</font></span><span><font size=3>&nbsp;</font></span></div>
<div style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt"><span><font size=3>4、&nbsp;</font></span><font size=3>在用户输入quit或exit后，需要退出后台telnet进程以及tail &#8211;f进程。脚本中采用kill进程的方式实现这一目标。因为kiill进程时需要一些参数，因此在脚本的开始处记录了tty的类型等信息；</font></div>
<div><font size=3>对于脚本中具体指令的解释，参加如下列表中的注释</font></div>
<table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 492.7pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=657>
            <div><span style="FONT-SIZE: 10pt; COLOR: black">#!/bin/bash<br><br>tmptty=`tty` &nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">取得当前的</span><span style="FONT-SIZE: 10pt; COLOR: blue">tty</span><span style="FONT-SIZE: 10pt; COLOR: blue">值</span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">tmptty=`basename $tmptty`&nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">去掉</span><span style="FONT-SIZE: 10pt; COLOR: blue">tty</span><span style="FONT-SIZE: 10pt; COLOR: blue">的绝对路径</span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">tmpname=`whoami`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-SIZE: 10pt; COLOR: blue">&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: blue">取得当前执行程序的用户名</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">以上信息在最后</span><span style="FONT-SIZE: 10pt; COLOR: blue">kill</span><span style="FONT-SIZE: 10pt; COLOR: blue">进程时作为筛选条件使用</span></div>
            <div><span style="FONT-SIZE: 10pt; COLOR: black">ip=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">10.22.33.44</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: blue">目标主机地址<br></span><span style="FONT-SIZE: 10pt; COLOR: black">inp1=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ABC^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: blue">主机的用户名。注意</span><span style="FONT-SIZE: 10pt; COLOR: blue">^M</span><span style="FONT-SIZE: 10pt; COLOR: blue">必须在</span><span style="FONT-SIZE: 10pt; COLOR: blue">UNIX</span><span style="FONT-SIZE: 10pt; COLOR: blue">下重装用以下方法输入才能用！！</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">方法为按住</span><span style="FONT-SIZE: 10pt; COLOR: blue">ctrl</span><span style="FONT-SIZE: 10pt; COLOR: blue">键按</span><span style="FONT-SIZE: 10pt; COLOR: blue">v</span><span style="FONT-SIZE: 10pt; COLOR: blue">键，不放</span><span style="FONT-SIZE: 10pt; COLOR: blue">ctrl</span><span style="FONT-SIZE: 10pt; COLOR: blue">键，再按</span><span style="FONT-SIZE: 10pt; COLOR: blue">shift</span><span style="FONT-SIZE: 10pt; COLOR: blue">键和</span><span style="FONT-SIZE: 10pt; COLOR: blue">m</span><span style="FONT-SIZE: 10pt; COLOR: blue">键，完成后全部放开<br><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">经过实际使用，不比按</span><span style="FONT-SIZE: 10pt; COLOR: blue">shilf</span><span style="FONT-SIZE: 10pt; COLOR: blue">键也可以</span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">inp2=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ABC^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">主机的密码，注意必须有</span><span style="FONT-SIZE: 10pt; COLOR: blue">^M<br></span><span style="FONT-SIZE: 10pt; COLOR: black">inp3=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">ls^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><span style="FONT-SIZE: 10pt; COLOR: black">&nbsp;</span><span style="FONT-SIZE: 10pt; COLOR: blue">#</span><span style="FONT-SIZE: 10pt; COLOR: blue">其他进入后的命令，可无或用</span><span style="FONT-SIZE: 10pt; COLOR: blue">ls</span><span style="FONT-SIZE: 10pt; COLOR: blue">之类的命令代替，注意必须有</span><span style="FONT-SIZE: 10pt; COLOR: blue">^M</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>inp4=</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">pwd^M</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><span style="FONT-SIZE: 10pt; COLOR: blue">&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: blue">命令</span><span style="FONT-SIZE: 10pt; COLOR: blue">4</span><span style="FONT-SIZE: 10pt; COLOR: blue">，同上<br></span><span style="FONT-SIZE: 10pt; COLOR: black">#--------------------------<br><br>inputfile=in&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">将命令导入后台telnet进程用的管道文件名称<br></span><span style="FONT-SIZE: 10pt; COLOR: black">outputfile=out.log &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">包含</span><span style="FONT-SIZE: 10pt; COLOR: black">telnet</span><span style="FONT-SIZE: 10pt; COLOR: black">后台进程输入的文件名称</span><span style="FONT-SIZE: 10pt; COLOR: black"> <br></span><span style="FONT-SIZE: 10pt; COLOR: black">rm -fr $inputfile &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>rm -fr $outputfile &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>mknod $inputfile p &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">建立管道文件</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>touch $outputfile &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">建立输出文件</span><span style="FONT-SIZE: 10pt; COLOR: black"><br><br></span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">exec 7&lt;&gt;$outputfile &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">将文件描述符</span><span style="FONT-SIZE: 10pt; COLOR: black">7</span><span style="FONT-SIZE: 10pt; COLOR: black">分配给</span><span style="FONT-SIZE: 10pt; COLOR: black">outputfile<br>exec 8&lt;&gt;$inputfile &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">将文件描述符</span><span style="FONT-SIZE: 10pt; COLOR: black">8</span><span style="FONT-SIZE: 10pt; COLOR: black">分配给</span><span style="FONT-SIZE: 10pt; COLOR: black">inputfile<br><br>telnet $ip &lt;&amp;8 &gt;&amp;7 &amp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">后台运行</span><span style="FONT-SIZE: 10pt; COLOR: black">telent</span><span style="FONT-SIZE: 10pt; COLOR: black">，同时重定向输入、输出</span><span style="FONT-SIZE: 10pt; COLOR: black"><br><br>sleep 2; echo $inp1 &gt;&gt; $inputfile&nbsp;&nbsp;#2</span><span style="FONT-SIZE: 10pt; COLOR: black">秒后输入用户名</span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">sleep 2; echo $inp2 &gt;&gt; $inputfile &nbsp;&nbsp;#2</span><span style="FONT-SIZE: 10pt; COLOR: black">秒后输入密码</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>sleep 2; echo $inp3 &gt;&gt; $inputfile &nbsp;&nbsp;#2</span><span style="FONT-SIZE: 10pt; COLOR: black">秒后输入命令</span><span style="FONT-SIZE: 10pt; COLOR: black">inp3</span><span style="FONT-SIZE: 10pt; COLOR: black"><br></span><span style="FONT-SIZE: 10pt; COLOR: black">sleep 2; echo $inp4 &gt;&gt; $inputfile &nbsp;&nbsp;#2</span><span style="FONT-SIZE: 10pt; COLOR: black">秒后输入命令</span><span style="FONT-SIZE: 10pt; COLOR: black">inp3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-SIZE: 10pt; COLOR: black">＃这里面</span><span style="FONT-SIZE: 10pt; COLOR: black">inp3</span><span style="FONT-SIZE: 10pt; COLOR: black">和</span><span style="FONT-SIZE: 10pt; COLOR: black">inp4</span><span style="FONT-SIZE: 10pt; COLOR: black">只是一个说明，对自动登录实际上没有什么作用</span></div>
            <div><span style="FONT-SIZE: 10pt; COLOR: black">tail -f $outputfile &amp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="FONT-SIZE: 10pt; COLOR: black">＃</span><span style="FONT-SIZE: 10pt; COLOR: black">强制在屏幕上显示任何输入输出<br></span><span style="FONT-SIZE: 10pt; COLOR: black"><br>while true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">正常情况下已经进入目标主机了，可以输入任何命令，所有的一切输入输出都会被记录</span><span style="FONT-SIZE: 10pt; COLOR: black"> <br>do <br>read str <br>if [[ $str = </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">quit</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> || $str = </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">exit</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> ]] <br>then echo $str &gt;&gt; $inputfile exit &nbsp;&nbsp;#</span><span style="FONT-SIZE: 10pt; COLOR: black">这里的</span><span style="FONT-SIZE: 10pt; COLOR: black">exit</span><span style="FONT-SIZE: 10pt; COLOR: black">实际上是从循环中退出</span><span style="FONT-SIZE: 10pt; COLOR: black"><br>else echo $str &gt;&gt; $inputfile <br>fi <br>done <br><br>#</span><span style="FONT-SIZE: 10pt; COLOR: black">退出时自动杀掉相关进程<br></span><span style="FONT-SIZE: 10pt; COLOR: black">ps -ef | grep telnet | grep -v grep | grep -v telnetd | grep $tmptty | grep $tmpname | awk </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">{print </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> kill -9</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">, $2}</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> | sh<br>ps -ef | grep tail | grep -v grep | grep -v telnetd | grep $tmptty | grep $tmpname | awk </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">{print </span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> kill -9</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">"</span></strong><span style="FONT-SIZE: 10pt; COLOR: black">, $2}</span><strong><span style="FONT-SIZE: 9pt; COLOR: black">'</span></strong><span style="FONT-SIZE: 10pt; COLOR: black"> | sh</span></div>
            </td>
        </tr>
    </tbody>
</table>
<div>&nbsp;</div>
<div><font size=3>明白了这个脚本的原理，我们可以做一个试验，用另外一种更加明显的方式来做输入输出的重定向。</font></div>
<div>&nbsp;</div>
<div><font size=3>1、新建1个普通文件<span>&nbsp;&nbsp;&nbsp; touch out.log</span></font></div>
<div><font size=3>2、新建一个管道文件:<span>&nbsp;&nbsp; mknod commands p</span></font></div>
<div><font size=3>3、为日志文件分配文件描述符7 ：&nbsp;exec 7&lt;&gt;out.log</font></div>
<div><font size=3>4、为管道文件分配文件描述符8：<span>&nbsp;&nbsp; exec 8&lt;&gt;commands</span></font></div>
<div><font size=3>5、后台方式启动telnet:<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; telnet 136.30.75.102 &lt;&amp;8 &gt;&amp;7 &amp;</span></font></div>
<div><font size=3>6、实时刷新输出信息：<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tail &#8211;f out.log</span></font></div>
<div><font size=3>7、另外启动一个终端，输入信息：</font><font size=3>&nbsp;echo &#8220;root^M&#8221; &gt;&gt;commands<br><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo &#8220;password^M&#8221;&gt;&gt;commands<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; echo &#8220;pwd^M&#8221; &gt;&gt; commands<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8230;.</span></font></div>
<div><font size=3>8、观察tail &#8211;f的输出，可以看到输入命令的执行结果。</font></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><font size=3>在这个脚本的基础上，可以实现自动telnet到一个主机上并执行一些列command的功能。脚本如下：</font></div>
<div align=center>
<table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 426.1pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent" vAlign=top width=568>
            <div><font size=3>#!/bin/bash</font></div>
            <div>&nbsp;</div>
            <div><font size=3>tmptty=`tty`</font></div>
            <div><font size=3>tmptty=`basename $tmptty`</font></div>
            <div><font size=3>tmpname=`whoami`</font></div>
            <div><font size=3>ip="136.39.75.102"</font></div>
            <div><font size=3>inp1="root^M"</font></div>
            <div><font size=3>inp2="Easy2get^M"</font></div>
            <div><font size=3>#####################################################################</font></div>
            <div><font size=3>#you may add as many commands as you want</font></div>
            <div><font size=3>#NOTE:every command should end with ^M, which is input under UNIX </font></div>
            <div><font size=3>#<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>方法为按住ctrl键按v键，不放ctrl键，再按shift键和m键，完成后全部放开</font></div>
            <div><font size=3>#####################################################################</font></div>
            <div><font size=3>inp3="ls^M"</font></div>
            <div><font size=3>inp4="echo 'hello,TeMIP users' &gt;&gt; hello.txt^M"</font></div>
            <div>&nbsp;</div>
            <div><font size=3>#--------------------------</font></div>
            <div>&nbsp;</div>
            <div><font size=3>inputfile=in</font></div>
            <div><font size=3>outputfile=out.log</font></div>
            <div><font size=3>rm -fr $inputfile</font></div>
            <div><font size=3>rm -fr $outputfile</font></div>
            <div><font size=3>mknod $inputfile p</font></div>
            <div><font size=3>touch $outputfile</font></div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div><font size=3>exec 7&lt;&gt;$outputfile</font></div>
            <div><font size=3>exec 8&lt;&gt;$inputfile</font></div>
            <div>&nbsp;</div>
            <div><font size=3>telnet $ip &lt;&amp;8 &gt;&amp;7 &amp;</font></div>
            <div>&nbsp;</div>
            <div><font size=3>sleep 2; echo $inp1 &gt;&gt; $inputfile</font></div>
            <div><font size=3>sleep 2; echo $inp2 &gt;&gt; $inputfile</font></div>
            <div>&nbsp;</div>
            <div><font size=3>echo "executing command $inp3"</font></div>
            <div><font size=3>sleep 2; echo $inp3 &gt;&gt; $inputfile</font></div>
            <div><font size=3>echo "executing $inp4"</font></div>
            <div><font size=3>sleep 2; echo $inp4 &gt;&gt; $inputfile</font></div>
            <div><font size=3>echo "exiting"</font></div>
            <div><font size=3>sleep 2; echo "exit^M" &gt;&gt; $inputfile</font></div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div><font size=3>rm $inputfile</font></div>
            <div><font size=3>rm $outputfile</font></div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<div>&nbsp;</div>
<div style="MARGIN: 13pt 0cm"><strong><font size=4><font size=5>附录：Shell中的输入/输出</font></font></strong></div>
<div><font size=3>（摘自HP-UX 参考手册 用户命令 ksh）</font></div>
<div><font size=3>命令执行之前，其输入和输出可以使用专用表示法重定向由Shell 解释。下列内容可以出现在简单命令内的任何位置，或在命令之前之后，并且不传递给调用命令。命令和参数替换发生在使用word 或digit 之前，除非如下所示。文件名生成仅出现在模式匹配单一文件且不执行空白解释时。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;word 使用文件word 作为标准输入（文件描述符0 ）。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;word 使用文件word 作为标准输出（文件描述符1 ）。如果不存在该文件，将另行创建。如果文件存在，并且使用noclobber 选项，则发生错误；否则文件被截断为零长度。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;|word 与&gt; 相同，区别在于覆盖noclobber 选项。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;&gt;word 使用文件word 作为标准输出。如果文件存在，追加输出到其中（通过首先搜索文件末尾）；否则，另行创建文件。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;&gt;word 打开文件word 作为标准输入以进行读取和写入。如果不存在该文件，将另行创建。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;&lt;[ - ]word 读取Shell 输入直至出现行与word 匹配，或者抵达文件末尾。在word 上没有执行参数替换、命令替换或文件名生成。得到的文档称为本文档，作为标准输入。如果引用word 的任意字符，不对文档字符进行解释。否则，发生参数和命令替换，忽略\newline，必须使用\ 引用字符\ 、$ 、&#8216; 和word 的第一个字符。如果- 追加到&lt;&lt; ，则从word 和文档去掉所有前导制表符。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;&amp;digit 从文件描述符复制标准输入digit （请参阅dup(2) ）。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;&amp;digit 标准输出复制到文件描述符digit （请参阅dup(2) ）。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;&amp;- 标准输入关闭。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;&amp;- 标准输出关闭。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&lt;&amp;p 来自联合进程的输入移动到标准输入。</font></div>
<div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><span><font size=3>l</font><span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><font size=3>&gt;&amp;p 到联合进程去的输出移动到标准输出。</font></div>
<div><font size=3>如果上述一项有数字前导，文件描述符号引用由该数字指定（取代缺省的0 或1 ）。例如：</font></div>
<div><font size=3>... 2&gt;&amp;1</font></div>
<div><font size=3>意味着文件描述符2 打开，作为文件描述符1 的副本用于写入。重定向顺序很重要，因为Shell 根据当前打开文件在计算时与指定文件描述符的关联计算重定向引用文件描述符。例如：</font></div>
<div><font size=3>... 1&gt;fname 2&gt;&amp;1</font></div>
<div><font size=3>首先分配文件描述符1（标准输出）给文件fname ，然后分配文件描述符2（标准错误）给分配给文件描述符1的文件，也就是fname 。另一方面，如果重定向顺序反转如下：</font></div>
<div><font size=3>... 2&gt;&amp;1 1&gt;fname</font></div>
<div><font size=3>文件描述符2 分配给当前标准输出，（用户终端，除非继承了不同的分配）。此时文件描述符1 重新分配给文件fname ，不更改文件描述符2 的分配。</font></div>
<div><font size=3>co-process 的输入和输出可移动到多个文件描述符，允许其他命令使用上述重定向运算符向其中写入和读取。如果当前co-process 输入移动到多个文件描述符，另一个co-process 开始。</font></div>
<div><font size=3>如果命令后跟随&amp; 并且作业控制非活动状态，命令的缺省标准输入为空文件/dev/null 。否则，执行命令的环境包括调用Shell 的文件描述符，通过输入/输出规格修改</font></div>
<a href="http://blog.csdn.net/muyuqing/archive/2007/04/27/1586824.aspx">http://blog.csdn.net/muyuqing/archive/2007/04/27/1586824.aspx</a>
<img src ="http://www.cppblog.com/thronds/aggbug/80393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-04-18 21:18 <a href="http://www.cppblog.com/thronds/archive/2009/04/18/80393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 10个你也许不知道的Ubuntu技巧</title><link>http://www.cppblog.com/thronds/archive/2009/04/14/79942.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Tue, 14 Apr 2009 13:46:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/04/14/79942.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/79942.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/04/14/79942.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/79942.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/79942.html</trackback:ping><description><![CDATA[新闻来源:PCWorld<br>原文作者近期刚开始与他的合作者合著一本关于Ubuntu技巧的书，目前定名为《Ubuntu功夫<br>》。不过这本书可能要到明年才会出版，作者先给出了以下10条技巧。这些技巧并不一定仅<br>仅是在Ubuntu上才可以使用，只是在Ubuntu这种Linux发行版下经过验证的。<br><br>1.打开超级用户权限的运行程序对话框<br><br>你也许已经知道用Alt+F2来打开&#8221;运行程序&#8221;对话框，然后可以输入任何命令行运行之。如<br>果你在终端窗口中输入gksu命令，则会弹出一个类似的对话框，但是运行的程序都是在<br>root级权限。你可以通过System-&gt;Preferences-&gt; Keyboard Shortcuts,，将这个命令与键 <br>盘快捷键（如Shift+Alt+F2）绑定，可以更加方便的使用这一功能。<br><br>2. 使用GDebi来安装包<br><br>笔者很长一段时间都没注意到GDebi这个程序，这是一个用于安装你自己手动下载的包的&nbsp;&nbsp; <br>GUI程序。它会根据软件仓库这一实用的特性，来解算依赖关系。很多人也许和笔者一样， <br>用传统的dpkg命令来实现。有一天笔者发现，GDebi也可以命令行模式运行（sudo gdebi&nbsp;&nbsp; <br>package.deb），其功能和GUI模式下完全一样。尝试一下这个命令，也许你再也不想用<br>dpkg &#8211;i了。<br><br>3. CD命令技巧<br><br>笔者确信甚至很多命令行专家也会偶尔发现一些自己以前没意识到的技巧。最近笔者发现了<br>两个以前被忽略的CD命令的技巧，输入cd命令而不带任何参数，可以直接切换到/home目录 <br>（等效于cd ~），输入cd &#8211;则可以切换到你浏览的上一个目录。<br><br>4. 使用PUSHD将目录添加到目录栈<br><br>首先来说明一下目录栈是什么，很简单，就是bash存储的一个目录列表。当前浏览的目录总<br><br>4. 使用PUSHD将目录添加到目录栈<br><br>首先来说明一下目录栈是什么，很简单，就是bash存储的一个目录列表。当前浏览的目录总<br>是在列表的顶端，但如果你不通过PUSHD往其中添加目录，这个列表则是空的。举例说明， <br>使用 pushd /usr/bin命令会添加/usr/bin目录到列表，同时会切换到这个目录（加上-n参 <br>数可以停留在当前目录不跳转）。使用popd则会删除最顶端的目录，然后跳转到列表中的下<br>一个目录。尝试一下这个命令，当你在管理系统时需要在不同目录之间跳转时或者容易忘记<br>重要东西的位置时，它可能会相当有用。<br><br>5. 使用PKILL快速杀掉进程<br><br>笔者经常使用top、kill或killall进程加上ps | aux查找进程号/进程名来杀掉进程。但是 <br>pkill命令则可去掉大量的工作，pkill firefox就可以杀掉进程列表中所有与firefox符合 <br>的incheng。Pstree也是一个很酷的命令，它会根据所有关系以家庭树的方式显示所有进程 <br>。<br><br>6.使用Gnome中心自定义Gnome<br><br>对于那些难于放弃窗口界面，希望能获得类似控制面板界面体验的用户，可以考虑使用<br>gnome-control-center来实现系统配置。在桌面上添加快捷方式，可以使新手获得类似<br>Windows的体验，避免迷失在复杂的系统菜单中。<br><br>7. 加速OpenOffice.org的启动<br><br>如果你经常使用OpenOffice.org，你可能会被它漫长的启动时间所囧到。要解决这个问题，<br>打开会话程序（在Jaunty中被称为启动项管理，反正你总能在System-&gt;Preferences-&gt;<br>Startup Applications中找到），然后新增一项。在命令行中输入openoffice<br>-nodefault &#8211;nologo，重启后，OpenOffice会在Gnome桌面启动的时候缓存，再次启动任何<br>OpenOffice程序时就会很快完成。<br><br>8.快速清理磁盘垃圾<br><br>磁盘空间又不够用了？尝试在终端窗口中输入sudo apt-get autoremove然后输入sudo<br>apt-get clean，前一个命令会卸载系统中所有未被使用的依赖关系，后一个命令会清除所 <br>有缓存的包文件，两者都是无害的。在一个升级过多次的系统上，你也许能通过这个方法清<br>理出若干GB的空间。<br><br>9. 找出丢失的文件扩展名<br><br>如果你收到一个没有扩展名的email附件，不知道是什么类型时（苹果用户经常把文件扩展 <br>名忽略），试一下file命令，直接加上文件名。同时也可以试一下strings命令，会显示出 <br>二进制文件中任何可显示的字符串，文件的类型通常就会在前面几行，所以用管道把这个命<br>令和head连接起来是个好办法。<br><br>10.不要忘了这些手册页面<br><br>看一下这些有趣的但是不是广为人知的手册页面：intro 初学者的命令行指导； hier 文件<br>系统的介绍； built-ins 各种没有自带说明的命令的迷你手册。<br><br><br><img src ="http://www.cppblog.com/thronds/aggbug/79942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-04-14 21:46 <a href="http://www.cppblog.com/thronds/archive/2009/04/14/79942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在移动存储设备中安装Ubuntu系统全攻略</title><link>http://www.cppblog.com/thronds/archive/2009/04/13/79801.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Mon, 13 Apr 2009 08:35:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/04/13/79801.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/79801.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/04/13/79801.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/79801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/79801.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 随着大容量移动存储设备价格的不断走低，更多的用户选择将Ubuntu系统安装到移动存储设备中。而近期揭晓的Ubuntu 8.10在移动运用 方面的功能大为增强，将它安装到移动存储设备中更为方便。下面就为大家细致介绍如何 将最新的Ubuntu 8.10版安装到移动硬盘和闪存上。&nbsp;&nbsp;<a href='http://www.cppblog.com/thronds/archive/2009/04/13/79801.html'>阅读全文</a><img src ="http://www.cppblog.com/thronds/aggbug/79801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-04-13 16:35 <a href="http://www.cppblog.com/thronds/archive/2009/04/13/79801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>15 Best websites where you can find Free eBooks</title><link>http://www.cppblog.com/thronds/archive/2009/04/04/78961.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Sat, 04 Apr 2009 11:34:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/04/04/78961.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/78961.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/04/04/78961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/78961.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/78961.html</trackback:ping><description><![CDATA[<div class=snap_preview>
<p style="TEXT-ALIGN: left"><em><strong>15 Best websites where you can find Free eBooks</strong></em></p>
<p>From ancient times, libraries are the places where people go to find and read books. Now, in this modern age, there are ebooks that you can view and read on your computer screen. You can sit at your home and read books, listen to, trade or borrow books using websites.</p>
<p>There are plenty of directories that host free ebooks that you can legally download and read at your home. But, there are some grey sites (black sites) that violate the copyright law where people share their ebook collection for others (I am not talking about the Peer-to-Peer sharing over computers which is a different world).</p>
<p>You need to be wise to choose what you want to read and what you want to skip based on your ethical values. But, here are some of the best collection of websites that every book lover would love. And yea, these are ebooks that are virtual - so, nothing beats the real feel of reading a book on a sunny afternoon sitting in a beach.</p>
<p style="TEXT-ALIGN: left"><strong>10 Best Websites for Booklovers</strong></p>
<p><strong>1. Project Gutenberg</strong></p>
<p><a href="http://www.promo.net/pg/index.html"><strong><font color=#b85b5a><u>Project Gutenberg</u></font></strong></a> is a repository of all the free texts that are in the public domain. It is the Internet&#8217;s oldest web portal that stocks the largest colelction of FREE electronic books that you can use legally. Billions of volunteers from all over the world scan, create, proof-read, edit and maintain this ebook collection. You can download the entire collection or individual books as a plain txt file.</p>
<p><strong>2. eSnips</strong></p>
<p><a href="http://www.esnips.com/"><strong><font color=#0066cc><u>eSnips</u></font></strong></a> is a place for sharing ebooks, mp3 songs, photographs or paintings. You can list your creations for free or set a price and sell them here. eSnips is really a grown market place. You can download the books as individual pdf files. Also, you can find some good quality audio books when you search site with &#8220;audio book&#8221;.</p>
<p><strong>3. Scribd</strong></p>
<p><a href="http://www.scribd.com/"><strong><font color=#0066cc><u>Scribd</u></font></strong></a> is another document sharing<br>website where people share lots of their e-books. This is the coolest document sharing web service that you may ever come across. You can download the ebooks in various formats such as .doc, .pdf or plain text files.</p>
<p><strong>4. WikiBooks</strong></p>
<p><a href="http://www.wikibooks.org/"><strong><font color=#0066cc><u>WikiBooks</u></font></strong></a> is another project from the creators of Wikipedia. Like Project Gutenberg, this is also a free collection of e-texts created by volunteers all over the world. The books are available in various international languages. You may use these texts in your creations as long as you credit the source properly (Always check the license before you use).</p>
<p><strong>5. Full Books</strong></p>
<p><strong><a href="http://www.fullbooks.com/"><font color=#0066cc><u>Full Books</u></font></a> </strong>lists thousands of free text books neatly arranged alphabetically. You can only read online, but you can copy and paste page-by-page which is a tedious task if a book</p>
<p><strong>6. Wiretap</strong></p>
<p><a href="http://wiretap.area.com/"><strong><font color=#0066cc><u>Wiretap</u></font></strong></a>, just like Project Gutenberg, is another probably the single useful gopher resource remaining on the Internet. They plan to be considerably expanding our offerings in the near future. More books, more authors are coming soon.</p>
<p><strong>7. Free Classic Audiobooks</strong></p>
<p><strong><a href="http://www.freeclassicaudiobooks.com/"><font color=#0066cc><u>Free Classic Audiobooks</u></font></a> </strong>is a place where you can download or listen to audiobooks. The files are available as .mp3 or .mp4 and you can directly download to your iPods or mp3 player for free.</p>
<p><strong>8. Digital Classics</strong></p>
<p><a href="http://imgs.zinio.com/retail_srvs/classics/"><strong><font color=#0066cc><u>Digital Classics Zinio</u></font></strong></a> is a place where you can browse and read books and magazines for free. The books appear as it is leather-bound and you can turn pages and read them at your own pace.</p>
<p><strong>9. Read Print</strong></p>
<p><a href="http://www.readprint.com/"><strong><font color=#0066cc><u>ReadPrint</u></font></strong></a> is a free online library. It lists thousands of free books for students, teachers, and the classic enthusiast. It includes poems and articles on various topics.</p>
<p>10. Planet eBook</p>
<p><a href="http://www.planetebook.com/"><strong><font color=#0066cc><u>Planet eBook</u></font></strong></a> is the home of free classic literature. All the novels and books are entirely free for you to download and share.</p>
<p><strong>Five Bonus Sites: Chicken Soup for Booklover&#8217;s Soul</strong></p>
<p><a href="http://www.readatwork.com/"><strong><font color=#0066cc><u>Read at Work</u></font></strong></a> is a site which will allow you to books at work. Your boss when walks past will think that you are actually work on the official presentation. Cool trick, right? See it to believe it.</p>
<p><strong><a href="http://www.bookcrossing.com/"><font color=#0066cc><u>BookCrossing</u></font></a></strong> is a the most popular book sharing site. People exchange books for free and these clubs exist in almost every city in the world. People drop books at designated places and log that in the bookcrossing website, some others pick it up, read and then pass it on. It is all free.</p>
<p><a href="http://bookmooch.com/languages"><strong><font color=#0066cc><u>BookMooch</u></font></strong></a> is a place where you can trade books. Yea, you post a book to a BookMooch user and you will get a book that you like from another user. You have to send out at least 1 book for every 2 you receive. If you don&#8217;t keep this ratio up, you won&#8217;t be able to mooch any books, even if you have the points, until you improve your ratio. Sending internationally counts as 3 books.</p>
</div>
From:http://bestwebsitesfreeebooks.wordpress.com/2009/03/31/hello-world/
<img src ="http://www.cppblog.com/thronds/aggbug/78961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-04-04 19:34 <a href="http://www.cppblog.com/thronds/archive/2009/04/04/78961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubuntu8.10下编译好的程序 到redhat服务器上碰到的问题: glibc_2.4 not found</title><link>http://www.cppblog.com/thronds/archive/2009/03/28/78199.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Sat, 28 Mar 2009 15:01:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/03/28/78199.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/78199.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/03/28/78199.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/78199.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/78199.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 编译时的小问题`GLIBC_2.4' not found带来的学习。不同linux系统之间的差别，编译时包依赖的问题。&nbsp;&nbsp;<a href='http://www.cppblog.com/thronds/archive/2009/03/28/78199.html'>阅读全文</a><img src ="http://www.cppblog.com/thronds/aggbug/78199.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-03-28 23:01 <a href="http://www.cppblog.com/thronds/archive/2009/03/28/78199.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Linux和Windows下搭建CVS服务器与CVS客户端的详细配置指南</title><link>http://www.cppblog.com/thronds/archive/2009/03/27/78040.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Fri, 27 Mar 2009 07:34:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/03/27/78040.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/78040.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/03/27/78040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/78040.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/78040.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本教程包含CVS的入门知识讲解、在linux和windows下CVS服务器与CVS客户端的配置指南，详细介绍了配置过程，可以说是一篇组建CVS开发环境的入门、学习与提高的完美教程。通过本教程你可以在最短的时间里面最快的搭建好CVS服务器与CVS客户端的的开发环境。如有不明之处，请联系飘扬&nbsp;&nbsp;<a href='http://www.cppblog.com/thronds/archive/2009/03/27/78040.html'>阅读全文</a><img src ="http://www.cppblog.com/thronds/aggbug/78040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-03-27 15:34 <a href="http://www.cppblog.com/thronds/archive/2009/03/27/78040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高效开发与彻底测试 </title><link>http://www.cppblog.com/thronds/archive/2009/03/05/75651.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Thu, 05 Mar 2009 09:05:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/03/05/75651.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/75651.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/03/05/75651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/75651.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/75651.html</trackback:ping><description><![CDATA[一、“千般路”与“磨豆腐”

　　很久以前听一个故事：从前有个小伙子，少时有大志，长大后却无好营生，开了个豆腐作坊，每天磨豆腐累得腰酸背疼。每到夜深人静，小伙子辗转反侧，总想找条更好的“事业之路”，可是想过千百条、尝试过几十条路，都走不通。夜不成寝，白天干活更累，小伙子不由慨叹：“晚上想过千般路，白天还得磨豆腐”。

　　不久以前看过一篇文章：《CMM欺骗了中国的软件业》，内容是对CMM热的反思。CMM当然不会主动欺骗人，实际上是我们的软件业自己欺骗自己。我们从来不缺少“某某模式”，“面向某某”，“某某认证”等等听起来美妙无比的东西，问题是实际的研发过程中能做得到码？现实是残酷的，美妙的概念漫天飞舞，开发过程仍然是作坊式的，正是：“晚上想过千般路，白天还得磨豆腐”。

　　中国的故事通常都有圆满的结局，现在接着说“磨豆腐”的故事。过了很长时间，小伙子终于面对现实，不再沉迷于不切实际的空想，用心磨好豆腐，闲时琢磨些个窍门，慢慢地，他的豆腐质量越来越好，每天产量也越来越多，作坊越开越大，成了远近闻名的“豆腐老板”，后来，他做起了别的生意，发现年轻时的空想，其实很多都是可行的，因为现在“能力”和“财力”都不同了。

　　再说软件开发。我们不反对任何理论、技术、方法、模式等等，但第一，您的企业或团队做得到吗？不要做“如果开发时间延长一倍，就可以做到”之类毫无意义的假设。第二，做了真的有效益吗？效益是指扣除成本之后的收益。如果不具备这两点，那么还是不要整天想着“千般路”，首先想想如何好好的“磨豆腐”吧。

　　对于所有软件开发来说，代码编写都是无可逃避的“磨豆腐”。改进代码编写工作，高率效低成本地开发出高质量的代码，对于软件产品能否在激烈的竞争中胜出，对于软件企业的生存和发展，都具有重要的现实意义。

　　本文是Visual Unit应用的范例项目C++代码文档生成器的主题文档，叙述的正是改进代码编写工作的方法和工具，所有内容均经过实战检验，具有"可行"和"效益"两个特征，"可行"是指较低门槛或没有门槛，凭现有条件即可实施；"效益"是指能产生立竿见影的效果。

　　本文所援引的范例项目，模拟最糟糕的开发团队，最混乱的开发流程：由很少写代码的测试和预研部门开发，人员不固定，时间也不固定，谁有空就写上一些；没有设计，没有文档，基至也不在代码文件中保存编码人员的信息，成员完全依赖于阅读代码和测试用例来理解其他成员写的代码；除了简单的命名规则外，没有其他规范，甚至连一个函数原则上不能超过50行之类的基本规范也没有（范例中有超过200行的函数CMacro::Unwind()，一万多条路径）。任何开发团队和开发流程都会好于范例项目的开发团队和开发流程，因此，范例所展示的方法和工具，具有"广泛可行性"。

　　本文介绍如何进行高效编码调试和实现彻底的单元测试。编码调试是任何软件开发都无可逃避的工作，在Visual Unit的支持下编码调试，只是把本来就一定要做的工作改变一下方式，不需要多做什么，就可以大幅提高编程效率和质量；另一方面，Visual Unit彻底改变了单元测试难于实施或成本昂贵的局面，无论团队中开发与测试人员的比例是怎么样的，都可以轻松快捷地实现彻底的单元测试。

二、高效编码调试

　　任何软件开发，都离不开编码调试。对于稍为复杂一点的函数，一般来说，编写几行代码，就要执行一下，看它们是否按预想的工作，然后再继续写，写完后还要将各种可能输入都执行一下。如何执行？一般由别的代码来调用，也就是说需要驱动，驱动通常是在开始编写函数实现代码之前建立，这样才能一边编写一边调试。驱动大致可分为自然驱动和专门驱动。

　　自然驱动：利用项目中已有的代码作为驱动，通常是在被调试的函数中加断点，从界面执行一个需要调用该函数的功能，调试器中断时就可以调试了；专门驱动：为需要调试的函数编写专门的驱动代码，通过执行驱动代码来执行被调试函数。

自然驱动的主要优点是不需要其他工作就可以直接调试，甚至感觉不到需要驱动，主要缺点是输入数据通常是公共的，即很多代码都使用相同的输入源进行调试，实际输入往往是经过其他代码处理后的中间结果，要针对各种可能输入都进行调试往往很困难，造成调试不全面，程序员的思维受到局限，难于做到全面地考虑各种可能输入。

　　专门驱动的主要优点是输入数据是专门针对于被测试程序，容易做到比较全面，程序员的思维也会比较全面，对编写功能齐全的健壮的程序很有好处，要针对某种特定输入进行调试比较容易，缺点是需要花费大量的时间来编写驱动代码。

　　显然，自然驱动的主要问题是不全面，代码错误较多，专门驱动的主要问题是编写驱动代码很费时。有没有更好的方法，既不需要编写驱动代码，又能方便且全面地调试？有 ！这就是自动驱动，即在Visual Unit的支持下编码调试，不但无需费时间写驱动代码，更拥有多种独特的便利，可以大幅提高编码调试的质量和效率。

　　Visual Unit是单元测试工具，但也是高效编程调试的支持环境，在Visual Unit的支持下调试，既全面又省时：
　　自动生成驱动代码，但又可以方便地设定调试输入；
　　测试用例编辑器列出全部输入，可以很方便地检查是否全面。

　　除了上述优点外，在Visual Unit的支持下调试，还可以：
　　可视化地选择调试输入；
　　调试过程中还可以切换输入；
　　无限制的后退，重复。

　　上述仅是免费的个人版的功能，对于企业版用户，实际上大多数单步调试都可以省略：
自动输出参数、成员变量的输入输出值，返回值，用户也可以用简单的语法输出任何变量或表达式的值，这些数值都是上下文相关的；

　　显示在一个用例下，程序所执行的代码，可以很方便地查看程序是否按预想的流程执行。

　　程序无论多复杂，无非就是执行一些代码，读写、计算一些数据，因此，上述两方面信息已完整地描述了程序行为，一眼就能看出程序干了什么，通常可以很快判断程序是否按预想的工作并找到出错原因，比单步调试要快得多。

　　下面以实例来进一步分析三种调试方式的优缺点。这里所用的示例是范例项目中的CExFunction::ParseOneParameter()函数，这是一个很普通的函数，读者也可以随便拿其他有些复杂度的代码来比较。该函数的功能是解析C++代码中的一个参数，原形如下：


　　PARAMETER* CExFunction::ParseOneParameter(CTokenList&amp; iList); 
　　PARAMETER 是保存一个参数对象的结构，定义如下：

　　 struct PARAMETER

　　 {

　　 CString type; //参数类型

　　 CString name; //参数名

　　 CString defVal; //缺省值

　　 CString array; //如果参数是数组，保存[]及[]内的文字常量

　　 }; 

　　
　　参数iList是一个输入参数（范例的命名规则是用i表示输入参数），传递由C++代码中的一个参数经过词法分析转换获得的记号对象序列，例如参数int* pi，将转换为三个记号对象，分别对应于：int, *, pi。该函数将记号对象序列解析到一个PARAMETER结构的指针中，并作为返回值返回。

在这个示例中，如果要进行比较全面的调试，输入至少要考虑以下可能：
　　普通输入，如int i；
　　类型中有符号，如int* pi；
　　类型中有多个符号，如int*&amp; pi；
　　模板类，如CList list；
　　带缺省值，如int i=0；
　　数组，如int ai[10]；
　　类型有多个单词，如const unsigned int&amp; i；
　　缺少参数名，如const int；

　　我们在编写这个函数的实现代码前，首先建立调试驱动，以例边编码边执行调试。

　　
自然驱动

　　假设界面和要调用这个函数的其他代码都已完成。在函数的入口处插入断点，以调试方式运行工程，在界面中选择要生成文档的工程目录，点击"生成文档"，程序中断时就可以调试了。这种方式相信所有程序员都很熟悉，并且很多人都会认为这种方式最省时，但实际上，这种方式只是开头省时，当你试图把各个可能输入都调试一遍，就会发现它很费时：可能输入通常分散分布于输入源中（这里的输入源是代码文件），如果要比较全面地调试，通常要整理输入源，否则几乎不可能全面地调试，也就是说，要全面地调试，仍然要费时间整理输入，并不能完全依赖自然输入；

　　要针对某种输入进行调试，例如要调试参数带有缺省值的情形，一般通过反复跟踪直到想要的输入出现，或者设置条件断点拦截所需要输入，反复跟踪当然费时不少，设置条件断点也是要花时间的，并且有时无法满足需要 ，很多时候，要针对特殊输入进行调试都是很大费时的；

　　由于是公共输入源，输入数据很难管理，尤其是条件断点更不可能无限期地保存，以后需要再次调试时可能要做很多重复工作。
如上所述，自然驱动并不省时，不过这种方式的时间消耗隐藏在调试过程中，通常不会引起重视，其实"隐藏于调试过程中"，其成本更大，因为分散了开发人员的注意力，影响思维的连续性。

　　自然驱动的更主要问题是不全面，开发人员常常会将思维局限于现有的输入源，导致一些可能输入根本就没有考虑到，在本例中，很可能只是试一下解析一两个文件，检查得到的结果是否正确，如果文件中没有 带数组的参数，那这种输入很可能就被忽略掉。这种不全面，导致代码功能不齐，健壮性差，后期测试和维护成本居高不下，甚至导致项目的失败，因此，这是看起来高效，实际上很低效的方式，读者可以在看完后面两种方式的介绍后，自 已尝试并对比一下，可以拿任何有一定复杂度的代码编写来对比，不局限于这里所举的例子。

　　
专门驱动

　　专门驱动离单元测试只有一步之遥了，只要在驱动代码中添加判断预期输出的语句就构成了完整的测试代码，因此，在实际工作中，采用专门驱动最好是边编码边测试，并使用测试代码作为调试驱动。下面是为函数CExFunction::ParseOneParameter ()编写的调试驱动代码：

　　 {CExFunction* pObj = new CExFunction(); 

　　 CTokenList iList; 

　　 CTokenReader reader; 

　　 reader.ReadTokenList(iList, "int i"); 

　　 PARAMETER* ret = pObj-&gt;ParseOneParameter(iList) ; 

　　 ASSERT( ret-&gt;type == "int" ); 

　　 ASSERT( ret-&gt;name == "i" ); 

　　 reader.ClearTokenList(iList); 

　　 delete pParam; 

　　 delete pObj; }

　　 

　　上面的代码其实是一个测试用例的完整代码，测试代码通常都是很简单的，功能无非是使被测试的代码得于执行，被测试代码通常都涉及到外部数据，如参数、成员变量、全局变量什么的，这些数据当然要设定初始值，例如，上面的测试用例是将字符串"int i"经过CTokenReader对象的ReadTokenList方法转换成CToken对象指针的列表作为参数iList的输入。

　　在实际工作中，函数的输入输出常常不是简单的数据类型，而是某些对象甚至是对象的集合，本例中，输入的数据就是CToken对象指针的列表。这种情况下，一般借助现有的代码来生成数据，通常，这些"现在代码"都是存在的，因为即使不做测试，也总有代码要调用该函数的，调用代码本来就需要生成相应的数据。本例中，CTokenReader::ReadTokenList()函数就是把字符串转换为CToken对象指针的列表。

只要写完了第一个测试用例的代码，更多的用例就简单了，只要拷贝并对输入输出数据进行修改就行。细心的读都可能已注意到，第一个测试用例的前后加了{}，这是为了多个测试用例可以使用相同的变量名。

　　使用这种方法，建立测试代码通常是很快的。编写很简单的函数时不需要调试，当然也不需要测试代码。测试代码的组织也很简单：一个产品工程对应一个测试工程，一个产品类对应一个测试类，一个需要测试的产品函数对应一个测试函数。测试工程可以加一个简单的界面，以便执行指定的测试，也可以使用相应的工具如 CppUnit。

　　再回到我们的主题：调试。有了测试代码，调试就简单了，要调试某种输入，只要在相应的测试用例中加断点就行了。使用这种方式，仅就调试来说，好处也是非常明显的：
　　所有输入在一起列出来，调试比较全面，程序员的思维也会比较全面；
　　要调试指定的输入很容易，通常不需要高级断点，更不需要通过反复跟踪来捕捉需要的输入；
　　调试数据可以永久保存，避免了以后修改代码时的重复工作。

　　
自动驱动

　　在Visual Unit的支持下编码调试，除了兼具自然驱动和专门驱动的优点外，还能享受Visual Unit的独特殊功能带来的便利。

　　首先我们用个人版来说明，个人版是免费的版本，并且开发商也提供免费的基本技术支持。

　　Visual Unit具有丰富的文档，包括视频教程，这里不再叙述其基本使用方法。只要选择要测试(调试)的类和函数(如果使用企业版的IDE插件，会根据当前文档和光标位置自动选择)，VU就会生成测试代码，并弹出测试用例编译器。VU是自动生成测试代码，而不是自动生成测试用例，也就是说，输入输出数据是由用户指定的，不过VU已经生成了输入输出数据的声明。下面是本例中VU生成的第一个测试用例的输入输出：

　　输入部分：
CTokenList iList =

　　输出部分：
ret ==

　　这里的“=”和“==”仅仅表示可能需要赋值或判断输出，对于基本数据类型，可以直接填写数值，高级数据类型需要灵活处理(详细信息请查看帮助或教程)。只要把输入输出改为这样就完成了第一个测试用例的建立：

　　输入部分：

　　 CTokenList iList = //多余的=会自动删除

　　 CTokenReader reader

　　 reader.ReadTokenList(iList, "int i")

　　
输出部分：

　　 ret-&gt;type == "int"

　　 ret-&gt;name == "i"

　　
　　更多的测试用例，只要点击"新建"，就会自动拷贝当前用例，只要修改输入输出就行了。这里没有涉及到成员变量和变局全量，不过都很简单的(成员变量用点操作符访问，全局变量直接访问)，请查看帮助。

　　可以看出，使用VU建立调试支持环境是很快速的：对于第一个测试用例，输入输出比较复杂时需要写少量简单的代码，输入输出简单时直接填写输入输出数值，其他测试用例只需点击一个按钮拷贝现有测试用例并修改输入输出就行，可以选择相近的用例来生成新的用例，这样通常只需要修改一两个数据就可以得到想要的用例。

　　那么，还可以得到哪些好处呢？
　　方便地进入调式：在被调试函数的入口加断点，并调试测试工程即可进入调试；
　　方便地选择输入：在测试用例编辑器中轻点鼠标即可指定要调试的输入，如果执行了测试，只要点击出错的测试，就会自动选择相应的输入；
　　方便地切换输入：调试过程中，不需要退出调试，就可以切换到其他输入：只要在测试用例编辑器中选择另一个测试用例，用调试器的"执行到光标所在行"命令回到函数入口，即可切换到新的输入；
　　无限制后退重复：用调试器的"执行到光标所在行"命令可以自由地后退和重复执行，其实现的原理是"重来"，后退时相关数据也会"还原"，感觉上是真正的"后退"，这个奇特而有用的功能是VU生成的测试代码自动实现的。

　　上述是免费的个人版所具有功能，VU企业版除了具有这些功能外，还具有"描述程序行为"的功能：
　　自动输出参数、成员变量的输入输出值，返回值，用户也可以用简单的语法输出任何变量或表达式的值。这些数值都是上下文相关的，也就是说，同一个用例的相关值放在一起；

　　显示在任一个用例下程序所执行的代码，可以很方便地查看程序是否按预想的流程执行。
程序无论多复杂，无非就是执行一些代码，读写、计算一些数据，因此，上述两方面信息已完整地描述了程序行为，很容易看出"程序干了什么"。这个功能大幅度地提高了开发人员的工作效率：

　　帮助整理、验证编程思路：写几行代码，就可以看看"程序干了什么"，轻松判断"现在所写的对不对"，也比较容易想清楚"接下来要怎么写"。快速找出程序错误：根据输入输出数据和所执行的代码，通常可以很快判断程序是否按预期工作并找到出错原因，比单步调试要快得多。编程的时间消耗主要不在于敲键盘，而在于编程思路和调试，VU企业版可谓"对症下药"，在这两方面大量提高工作效率。

　　以上所述，都是针对软件开发过程中无可逃避的工作：编码调试。仅从时间上来说，对于编写调试有一定复杂度的程序，使用专门驱动，可能比自然驱动多费一点时间，但也是完全合算的，至于自动驱动，如果使用VU个人版，大概能省时10%，如果使用企业版，则可以省时20-50%!读者可以自行尝试比较一下。是否省时还不是最重要的，更高的价值在于：使用专门驱动或自动驱动编码调试，实际上也已经把令人望而生畏的单元测试工作完成了一半，并清除了实施单元测试的最主要障碍。

三、实现彻底单元测试

　　是什么使单元测试难于实施？首先是代码的可测性。可测性是什么？如果一个类具有基本的可测性，那么把它加入到另一个工程后（当然有关联的文件也要加入）能够通过编译，这其实是很低的要求，但对于一个有一定规模的项目，如果开发调试时使用自然驱动，在完成编码后才进行单元测试，那么通常都不具有可测性，因为开发人员常常在无意之中使代码之间产生了不当耦合，这些不当耦合累积起来，会使整个项目的代码纠缠在一起，造成难于测试。

　　使单元测试难于实施的另一个方面是建立测试用例。在本例中，如果由不熟悉代码的测试人员建立测试用例，那么他很可能不知道如何生成CToken对象 指针的列表。

　　如果边开发边使用专门驱动(测试代码放在另一个工程中)或自动驱动调试，那么一旦出现影响可测性的不当耦合就会及时发现及时解决，保证了代码的可测性，另一方面，由于至少建立了一个测试用例，测试人员建立其他用例时只要修改一下输入输出数据，从而大大降低建立测试用例的难度。总之，使用专门驱动或自动驱动调试，在不增加开发工作量的同时，已经为单元测试打一下了坚实的基础。

　　范例项目V0.1处于这样一个阶段：刚刚完成代码编写，并未完成单元测试，现有的多数测试用例都是编码时用于调试的。在此基础上，单元测试由谁做，难度都不大。VU的典型应用是通过三个 阶段来完成针对一个函数的彻底的测试：
　　1）基本功能测试：测试代码的基本功能；
　　2）完成白盒覆盖：在现有用例的基础上，使用测试用例设计器为未覆盖的语句、条件、分支、路径设计测试用例，达到100%语句、条件、分支、路径覆盖；
　　3）执行自动边界测试捕捉意料之外的错误。

　　以上三阶段可以由不同人员在不同时间完成，团队可以根据实际情况做出灵活安排，下面是一个典型的开发测试流程。

　　1）开发人员边开发边使用VU调试测试，完成基本功能测试。在VU的支持下开发调试，可以大幅提高开发效率，绝不会影响开发进度。也许读者会认为，开发人员没有时间去设计测试用例，其实这是一种误解，开发人员写代码时肯定要想清楚代码的功能并且要使用基本的输入进行调试，这些就是基本的测试用例，实际上不需要多做什么。开发人员提交代码同时提交测试代码和测试报告。如果项目已完成或部分完成编码，也建议先由程序员首先对重要代码进行基本的功能测试。
　　2）测试人员检查基本测试用例是否符合设计，并在此基础上完成白盒覆盖和边界测试。由于有了初步的测试，保证了代码可测性，不可能产生因为不当耦合造成难于测试的状况；在现有用例的基础上，使用测试用例设计器找出遗漏用例也不会有太大障碍，这就使测试人员的工作易于进行。测试人员只需要提交更新过的测试代码和测试报告，不需要另外记录测出的问题。
　　3）开发人员下载新的测试代码和测试报告，执行整体测试，然后针对报告了错误的函数执行函数测试以获取详细信息，必要时进行调试，找出错误，修改代码，使所有测试通过，再次提交产品代码和测试报告。
　　4）测试人员再次执行整体测试，验证所有的测试均已通过。

　　以上流程是动态和反复的，并不是编码完成后再单元测试。开发人员写完一个类后即可提交代码由测试人员完成白盒覆盖和边界测试。另外，团队可以根据开发与测试人员的比例调整工作份额，如果团队没有测试人员，那么由开发人员完成全部单元测试也是可行的。

　　彻底的单元测试对于软件开发来说，其价值是难于估量的：除了保证局部代码的质量外，有了单元测试，任何时候修改代码后都可以通过回归测试来自动检查修改是否引入错误，这就使开发过程可以适应频繁变化的需求，系统分析、概要设计和详细设计都可以做得简单一些，也更能适应螺旋式开发过程，以后的维护升级成本也会大幅降低，同时，高质量的代码使集成测试和系统测试的工作量降低很多(实际上单元测试已包含了大部分的集成测试)，发现问题后的修改也会高效得多。总之，要提高软件开发质量、降低软件开发成本，最有效的改进就是进行彻底的单元测试，如果不进行单元测试，任何流程改进都无法保证产品质量，因为，程序始终是由代码构成的，代码的质量没有保证，软件的质量拿什么来保证？单元测试并不排斥其他过程改进，相反，单元测试对开发流程中的所有环节几乎都有促进作用。

　　下边再谈谈关于白盒覆盖的话题。使用VU实施单元测试，100%的语句、条件、分支覆盖通常都是很容易的，路径覆盖有时候会很难，例如，我们所举的例子， CExFunction::ParseOneParameter ()，有九十多条路径，要覆盖似乎不现实或没必要，这种状况通常是设计不合理造成的，例如，CExFunction:: ParseOneParameter ()函数的代码分为三块：1、解析缺省值，2、解析数组，3、解析类型和参数名，前两块解析了缺省值和数组后把相应的Token从列表中删除，这样的话，第3块与前两块是没有逻辑关系的，但是，这3块代码会组合出很多路径，没有逻辑关系的代码所组合出来的路径是没有意义的，这些代码具有"高耦合低内聚"的特征，不应该放在一个函数中。范例中另外写了一个函数：CExFunction::ParseOneParameter2()，把以上三块代码分别独立出来自成一个函数，这样每个函数都能完成100%的路径覆盖，重构后的代码既易于测试，也易于维护。范例中有大量类似的函数，甚至有超过200行的函数，这是为了检验VU的适应能力，以后的版本是会进行重构。我们建议程序员完成编码后，检查一下路径数量，如果路径很多，代码很可能需要分拆，合理的路径数量应该是等价类数量的一至两倍。另外，从逻辑结构图也可以看出来：图中有两个或两个以上串联的复杂分支结构，往往表示代码的结构有问题。

　　VU的逻辑结构图具有屏蔽对象的功能，因此，遇到上述情形时可以通过交替屏蔽部分分支结构的方式来实现路径覆盖，但这不是我们推荐的方式，因为它虽然可以保证测试的完整性，但并没有改进代码的结构。

　　关于单元测试和范例项目，还有很多值得叙述的话题，例如内存泄漏测试以及一些复杂问题的处理等等，这里暂且不谈。最后谈谈已完成编码的项目的单元测试。对于已完成编码的项目，最好先由开发人员"去耦合"，方法是将代码文件从底层向上排列，按顺序依次将文件加入到另一个工程并编译，如果产生编译错误，则想办法消除编译错误 ，VU提供了文件排序工具，具体的使用方法请查阅帮助中《测试旧工程》部分。完成“去耦合”后，由开发人员对自己编写的代码完成基本功能测试，测试人员完成白盒覆盖和边界测试。对于编码过程中使用自然驱动调试的已完成编写的代码，完全由测试部门进行单元测试通常是很难的。

    来自：http://www.rjzl.gov.cn/news.asp?id=2351<img src ="http://www.cppblog.com/thronds/aggbug/75651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-03-05 17:05 <a href="http://www.cppblog.com/thronds/archive/2009/03/05/75651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vnc server配置(server&amp;client)詳細</title><link>http://www.cppblog.com/thronds/archive/2009/02/19/74323.html</link><dc:creator>thronds</dc:creator><author>thronds</author><pubDate>Thu, 19 Feb 2009 12:12:00 GMT</pubDate><guid>http://www.cppblog.com/thronds/archive/2009/02/19/74323.html</guid><wfw:comment>http://www.cppblog.com/thronds/comments/74323.html</wfw:comment><comments>http://www.cppblog.com/thronds/archive/2009/02/19/74323.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/thronds/comments/commentRss/74323.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/thronds/services/trackbacks/74323.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 由于客户需要充分利用花了N多money购买的服务器，而服务器上运行的是Linux AS,客户又不太会使用文本模式，因此只好采用配置X-server的方式来给每一个用户一个图形终端了，这多亏了X-windows设计的先进性呀。 <br>为了简单，我就使用了Linux自带的vnc-server。 &nbsp;&nbsp;<a href='http://www.cppblog.com/thronds/archive/2009/02/19/74323.html'>阅读全文</a><img src ="http://www.cppblog.com/thronds/aggbug/74323.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/thronds/" target="_blank">thronds</a> 2009-02-19 20:12 <a href="http://www.cppblog.com/thronds/archive/2009/02/19/74323.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>