平时记录的
Last edited May 26, 2009
More by joe »
Sections:
面向对象的三个基本特征 - C++编程 - purple_lotuses
blog.chinaunix.net/u/23975/showart_352478.html
面向对象的三个基本特征  UML图例说明对象的关系

面向对象的三个基本特征(讲解)

面向对象的三个基本特征是:封装、继承、多态。

o_OOBase.gif

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承

面向对象编程 (OOP) 语言的一个主要功能就是继承。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为基类父类超类

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过继承Inheritance)和组合Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

 

继承概念的实现方式有三类:实现继承、接口继承和可视继承。

Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;

Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

Ø         可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是属于关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。

抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class

OO开发范式大致为:划分对象抽象类将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

 

多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

实现多态,有二种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

其实,重载的概念并不属于面向对象编程,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_funcstr_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是覆盖。 当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法 确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对 象也无关!引用一句Bruce Eckel的话:不要犯傻,如果它不是晚邦定,它就不是多态。

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用家谱中任一类的实例的某一属性时的正确调用。

 

概念讲解

泛化(Generalization

o_Generalization.gif

图表 1 泛化

在上图中,空心的三角表示继承关系(类继承),在UML的术语中,这种关系被称为泛化(Generalization)。Person()是基类,Teacher(教师)Student(学生)Guest(来宾)是子类。

若在逻辑上BA的“一种”,并且A的所有功能和属性对B而言都有意义,则允许B继承A的功能和属性。

例如,教师是人,Teacher Person的“一种”(a kind of )。那么类Teacher可以从类Person派生(继承)。

如果A是基类,BA的派生类,那么B将继承A的数据和函数。

如果类A和类B毫不相关,不可以为了使B的功能更多些而让B继承A的功能和属性。

若在逻辑上BA的“一种”(a kind of ),则允许B继承A的功能和属性。

 

聚合(组合)

o_aggregationBase.gif

图表 2 组合

若在逻辑上AB的“一部分”(a part of),则不允许BA派生,而是要用A和其它东西组合出B

例如,眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head应该由类EyeNoseMouthEar组合而成,不是派生(继承)而成。

 

聚合的类型分为无、共享(聚合)、复合(组合)三类。

 

聚合(aggregation

 

o_aggregation.gif

图表 3 共享

上面图中,有一个菱形(空心)表示聚合(aggregation)(聚合类型为共享),聚合的意义表示has-a关系。聚合是一种相对松散的关系,聚合类B不需要对被聚合的类A负责。

 

组合(composition

o_composition.gif

图表 4 复合

这幅图与上面的唯一区别是菱形为实心的,它代表了一种更为坚固的关系——组合(composition)(聚合类型为复合)。组合表示的关系也是has-a,不过在这里,A的生命期受B控制。即A会随着B的创建而创建,随B的消亡而消亡。

 

依赖(Dependency)

o_Dependency.gif

图表 5 依赖

这里BA的关系只是一种依赖(Dependency)关系,这种关系表明,如果类A被修改,那么类B会受到影响。 
Google Sync手机在线同步工具使用指南_Google / 谷歌_cnBeta.COM
www.cnbeta.com/articles/76713.htm
参考知识: 4.1、关于Syncml
    SyncML是一种唯一行业通用的移动数据同步化协议,由SyncML initiative发行,是一种开放性协议。SyncML协议的目的是解决移动设备和网络之间的数据同步和设备管理问题。在SyncML之前,数据同步 和设备管理是基于各种私有协议实现的,每种协议只能支持有限的设备和数据类型。各种协议间不能互通,这就限制了用户的数据访问、传输和移动性。

    SyncML的主要目的有两方面:
  • 可以通过任何移动设备将网络数据同步化。
  • 移动设备中的数据也可以用任何网络数据同步化。
  • SyncML协议特性:
  • 可以在不同的网络上工作–包括有线网络和无线网络.
  • 支持多种传输协议,包括HTTP,WSP,OBEX,SMTP,Pure TCP/IP.
  • 支持通用的个人数据格式,如vCard,vCalendar和E-MAIL等.
  • 考虑到移动设备的资源限制,对移动设备的存储空间进行了优化.
  • 建立在internet协议和web技术上,是可执行而且有很好的协作性的.
  • 协议最小功能就是赋予所有设备最常用的同步能力
4.2、Syncml的7种同步模式
syncml sync mode
4.3、SyncML Protocol Architecture
syncml
Web 前端优化最佳实践之 JavaScript 篇 - DBA notes
www.dbanotes.net/web/best_practices_for_speeding_u...

Web 前端优化最佳实践之 JavaScript 篇

作者: Fenng | 可以转载, 转载时务必以超链接形式标明文章原始出处和作者信息及版权声明
网址: http://www.dbanotes.net/web/best_practices_for_speeding_up_your_web_site_javascript.html

Web 前端优化最佳实践之 JavaScript 篇,这部分有 6 条规则,和 CSS 篇 重复的有几条。前端优化最佳实践,最重要的还是"实践",要理解这东西容易得很,关键是要去"实践",去"执行",去"反馈",去获取受益。

1. 脚本放到 HTML 代码页底部 (Put Scripts at the Bottom)

当一个脚本在下载的时候,浏览器干不了其它的事儿(串行了)。所以,把它扔到最后面去处理。对于一些功能性的脚本,可能实现起来有些两难。不过对于国内网站来说,有很多使用 Google Analytics 服务进行网站数据分析的。这这一点来说,绝对可行的建议,放到页面最底下。

2. Make JavaScript and CSS External

参见 CSS 篇的描述

3. 精简 JavaScript 与 CSS (Minify JavaScript and CSS)

参见 CSS 篇的描述

4. 移除重复脚本 (Remove Duplicate Scripts)

对于一些历史遗留站点或是论坛类的网站来说,这倒是比较常见的。接手维护人前后变化过多,每个人都有自己的一套。这就会带来一些潜在的麻烦。

5. 减少 DOM 访问 (Minimize DOM Access)

有三条指导建议:
  • 缓存已经访问过的元素 (Cache references to accessed elements)
  • "离线"更新节点, 再将它们添加到树中 (Update nodes "offline" and then add them to the tree)
  • 避免使用 JavaScript 输出页面布局--应该是 CSS 的事儿 (Avoid fixing layout with JavaScript)

6. Develop Smart Event Handlers

除了英文解释外,这里也提醒一下注意关于 Java Script 内存泄漏的问题。

另外推荐一篇《如何优化 JavaScript 脚本的性能》,关于 Ajax 优化指导原则,可以参见 提高 Ajax 应用程序性能,避开 Web 服务漏洞

后记1) :整理得差不多之后,发现网络上已经有一篇 《Yahoo!网站性能最佳体验的34条黄金守则》,是翻译稿。看来我做了一部分重复劳动。

后记 2):CSS / JavaScript 都有优化规则。但似乎缺少了对 Flash 的优化实践。

--EOF--

如何设置虚拟IP? - 我的文章 - linux ubuntu学习园地1025
blog.chinaunix.net/u2/81758/showart_1285686.html
#ifconfig eth0:0 192.168.0.1 netmask 255.255.255.0 up

#ifconfig eth0:1 192.168.0.2 netmask 255.255.255.0 up

#ping 192.168.0.1

#ping 192.168.0.2
ping测试通过,就完成了单网卡配置多ip的功能。reboot以后发现ip地址变了回去。
所以必须设置启动时自动激活ip设置
第一种:
将上边的命令ifconfig加入到rc.local中去
第二种:
就是仿照/etc/sysconfig/network-scripts/ifcfg-eth0增加一文件根据网络虚拟接口的名字进行命名
例如ifcfg-eth0:0或者ifcfg-eth0:1等等

#下边看下ifcfg-eth0:0文件里面的配置信息
DEVICE=eth0:0 #网络虚拟接口eth0:0
ONBOOT=yes #启动的时候激活
BOOTPROTO=static #使用静态ip地址
IPADDR=192.168.0.1 #分配ip地址
NETMASK=255.255.255.0 #子网掩码

其他配置文件类似。重启ping测试,配置成功。
今天看了别人的没看明白自己试了试才知道具体如何操作。
如何关闭一个ip呢则使用

#ifconfig eth*[:x] down(*代表的是网卡编号,x代表虚拟接口号0-255)
查看ip配置信息:

#ifconfig

btw:用netconfig更方便啊!!!!!!!!!!!!

请问斑竹设置这样的多个IP有什么用处?
《零-八-憲—章》 - 且行且吟唱 - 博客大巴
iamgodbug.blogbus.com/logs/32323383.html
  • 零-八-憲-章

    2008年12月

    一、前言

    今年是中国立宪百年,《世界人权宣言》公布60周年,“民主墙”诞生30周年,中国政府签署《公民权利和政治权利国际公约》10周年。在经历了长期的人权灾难和艰难曲折的抗争历程之后,觉醒的中国公民日渐清楚地认识到,自由、平等、人权是人类共同的普世价值;民主、共和、宪政是现代政治的基本制度架构。抽离了这些普世价值和基本政制架构的“现代化”,是剥夺人的权利、腐蚀人性、摧毁人的尊严的灾难过程。21世纪的中国将走向何方,是继续这种威权统治下的“现代化”,还是认同普世价值、融入主流文明、建立民主政体?这是一个不容回避的抉择。

    19世纪中期的历史巨变,暴露了中国传统专制制度的腐朽,揭开了中华大地上“数千年未有之大变局”的序幕。洋务运动追求器物层面的进良,甲午战败再次暴露了体制的过时;戊戌变法触及到制度层面的革新,终因顽固派的残酷镇压而归于失败;辛亥革命在表面上埋葬了延续2000多年的皇权制度,建立了亚洲第一个共和国。囿于当时内忧外患的特定历史条件,共和政体只是昙花一现,专制主义旋即卷土重来。器物模仿和制度更新的失败,推动国人深入到对文化病根的反思,遂有以“科学与民主”为旗帜的“五四”新文化运动,因内战频仍和外敌入侵,中国政治民主化历程被迫中断。抗日战争胜利后的中国再次开启了宪政历程,然而国共内战的结果使中国陷入了现代极权主义的深渊。1949年建立的“新中国”,名义上是“人民共和国”,实质上是“党天下”。执政党垄断了所有政治、经济和社会资源,制造了反右、大跃进、文革、***、打压民间宗教活动与维权运动等一系列人权灾难,致使数千万人失去生命,国民和国家都付出了极为惨重的代价。

    二十世纪后期的“改革开放”,使中国摆脱了***时代的普遍贫困和绝对极权,民间财富和民众生活水平有了大幅度提高,个人的经济自由和社会权利得到部分恢复,公民社会开始生长,民间对人权和政治自由的呼声日益高涨。执政者也在进行走向市场化和私有化的经济改革的同时,开始了从拒绝人权到逐渐承认人权的转变。中国政府于1997年、1998年分别签署了两个重要的国际人权公约,全国人大于2004年通过修宪把“尊重和保障人权”写进宪法,今年又承诺制订和推行《国家人权行动计划》。但是,这些政治进步迄今为止大多停留在纸面上;有法律而无法治,有宪法而无宪政,仍然是有目共睹的政治现实。执政集团继续坚持维系威权统治,排拒政治变革,由此导致官场腐败,法治难立,人权不彰,道德沦丧,社会两极分化,经济畸形发展,自然环境和人文环境遭到双重破坏,公民的自由、财产和追求幸福的权利得不到制度化的保障,各种社会矛盾不断积累,不满情绪持续高涨,特别是官民对立激化和群体事件激增,正在显示着灾难性的失控趋势,现行体制的落伍已经到了非改不可的地步。

    二、我们的基本理念

    当此决定中国未来命运的历史关头,有必要反思百年来的现代化历程,重申如下基本理念:

    自由:自由是普世价值的核心之所在。言论、出版、信仰、集会、结社、迁徙、罢工和游行示威等权利都是自由的具体体现。自由不昌,则无现代文明可言。

    人权:人权不是国家的赐予,而是每个人与生俱来就享有的权利。保障人权,既是政府的首要目标和公共权力合法性的基础,也是“以人为本”的内在要求。中国的历次政治灾难都与执政当局对人权的无视密切相关。人是国家的主体,国家服务于人民,政府为人民而存在。

    平等:每一个个体的人,不论社会地位、职业、性别、经济状况、种族、肤色、宗教或政治信仰,其人格、尊严、自由都是平等的。必须落实法律面前人人平等的原则,落实公民的社会、经济、文化、政治权利平等的原则。

    共和:共和就是“大家共治,和平共生”,就是分权制衡与利益平衡,就是多种利益成分、不同社会集团、多元文化与信仰追求的群体,在平等参与、公平竞争、共同议政的基础上,以和平的方式处理公共事务。

    民主:最基本的涵义是主权在民和民选政府。民主具有如下基本特点:(1)政权的合法性来自人民,政治权力来源于人民;(2)政治统治经过人民选择,(3)公民享有真正的选举权,各级政府的主要政务官员必须通过定期的竞选产生。(4)尊重多数人的决定,同时保护少数人的基本人权。一句话,民主使政府成为“民有,民治,民享”的现代公器。

    宪政:宪政是通过法律规定和法治来保障宪法确定的公民基本自由和权利的原则,限制并划定政府权力和行为的边界,并提供相应的制度设施。

    在中国,帝国皇权的时代早已一去不复返了;在世界范围内,威权体制也日近黄昏;公民应该成为真正的国家主人。祛除依赖“明君”、“清官”的臣民意识,张扬权利为本、参与为责的公民意识,实践自由,躬行民主,尊奉法治,才是中国的根本出路。

    三、我们的基本主张

    藉此,我们本着负责任与建设性的公民精神对国家政制、公民权利与社会发展诸方面提出如下具体主张:

    1、修改宪法:根据前述价值理念修改宪法,删除现行宪法中不符合主权在民原则的条文,使宪法真正成为人权的保证书和公共权力的许可状,成为任何个人、团体和党派不得违反的可以实施的最高法律,为中国民主化奠定法权基础。

    2、分权制衡:构建分权制衡的现代政府,保证立法、司法、行政三权分立。确立法定行政和责任政府的原则,防止行政权力过分扩张;政府应对纳税人负责;在中央和地方之间建立分权与制衡制度,中央权力须由宪法明确界定授权,地方实行充分自治。

    3、立法民主:各级立法机构由直选产生,立法秉持公平正义原则,实行立法民主。

    4、司法独立:司法应超越党派、不受任何干预,实行司法独立,保障司法公正;设立宪法法院,建立违宪审查制度,维护宪法权威。尽早撤销严重危害国家法治的各级党的政法委员会,避免公器私用。

    5、公器公用:实现军队国家化,军人应效忠于宪法,效忠于国家,政党组织应从军队中退出,提高军队职业化水平。包括警察在内的所有公务员应保持政治中立。消除公务员录用的党派歧视,应不分党派平等录用。

    6、人权保障:切实保障人权,维护人的尊严。设立对最高民意机关负责的人权委员会,防止政府滥用公权侵犯人权,尤其要保障公民的人身自由,任何人不受非法逮捕、拘禁、传讯、审问、处罚,废除劳动教养制度。

    7、公职选举:全面推行民主选举制度,落实一人一票的平等选举权。各级行政首长的直接选举应制度化地逐步推行。定期自由竞争选举和公民参选法定公共职务是不可剥夺的基本人权。

    8、城乡平等:废除现行的城乡二元户籍制度,落实公民一律平等的宪法权利,保障公民的自由迁徙权。

    9、结社自由:保障公民的结社自由权,将现行的社团登记审批制改为备案制。开放党禁,以宪法和法律规范政党行为,取消一党垄断执政特权,确立政党活动自由和公平竞争的原则,实现政党政治正常化和法制化。

    10、集会自由:和平集会、游行、示威和表达自由,是宪法规定的公民基本自由,不应受到执政党和政府的非法干预与违宪限制。

    11、言论自由:落实言论自由、出版自由和学术自由,保障公民的知情权和监督权。制订《新闻法》和《出版法》,开放报禁,废除现行《刑法》中的“煽动颠覆国家政权罪”条款,杜绝以言治罪。

    12、宗教自由:保障宗教自由与信仰自由,实行政教分离,宗教信仰活动不受政府干预。审查并撤销限制或剥夺公民宗教自由的行政法规、行政规章和地方性法规;禁止以行政立法管理宗教活动。废除宗教团体(包括宗教活动场所)必经登记始获合法地位的事先许可制度,代之以无须任何审查的备案制。

    13、公民教育:取消服务于一党统治、带有浓厚意识形态色彩的政治教育与政治考试,推广以普世价值和公民权利为本的公民教育,确立公民意识,倡导服务社会的公民美德。

    14、财产保护:确立和保护私有财产权利,实行自由、开放的市场经济制度,保障创业自由,消除行政垄断;设立对最高民意机关负责的国有资产管理委员会,合法有序地展开产权改革,明晰产权归属和责任者;开展新土地运动,推进土地私有化,切实保障公民尤其是农民的土地所有权。

    15、财税改革:确立民主财政和保障纳税人的权利。建立权责明确的公共财政制度构架和运行机制,建立各级政府合理有效的财政分权体系;对赋税制度进行重大改革,以降低税率、简化税制、公平税负。非经社会公共选择过程,民意机关决议,行政部门不得随意加税、开征新税。通过产权改革,引进多元市场主体和竞争机制,降低金融准入门槛,为发展民间金融创造条件,使金融体系充分发挥活力。

    16、社会保障:建立覆盖全体国民的社会保障体制,使国民在教育、医疗、养老和就业等方面得到最基本的保障。

    17、环境保护:保护生态环境,提倡可持续发展,为子孙后代和全人类负责;明确落实国家和各级官员必须为此承担的相应责任;发挥民间组织在环境保护中的参与和监督作用。

    18、联邦共和:以平等、公正的态度参与维持地区和平与发展,塑造一个负责任的大国形象。维护香港、澳门的自由制度。在自由民主的前提下,通过平等谈判与合作互动的方式寻求海峡两岸和解方案。以大智慧探索各民族共同繁荣的可能途径和制度设计,在民主宪政的架构下建立中华联邦共和国。

    19、转型正义:为历次政治运动中遭受政治迫害的人士及其家属,恢复名誉,给予国家赔偿;释放所有政治犯和良心犯,释放所有因信仰而获罪的人员;成立真相调查委员会,查清历史事件的真相,厘清责任,伸张正义;在此基础上寻求社会和解。

    四、结语

    中国作为世界大国,作为联合国安理会五个常任理事国之一和人权理事会的成员,理应为人类和平事业与人权进步做出自身的贡献。但令人遗憾的是,在当今世界的所有大国里,唯独中国还处在威权主义政治生态中,并由此造成连绵不断的人权灾难和社会危机,束缚了中华民族的自身发展,制约了人类文明的进步——这种局面必须改变!政治民主化变革不能再拖延下去。

    为此,我们本着勇于践行的公民精神,公布《零八宪章》。我们希望所有具有同样危机感、责任感和使命感的中国公民,不分朝野,不论身份,求同存异,积极参与到公民-运动中来,共同推动中国社会的伟大变革,以期早日建成一个自由、民主、宪政的国家,实现国人百余年来锲而不舍的追求与梦想。

    已有签署人:303人

    于浩成(北京,法学家)
    张思之(北京,律师)
    茅于轼(北京,经济学家)
    杜 光 (北京,政治学家)
    李 普 (北京,老记者)
    沙叶新(上海,剧作家)
    流沙河(四川,诗人)
    鲍 彤(北京,公民)
    刘军宁(北京,政治学家)
    徐友渔(北京,哲学家)
    贺卫方(北京,法学家)
    莫少平(北京,律师)
    陈子明(北京,学者)
    张博树(北京,政治学家)
    崔卫平(北京,学者
    李大同(北京,记者)
    张 鸣(北京,教授)
    ……

    本宪章为开放签名。 签名信箱:2008xianzhang@gmail.com2008xianzhang2008@gmail.com

    随机文章:

    讨伐中喧布 2008-09-24
    农民工 2008-03-06

    收藏到:Del.icio.us




    Tag:
    引用地址:
    臭虫 发表于20:59:33 | 编辑 | 继续话题 | 转发 | 分享

    评论

  • 是刘晓波,喊口号前也得做做功课
    臭虫 | 发表于2008-12-14 17:39:13 [回复]
  • 刘小波他们303个勇士是中华民族的脊梁
    ddwe | 发表于2008-12-13 21:29:37 [回复]
  • 声援刘小波,营救刘小波
    ddwe | 发表于2008-12-13 21:27:53 [回复]
  • 我坚决支持
    ddwe | 发表于2008-12-13 21:24:55 [回复]
  • 08宪章唤醒了广大的劳动人民。能够使中国真正走向民主富强的道路;使中华民族迎头赶上其它的世界民族。能够让我们的子孙后代有着极好的人权。
    ddwe | 发表于2008-12-13 21:23:46 [回复]
  • 08宪章好,确实好
    ddwe | 发表于2008-12-13 21:18:08 [回复]
  • 中国的经济总量超过美国?以中国目前的经济结构和政治制度,经济总量有可能超过美国吗?ZJ在开玩笑吧!
    搞当然会有产生问题,但不搞,问题更大。虽然我不认同太过于激进的变革,但变革是必须的,中国在所谓“和谐、稳定”的幌子下已是大厦将倾的一幢危房了.
    臭虫 | 发表于2008-12-12 23:00:09 [回复]
  • 等中国经济总量超过美国再讨论这事 现在搞容易出问题
    zj | 发表于2008-12-10 10:06:30 [回复]
  • 附:联合国《世界人权宣言》

    联合国大会1948年12月10日第217A(III)号决议通过并颁布《世界人权宣言》。这一具有历史意义的《宣言》颁布后,大会要求所有会员国广为宣传,并且“不分国家或领土的政治地位,主要在各级学校和其他教育机构加以传播、展示、阅读和阐述。”《宣言》全文如下:


    序 言
    鉴于对人类家庭所有成员的固有尊严及其平等的和不移的权利的承认,乃是世界自由、正义与和平的基础,

    鉴于对人权的无视和侮蔑已发展为野蛮暴行,这些暴行玷污了人类的良心,而一个人人享有言论和信仰自由并免予恐惧和匮乏的世界的来临,已被宣布为普通人民的最高愿望,

    鉴于为使人类不致迫不得已铤而走险对暴政和压迫进行反叛,有必要使人权受法治的保护,

    鉴于有必要促进各国间友好关系的发展,

    鉴于各联合国国家的人民已在联合国宪章中重申他们对基本人权、人格尊严和价值以及男女平等权利的信念,并决心促成较大自由中的社会进步和生活水平的改善,

    鉴于各会员国业已誓愿同联合国合作以促进对人权和基本自由的普遍尊重和遵行,

    鉴于对这些权利和自由的普遍了解对于这个誓愿的充分实现具有很大的重要性,


    因此现在, 大会, 发布这一世界人权宣言,作为所有人民和所有国家努力实现的共同标准,以期每一个人和社会机构经常铭念本宣言,努力通过教诲和教育促进对权利和自由的尊重,并通过国家的和国际的渐进措施,使这些权利和自由在各会员国本身人民及在其管辖下领土的人民中得到普遍和有效的承认和遵行;
    第一条
    人人生而自由,在尊严和权利上一律平等。他们赋有理性和良心,并应以兄弟关系的精神相对待。

    第二条
    人人有资格享有本宣言所载的一切权利和自由,不分种族、肤色、性别、语言、宗教、政治或其他见解、国籍或社会出身、财产、出生或其他身分等任何区别。

    并且不得因一人所属的国家或领土的政治的、行政的或者国际的地位之不同而有所区别,无论该领土是独立领土、托管领土、非自治领土或者处于其他任何主权受限制的情况之下。

    第三条
    人人有权享有生命、自由和人身安全。

    第四条
    任何人不得使为奴隶或奴役;一切形式的奴隶制度和奴隶买卖,均应予以禁止。

    第五条
    任何人不得加以酷刑,或施以残忍的、不人道的或侮辱性的待遇或刑罚。

    第六条
    人人在任何地方有权被承认在法律前的人格。

    第七条
    法律之前人人平等,并有权享受法律的平等保护,不受任何歧视。人人有权享受平等保护,以免受违反本宣言的任何歧视行为以及煽动这种歧视的任何行为之害。

    第八条
    任何人当宪法或法律所赋予他的基本权利遭受侵害时,有权由合格的国家法庭对这种侵害行为作有效的补救。

    第九条
    任何人不得加以任意逮捕、拘禁或放逐。

    第十条
    人人完全平等地有权由一个独立而无偏倚的法庭进行公正的和公开的审讯,以确定他的权利和义务并判定对他提出的任何刑事指控。

    第十一条
    ㈠ 凡受刑事控告者,在未经获得辩护上所需的一切保证的公开审判而依法证实有罪以前,有权被视为无罪。

    ㈡ 任何人的任何行为或不行为,在其发生时依国家法或国际法均不构成刑事罪者,不得被判为犯有刑事罪。刑罚不得重于犯罪时适用的法律规定。

    第十二条
    任何人的私生活、家庭、住宅和通信不得任意干涉,他的荣誉和名誉不得加以攻击。人人有权享受法律保护,以免受这种干涉或攻击。

    第十三条
    ㈠ 人人在各国境内有权自由迁徙和居住。

    ㈡ 人人有权离开任何国家,包括其本国在内,并有权返回他的国家。

    第十四条
    ㈠ 人人有权在其他国家寻求和享受庇护以避免迫害。

    ㈡ 在真正由于非政治性的罪行或违背联合国的宗旨和原则的行为而被起诉的情况下,不得援用此种权利。

    第十五条
    ㈠ 人人有权享有国籍。

    ㈡ 任何人的国籍不得任意剥夺,亦不得否认其改变国籍的权利。

    第十六条
    ㈠ 成年男女,不受种族、国籍或宗教的任何限制有权婚嫁和成立家庭。他们在婚姻方面,在结婚期间和在解除婚约时,应有平等的权利。

    ㈡ 只有经男女双方的自由和完全的同意,才能缔婚。

    ㈢ 家庭是天然的和基本的社会单元,并应受社会和国家的保护。

    第十七条
    ㈠ 人人得有单独的财产所有权以及同他人合有的所有权。

    ㈡ 任何人的财产不得任意剥夺。

    第十八条
    人人有思想、良心和宗教自由的权利;此项权利包括改变他的宗教或信仰的自由,以及单独或集体、公开或秘密地以教义、实践、礼拜和戒律表示他的宗教或信仰的自由。

    第十九条
    人人有权享有主张和发表意见的自由;此项权利包括持有主张而不受干涉的自由,和通过任何媒介和不论国界寻求、接受和传递消息和思想的自由。

    第二十条
    ㈠ 人人有权享有和平集会和结社的自由。

    ㈡ 任何人不得迫使隶属于某一团体。

    第二十一条
    ㈠ 人人有直接或通过自由选择的代表参与治理本国的权利。

    ㈡ 人人有平等机会参加本国公务的权利。

    ㈢ 人民的意志是政府权力的基础;这一意志应以定期的和真正的选举予以表现,而选举应依据普遍和平等的投票权,并以不记名投票或相当的自由投票程序进行。

    第二十二条
    每个人,作为社会的一员,有权享受社会保障,并有权享受他的个人尊严和人格的自由发展所必需的经济、社会和文化方面各种权利的实现,这种实现是通过国家努力和国际合作并依照各国的组织和资源情况。

    第二十三条
    ㈠ 人人有权工作、自由选择职业、享受公正和合适的工作条件并享受免于失业的保障。

    ㈡ 人人有同工同酬的权利,不受任何歧视。

    ㈢ 每一个工作的人,有权享受公正和合适的报酬,保证使他本人和家属有一个符合人的生活条件,必要时并辅以其他方式的社会保障。

    ㈣ 人人有为维护其利益而组织和参加工会的权利。

    第二十四条
    人人有享有休息和闲暇的权利,包括工作时间有合理限制和定期给薪休假的权利。

    第二十五条
    ㈠ 人人有权享受为维持他本人和家属的健康和福利所需的生活水准,包括食物、衣着、住房、医疗和必要的社会服务;在遭到失业、疾病、残废、守寡、衰老或在其他不能控制的情况下丧失谋生能力时,有权享受保障。

    ㈡ 母亲和儿童有权享受特别照顾和协助。一切儿童,无论婚生或非婚生,都应享受同样的社会保护。

    第二十六条
    ㈠ 人人都有受教育的权利,教育应当免费,至少在初级和基本阶段应如此。初级教育应属义务性质。技术和职业教育应普遍设立。高等教育应根据成绩而对一切人平等开放。

    ㈡ 教育的目的在于充分发展人的个性并加强对人权和基本自由的尊重。教育应促进各国、各种族或各宗教集团间的了解、容忍和友谊,并应促进联合国维护和平的各项活动。

    ㈢ 父母对其子女所应受的教育的种类,有优先选择的权利。

    第二十七条
    ㈠ 人人有权自由参加社会的文化生活,享受艺术,并分享科学进步及其产生的福利。

    ㈡ 人人对由于他所创作的任何科学、文学或美术作品而产生的精神的和物质的利益,有享受保护的权利。

    第二十八条
    人人有权要求一种社会的和国际的秩序,在这种秩序中,本宣言所载的权利和自由能获得充分实现。

    第二十九条
    ㈠ 人人对社会负有义务,因为只有在社会中他的个性才可能得到自由和充分的发展。

    ㈡ 人人在行使他的权利和自由时,只受法律所确定的限制,确定此种限制的唯一目的在于保证对旁人的权利和自由给予应有的承认和尊重,并在一个民主的社会中适应道德、公共秩序和普遍福利的正当需要。

    ㈢ 这些权利和自由的行使,无论在任何情形下均不得违背联合国的宗旨和原则。

    第三十条
    本宣言的任何条文,不得解释为默许任何国家、集团或个人有权进行任何旨在破坏本宣言所载的任何权利和自由的活动或行为。
让Java程序作为linux的Daemon后台运行 - log4deng - BlogJava
www.blogjava.net/qiyadeng/archive/2008/04/11/29171...

因为需要对网络环境进行监控,做了个Java程序在linux服务器上运行。但是每次重新启动的时候都要手动的运行,这样就不太现实。所以想到把Java程序做成像Windows的系统服务那样,开机就会自动在后台运行。以前使用过一个工具http://javaservice.objectweb.org/,可以把Java程序注册成为Windows的系统服务,而且使用起来很简单,但是遗憾的是该工具不能注册linux的后台服务。所以不得不另外寻找工具。

 

   最后找到了JavaService Wrapper(http://wrapper.tanukisoftware.org/doc/english/introduction.html),该工具能在很多中平台下面注册为系统服务(查看支持平台)。该工具使用方法有三种模式,我用的是第一种WrapperSimpleApp帮助类,另外的两种方式都需要在原来的程序上进行适当的编码。下面就用我的程序NetWatchDog为例子说明下大概的配置步骤。(其实文档中已经用Jboss进行了演示)

 

1.建立一个目录名为NetWatchDog,并在该目录下建立bin,lib,conf,logs目录。以下把NetWatchDog目录称为$DOG_HOME。

2.把下载来的文件解压,把$WRAPPER_HOME/bin/wrapper,$WRAPPER_HOME/src/bin/sh.script.in文件copy到$DOG_HOME/bin目录中。

3.把sh.script.in文件该名为你的服务名称,这里改为NetWatchDog。

4.编辑NetWatchDog,把Application的相关信息改为如下:

APP_NAME="NetWatchDog"
APP_LONG_NAME="NetWatchDog Application"

5.把你的程序的打包成jar文件,拷贝到$DOG_HOME/lib目录下,并把$WRAPPER_HOME/lib/libwrapper.so,$WRAPPER_HOME/lib/wrapper.jar文件也拷贝到$DOG_HOME/lib目录下面。

6.这步比较重要是成败的关键,把$WRAPPER_HOME/conf/wrapper.conf文件拷贝到$DOG_HOME/conf目录下(文档上面说的是wrapper.conf.in文件,但是我下载来的文件就是wrapper.conf,所以步需要改名的)。

7.编辑wrapper.conf文件:

#java命令的位置

wrapper.java.command=%JAVA_HOME%/bin/java

#wrapper的主类

wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp

#java classpath

wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=%JAVA_HOME%/jre/lib/ext/log4j-1.2.13.jar
wrapper.java.classpath.3=%JAVA_HOME%/jre/lib/ext/activation.jar
wrapper.java.classpath.4=%JAVA_HOME%/jre/lib/ext/commons-email-1.0.jar
wrapper.java.classpath.5=%JAVA_HOME%/jre/lib/ext/mail.jar
wrapper.java.classpath.6=../lib/NetWatchDog.jar
#你的程序的主类,将作为wrapper的参数

wrapper.app.parameter.1=qiya.deng.main.Main

8.这样基本就大功告成了,现在可以运行命令./NetWatchDog  start,如果提示权限不够就用chmod 755 NetWatchDog命令改变权限。如果没出现错误提示,这样基本上就正确了。
另外Windwos版本可以参考:http://blog.chinaunix.com/u/1677/?u=http://blog.chinaunix.com/u/1677/showart.php?id=67084

3
通过蓝牙在Ubuntu上同步Palm Treo650 - Ubuntu - 红联Linux论坛 全球Linux人网上交流平台 - 天下没有难学的Linux
www.linuxdiyf.com/bbs/redirect.php?tid=82406&goto=...

通过蓝牙在Ubuntu上同步Palm Treo650

我在自己的Thinkpad T43本子上装了内置蓝牙芯片BMDC3,并且在Ubuntu Gusty操作系统上将蓝牙配置成功。购买蓝牙芯片的主要目的是——装酷!恩,就类似于不用一次性打火机而非要买个ZIPPO努力表现的很小资一样(嘿嘿,说的也是我自己)。其次的原因是,我爱死这台treo 650了,对treo 650深深的爱恋和对中国移动的刻骨仇恨促使我入手BMDC芯片——我的计划是,用t43笔记本以wi-fi功能连接办公室的无线路由,再用treo的蓝牙功能连t43的蓝牙适配器,在treo上安装skype软件,通过skype给老爸老妈打长途,费用大概是0.17RMB/min,若是购买套餐的话就更加便宜了,每分钟要比17951拨打国内长途足足便宜0.03RMB!(当然,这个理由你千万别相信,恩)

前面的拆开T43机器卸下moden芯片、安装bmdc3蓝牙芯片、调整数据线之类的工作就不多做介绍了,会在以后心情好的时候介绍一下。现在只是假设如下的情况:
笔记本上已经安装了蓝牙硬件,并且在ubuntu下配置成功;
t43的蓝牙和treo的蓝牙都已经打开
那么,下面开始乱入正题:

一、在ubuntu笔记本上的设置

首先是要修改蓝牙属性:
sduo vim /etc/default/bluetooth
(我搜索的一些资料中提示这个文件应该是在 /etc/default/bluez-utils。但无论如何都找不到,看了更多的文档之后才知道,原来现在已经变成/etc/default/bluetooth了)
将其中这两段代码修改如下:
DUND_ENABLED=1
DUND_OPTIONS="--listen --persist --msdun call treo"
其中的treo是我们假设将要在ubuntu系统中给手机连接起的名字,它可以是符合linux系统明明规则的任何名字,你可以按照自己的喜好来设置,比如chenshuibian之类的。

然后是修改/etc/ppp/peers/treo文件,其作用是建立一个拨号连接treo650和t43笔记本的脚本,如果你在前面将手机连接命名为chenshuibian,那么这里就是指向/etc/ppp/peers/chenshuibian
我们可以看到如下几行:
115200
192.168.1.1:192.168.1.2
local
ms-dns 202.120.190.208
noauth
debug

其中,115200是该连接允许的最大流量,192.168.1.1计算机的网关ip地址,192.168.1.2是为treo设置的ip地址,诸位可以根据自己的喜好来设置,只要确保它们二者处于同一个网端就可以了。ms-dns和t43设置使用的dns一样就可以,这里我填写的是我所在网络的地址

再看看这个文件,$sudo cat /etc/bluetooth/hcid.conf
如果其中有auth enable和encrypt enable的,就将这两行注释掉。

重新起动t43的蓝牙服务
sudo /etc/init.d/bluetooth restart
二、好,随后进入到在treo上的设置:

控制台——参数设定——其他——连接(假设你已经将treo汉化了)——新增
“名称”随意起吧,我用的是BT,bluetooth的简称(或者变态?)
“连接到”PC
“经由”bluetooth
“设备”地方按一下屏幕,进入搜索界面,在“选一个设备”中选择这台打开了蓝牙功能的笔记本,确定
“详情”——“速度”设置为115.200bps,“流量控制”设“自动”即可
确定
确定

还是在控制台中,通讯——网络,打开“修改”,即让屏幕左下方红色锁住模样的锁头变成绿色打开模样的锁头。
“连接”处选择BT
“用户名称”BT
密码”不要设置
详情——“后备”一定要设置成无,免得treo到时候一旦连接蓝牙失败,跳过wifi直接gprs或wap上网去了,白白给移动联通送钱。“闲置间断时间”1或3分钟均可。再选择“高级”——在“IP地址”和“查询DNS”后面都选上勾,这样连接到t43的时候就会自动被/etc/ppp/peers/treo脚本授予192.168.1.2的ip地址和202.120.190.208的dns。
确定,确定,在“服务”处随便填个名字,容易区分即可。我写的是“Notebook”。
“连接”一下,看看能否成功。若出现“连接建立”的字样,表示这一步也成功了。

三、在treo上设置hotsync:
打开hotsync,“选项”部分中:
调制解调器同步参数设定——选择“网络”
局域网同步参数设定——本机HotSync
主PC机设定:名字留空,地址填入192.168.1.1,子网掩码255.255.255.0
连线设定:BT
回到hotsync的主界面,选择“调制解调器”,在大图标下方选择”Notebook”,按一下大图标试试看?

treo屏幕上跳出“与桌上设备连线使用Notebook”字样。。。。。。
。。。。。。。。。
。。。。。。。。
连不上??!!
当然了,笔记本上还没装同步软件呢:)

四、t43上安装jpilot:
没什么可说的,jpilot还算不错,欢迎使用:)
若是此前ubuntu没有安装jpilot的话
sudo apt-get install jpilot
alt+f2,输入jpilot,回车,进入jpilot界面
文件——用户名输入Handspring,没办法,很多软件都是用这个名字安装的,如果用其他名字,同步完成后treo里的软件还要一个个的重新注册,太麻烦
文件——首选项。字符集选择UTF:Simplified Chinese (GBK)。否则Jpilot同步后会变成乱码。捎带着说一句,建议把联系人中的名字都设置成英文,比如王小二在联系人中保存为Wang Xiaoer,在备注里输入他的中文名字王小二即可。这样可以省去很多英文软件中无法正常显示中问的麻烦。
还是在文件——首选项中,设置——串行接口部分填入net:any,以使jpilot通过蓝牙网络寻找treo
其他jpilot设置就自己看着玩吧

五、连接T43和treo:
在jpilot上点一下hotsync按钮(快捷键ctrl+y),jpilot的命令行中出现如下字样
****************************************
正在与设备 net:any 同步
现在请按 HotSync 键
****************************************
此时再回到手机上,按hotsync同步之
若Jpilot出现如下字样:
用户名是“Handspring”"
用户 ID 是 1490960081
上次同步的PC = 773979359
这部 PC = 773979359
正在进行快速同步。
treo上也有同步时的音乐声和“正在同步***”的字样,那么恭喜,你得到它了!

明天再研究一下如果让treo通过t43的wifi网络上网
谷歌李开复:我的传奇人生源于十句箴言 - 博客园IT新闻
news.cnblogs.com/n/43760/

谷歌李开复:我的传奇人生源于十句箴言

投递人 itwriter 发布于 2008-12-02 13:35 评论(18) 有1061人阅读 [收藏]

一个成功的人如何定义成功?一个成功的人如何从成功中获得启发?这个命题无疑会让许多人充满了悬念与期待.2008年11月30日下午,北京青年报大厦的 20层大会议室迎来了北青教育大讲堂活动开办以来最爆满的盛况,谷歌全球副总裁、大中华区总裁李开复的到来,让许多人对于成功的定义有了崭新的认识.

 

对于成功,不仅仅是对名利的追逐,不应该完全用世俗的价值观去衡量成功与否,而是实现自己的价值,关爱自己身边的人,给这个世界带来更多的影响力,用自己 的力量去感染周围的磁场.当你某一天逝去的时候,你的墓志铭上应该撰写的是对你最公平的评价.成功的定义应该是多元化的.

在 这个下午,谷歌大中华区总裁李开复用平实而不失幽默的语言,讲述了自己成长中的很多故事.和许多人的成长经历相似,他的成长中也有儿时的淘气顽皮,学生时 代的疑问与困惑,有获得成功时的泪水与喜悦,也有经历困难与挫折时的蹉跎与彷徨.甚至有经历人生最低潮时期的痛苦与煎熬.但是与众不同的是,李开复在成功 中收获了经验,在失败中得到了成长.他把富有传奇的人生经历浓缩成为十句具有启发性的箴言,在如同与你交谈般的娓娓道来中,将这种宝贵的人生经验像冬日暖 阳一样,洒满了整个房间.

●成功箴言之一:
自信不失谦虚 谦虚不失自信

李 开复1961年出生于台湾,母亲在43岁高龄时生下他前,被医生数次劝阻.因为医生透露,如此高龄的产妇很可能生下白痴.但是母亲不顾一切劝阻生下了这个 幺儿.这个幺儿在母亲的极度宠爱下自由自在地成长着,喜欢做很多恶作剧.把家里所有的钟表调慢一小时以便晚上床睡觉.把邻居池塘里的水放干以证实邻居池塘 里并没有100条鱼.这一切母亲都只是报以宽容的一笑.但是母亲不允许孩子傲慢和目中无人.

当5岁的李开复得意洋洋地对邻居阿姨表示“上 小学以后就没有见过99分”后.母亲不允许这样的狂放存在于孩子身上,有史以来第一次打了开复.母亲告诉他,“不只要好好学习,还要改掉骄傲的毛病.自夸 是要不得的.谦虚是中国人的美德.”母亲总是不失时机地把做人的道理告诉开复.这一次强烈的记忆,使得开复懂得如何在谦虚和自信中保持平衡,而不会在自卑 或自负中跌倒.

●成功箴言之二:
天赋就是兴趣 兴趣就是天赋

李 开复11岁留学美国之后,一直在美国成长.1972年,他进入了美国哥伦比亚大学学习“政治科学” 专业.然而两年的学习让他知道自己的兴趣并非在政治方面.学习的枯燥经常让他在课堂上昏昏欲睡,学习成绩也不尽如人意.但是,他发现他在选修的计算机课 上,有着惊人的天赋.往往是别人还在苦思冥想如何写出程序时,他早就把程序写完而无所事事.后来,他发现他像发疯一样爱上了这门学科.因此,在大学二年级 时,他自己做出了一个惊人的决定,“转系!”这意味着他将从一个全美排名第3的专业转到一个毫无名气可言的专业.但是,他听从了内心的选择,还是选择了计 算机专业.而这个决定,改写了他一生的轨迹.

●成功箴言之三:
思考比传道重要 观点比解惑重要

李 开复以哥伦比亚大学计算机专业第一名的成绩毕业以后,顺利进入匹兹堡的卡内基·梅隆大学就读计算机专业的博士.在读博士之前,他的系主任Haberman 就告诉他,读博士的目的,就是要做出世界上一流的博士论文.至少在本领域是世界顶尖的.这句话让李开复十分震撼.然而,下面一句话,让他受益更 深,Haberman说,“做出一流的博士论文,也不是读博士的最终目的.而是你在读博士的过程中,获得一种思考的方法,而这种方法将使你在任何一个领 域,都获得顶尖的成功!”而李开复的努力证实了这种说法.李开复关于统计学方法做出的语音识别博士论文至今还是语音识别产品的理论基础.而李开复也在博士 生涯中,学会了解决问题,拥有了战胜困难的勇气.

●成功箴言之四:
我不同意你 但我支持你

李 开复在读博士期间选择的研究方向是“语音识别”.师从博士生导致罗迪.罗迪教授鼓励李开复用专家统计的方法来研究语音识别,而李开复在这个领域经过了一番 研究后,发现语音识别用这个方法可以获得特定语者95%的语音识别率.李开复把整个研究过程写了一篇论文.一经发表,得到了很正面的回馈.但是他最终发 现,专家系统是有严重局限性的,无法延伸到做不特定语者的语音识别.他认为有数据的支持的统计模式是唯一的希望.当他把想法告诉导师,罗迪告诉他,“我不 同意你,但是我支持你!”这样的说法让李开复备受感动,成就了李开复博士论文的成功.他的论文当年被评为《商业周刊》最杰出创新.

●成功箴言之五:
挫折不是惩罚 而是学习的机会

李 开复在博士生生涯里,成绩依然优秀.他用统计学做出的语音识别率大大地提高了,而博士论文发表在国际期刊上,让全美的科技界震惊.这样一个明星学生可以说 在卡内基·梅隆里没有什么忧愁可言.然而,一次暑期课程让他经历了不小的挫折.1983年暑假,李开复得到了暑期工的工作.

其任务就是教宾夕法尼亚州60个最聪明的高中生计算机课程.李开复自己对那段时光非常享受,每天忙碌地备课,还想出各种教学方法.但是,他领取薪水的那一瞬间看到学生的评语,才知道学生认为,“李老师的教学就像催眠曲!”这样的评价无疑使得李开复备受打击.

然而,李开复并没有气馁.他把失败当成了学习的机会,因此获得了成功.他在此后的生涯里,尤其是回到中国以后,做了上千场的演讲.这无疑得益于学生时代的练习.

●成功箴言之六:
创新不重要 有用的创新才重要

在 苹果和SGI李开复度过了八年科学家到产品副总裁的路程.在这段路程上,他有许多成功,例如苹果的QuickTime,但是在SGI他碰到了巨大的挫折. 他的团队发明的三维浏览器,在市场上失败,整个团队和产品被公司廉价卖掉.这时,他又发挥了“从挫折中学习”的反省.他理解了,仅仅有科学家的“新”、“ 酷”的创新是不够的.创新必须是针对用户的,必须是有用的.做产品的管理,必须把用户放在第一位.李开复1998年夏天回到中国,在中国开创微软中国研究 院.这时,他把这个教训带入中国团队.

●成功箴言之七:
完美的工作 成长兴趣 影响力

2000 年,李开复被调回微软总部成为微软全球副总裁.几年工作后,他深深地体会了一个完美工作的标准,那就是自己有浓厚的兴趣,能有成长的空间,并具备一定的影 响力.他怀念着在中国研究院的兴趣,还有在刚调回美国的学习,但是他期望着有更大的影响力.当他发现谷歌将开始在中国创建时,他主动找到了谷歌CEO施密 特,并表示愿意加入谷歌.而施密特十分高兴,在一个月之后就给了李开复OFFER.李开复说,当你遇到喜欢的工作机会,不需要任何的迟疑,而需要积极主动 来争取.因为这样的机会往往炙手可热,一秒钟的犹豫你就可能与之失之交臂.

●成功箴言之八:
用勇气改变可以改变的事情

2005年,是李开复的转折年.他没有想到,一次普通换工作的经历引发了一次地震.微软的诉讼使他陷入了人生最低的低谷.对他的虚假负面报道铺天盖地而来.但是,他想到了他一生的座右铭:用勇气改变可以改变的事情,用胸怀接受不能改变的事情,用智慧分辨两者的不同.

于 是,他全力以赴地投入了这场战斗,不再理会那些不能改变的谣言.将从微软提取的30万份邮件资料中找寻有利的证据以证明自己的清白.经过两个月的努力,法 庭同意李开复到谷歌工作.最后,当李开复回到媒体面前开始工作时,他发现,没有一个记者还提问与诉讼有关的问题,因为作为官司的胜利者,媒体不再相信那些 谣言.

●成功箴言之九:
做最好的领导 让员工做有兴趣的事

谷 歌公司聚集着世界上最天才的工程师们.如何管理这些“天才”,是摆在李开复面前的另一个课题.李开复非常推崇“放权”式的管理,他深知在以创意为主要生产 力的公司里,不能严格地恪守那些死板的规定.他可以让员工自己提出研究的方向.大家讨论决定.也可以让员工用20%的时间做自己喜欢的项目.他甚至可以让 员工对公司提出建议.如果合理就采纳.谷歌里自由的环境非常有名.作为管理者,他主要是在公司战略、每年的目标、合作伙伴、总部沟通上努力,其他的时间, 他更是一个企业文化的维护者、公司的发言人、员工的教练.

●成功箴言之十:
价值不是你拥有多少 而是你留下多少

什么是成功?是否拥有了名利就算成功.对此,李开复回答,你的价值不是你拥有多少,而是你留下多少.当他的一个同事赚够了钱而发现失去人生目标时,才意识到,人生的价值在于贡献,和对他人的影响.

李 开复曾经有过一个独特的梦想,就是在中国创建一所一流的,有世界影响力的私立大学.他甚至身体力行地为此多方奔走.但是最终因为种种原因没有成功.但是他 并没有气馁,而是用另外的方式实践梦想.他说:“我不能改变教育,但是我可以帮助学生.” 他给中国的大学生写信,写书,办了“我学网”,每年面对十万学生做演讲.在帮助学生的过程中,李开复看到中国大学生的成长.他说,他曾经想过自己的墓志铭 应该有科学家或者企业家的注脚.但是,他说他现在已经没有这种想法,如果他的墓志铭上有热心教育者的字样,他会感觉到内心的温暖.
How To Optimize Your Site With GZIP Compression | BetterExplained
betterexplained.com/articles/how-to-optimize-your-...

How To Optimize Your Site With GZIP Compression

Compression is a simple, effective way to save bandwidth and speed up your site. I hesitated when recommending gzip compression when speeding up your javascript because of problems in older browsers.

But it’s 2007. Most of my traffic comes from modern browsers, and quite frankly, most of my users are fairly tech-savvy. I don’t want to slow everyone else down because somebody is chugging along on IE 4.0 on Windows 95. Google and Yahoo use gzip compression. A modern browser is needed to enjoy modern web content and modern web speed — so gzip encoding it is. Here’s how to set it up.

Wait, wait, wait: Why are we doing this?

Before we start I should explain what content encoding is. When you request a file like http://www.yahoo.com/index.html, your browser talks to a web server. The conversation goes a little like this:

HTTP_request.png

1. Browser: Hey, GET me /index.html
2. Server: Ok, let me see if index.html is lying around…
3. Server: Found it! Here’s your response code (200 OK) and I’m sending the file.
4. Browser: 100KB? Ouch… waiting, waiting… ok, it’s loaded.

Of course, the actual headers and protocols are much more formal (monitor them with Live HTTP Headers if you’re so inclined).

But it worked, and you got your file.

So what’s the problem?

Well, the system works, but it’s not that efficient. 100KB is a lot of text, and frankly, HTML is redundant. Every <html>, <table> and <div> tag has a closing tag that’s almost the same. Words are repeated throughout the document. Any way you slice it, HTML (and its beefy cousin, XML) is not lean.

And what’s the plan when a file’s too big? Zip it!

If we could send a .zip file to the browser (index.html.zip) instead of plain old index.html, we’d save on bandwidth and download time. The browser could download the zipped file, extract it, and then show it to user, who’s in a good mood because the page loaded quickly. The browser-server conversation might look like this:

HTTP_request_compressed.png

1. Browser: Hey, can I GET index.html? I’ll take a compressed version if you’ve got it.
2. Server: Let me find the file… yep, it’s here. And you’ll take a compressed version? Awesome.
3. Server: Ok, I’ve found index.html (200 OK), am zipping it and sending it over.
4. Browser: Great! It’s only 10KB. I’ll unzip it and show the user.

The formula is simple: Smaller file = faster download = happy user.

Don’t believe me? The HTML portion of the yahoo home page goes from 101kb to 15kb after compression:

yahoo_compression.PNG

The (not so) hairy details

The tricky part of this exchange is the browser and server knowing it’s ok to send a zipped file over. The agreement has two parts

  • The browser sends a header telling the server it accepts compressed content (gzip and deflate are two compression schemes): Accept-Encoding: gzip, deflate
  • The server sends a response if the content is actually compressed: Content-Encoding: gzip

If the server doesn’t send the content-encoding response header, it means the file is not compressed (the default on many servers). The “Accept-encoding” header is just a request by the browser, not a demand. If the server doesn’t want to send back compressed content, the browser has to make do with the heavy regular version.

Setting up the server

The “good news” is that we can’t control the browser. It either sends the Accept-encoding: gzip, deflate header or it doesn’t.

Our job is to configure the server so it returns zipped content if the browser can handle it, saving bandwidth for everyone (and giving us a happy user).

In Apache, enabling output compression is fairly straightforward. Add the following to your .htaccess file:


# compress all text & html:
AddOutputFilterByType DEFLATE text/html text/plain text/xml

# Or, compress certain file types by extension:
<Files *.html>
SetOutputFilter DEFLATE
</Files>

Apache actually has two compression options:

  • mod_deflate is easier to set up and is standard.
  • mod_gzip seems more powerful: you can pre-compress content.

Deflate is quick and works, so I use it; use mod_gzip if that floats your boat. In either case, Apache checks if the browser sent the “Accept-encoding” header and returns the compressed or regular version of the file. However, some older browsers may have trouble (more below) and there are special directives you can add to correct this.

If you can’t change your .htaccess file, you can use PHP to return compressed content. Give your HTML file a .php extension and add this code to the top:


In PHP:
<?php if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start(); ?>

We check the “Accept-encoding” header and return a gzipped version of the file (otherwise the regular version). This is almost like building your own webserver (what fun!). But really, try to use Apache to compress your output if you can help it. You don’t want to monkey with your files.

Verify Your Compression

Once you’ve configured your server, check to make sure you’re actually serving up compressed content.

  • Online: Use the online gzip test to check whether your page is compressed.
  • In your browser: Use Web Developer Toolbar > Information > View Document Size (like I did for Yahoo, above) to see whether the page is compressed.
  • View the headers: Use Live HTTP Headers to examine the response. Look for a line that says “Content-encoding: gzip”.

Be prepared to marvel at the results. The instacalc homepage shrunk from 36k to 10k, a 75% reduction in size.

Try Some Examples

I’ve set up some pages and a downloadable example:

  • index.html - No explicit compression (on this server, I am using compression by default :) ).
  • index.htm - Explicitly compressed with Apache .htaccess using *.htm as a rule
  • index.php - Explicitly compressed using the PHP header

Feel free to download the files, put them on your server and tweak the settings.

Caveats

As exciting as it may appear, HTTP Compression isn’t all fun and games. Here’s what to watch out for:

  • Older browsers: Yes, some browsers still may have trouble with compressed content (they say they can accept it, but really they can’t). If your site absolutely must work with Netscape 1.0 on Windows 95, you may not want to use HTTP Compression. Apache mod_deflate has some rules to avoid compression for older browsers.
  • Already-compressed content: Most images, music and videos are already compressed. Don’t waste time compressing them again. In fact, you probably only need to compress the “big 3″ (HTML, CSS and Javascript).
  • CPU-load: Compressing content on-the-fly uses CPU time and saves bandwidth. Usually this is a great tradeoff given the speed of compression. There are ways to pre-compress static content and send over the compressed versions. This requires more configuration; even if it’s not possible, compressing output may still be a net win. Using CPU cycles for a faster user experience is well worth it, given the short attention spans on the web.

Enabling compression is one of the fastest ways to improve your site’s performance. Go forth, set it up, and let your users enjoy the benefits.

Hello.World » Injecting JavaScript and CSS into Iframes » The Weblog of Matthew Delmarter
matthew.delmarters.com/weblog/injecting-javascript...
InfoQ: Apache Solr : 基于Lucene的可扩展集群搜索服务器
www.infoq.com/cn/news/2008/11/apache-solr

Apache Solr : 基于Lucene的可扩展集群搜索服务器

作者 Ryan Slobojan译者 崔康 发布于 2008年11月13日 上午7时27分

社区
Java
主题
搜索
标签
Lucene,
Apache Solr

Apache Solr项目,是一款基于Apache Lucene的开源企业搜索服务器,最近发布了1.3版。InfoQ采访了Solr的创建者Yonik Seeley,了解了新版本的更多信息和Solr提供给最终用户的功能。

Seeley首先描述了目标用户:“需要搜索框、分面浏览(导航)或者两者结合的任何人”,Solr的关键特性包括:

  • 基于标准的开放接口——Solr搜索服务器支持通过XML、JSON和HTTP查询和获取结果。
  • 易管理——Solr可以通过HTML页面管理,服务器统计数据以JMX输出,Solr配置通过XML完成。
  • 分面浏览——搜索结果自动分类。
  • 突出显示命中词——匹配的字符自动在搜索结果中高亮显示。
  • 可伸缩性——快速增量更新和快照分发/复制到其他服务器。
  • 灵活的插件体系——新功能能够以插件的形式方便的添加到Solr服务器上。

Seeley同时谈到了该版本中的主要新功能:

  • 分布式搜索——索引现在可以透明的分割成多个部分,单个Solr服务器基于各个配置和模式支持多索引,无须停止Solr服务器就可以改动主要的配置。
  • 扩展了查询功能——包含了一个新的Java客户端(SolrJ)和若干新功能,例如直接配置对于特定查询哪些文档首先命中、近似命中、搜索过期、记录分面时间和拼写检查
  • 增强了数据导入工具——数据库和其他结构化数据源现在都可以导入、映射和转化。
  • 更多可定制扩展点——存在一个新的更新处理器链,允许在查询时修改和重定向文档;一个搜索组件链修改和添加查询结果、用户查询分析器和插件式功能。
  • 性能增强——显著提高了索引速度,二进制响应格式和快速查询删除功能。

详细的更新日志可以这里获得。

Seeley谈到了更多Solr在伸缩性、功能和实用性方面的细节:

Solr已经部署过数以百万计容量的文档,如果借助分布式搜索,Solr应该能够处理数十亿的文档集合。

Solr基于Lucene,具有优秀的全文相关性,可以很方便的提供词组接近性增强、近期文档增强、编辑增强和基于数字值的专有函数的定制评分机制。

AOL正在使用Solr增强它的频道功能:音乐、橄榄球运动、食谱、参考中心、房地产和汽车都使用这项技术。Solr的搜索功能也应用于Netflix、 Zappos、Gamespot、和Internet Archive。还有很多大客户我目前还不能透漏。

关于Solr的未来计划,Seeley提到了更多的可扩展性、对大集群更方便的配置和管理、基于区域和实时的搜索、重构以使用Spring配置插件。Seeley同时提供了一个邮件列表,在那里他详细讨论了Solr未来、特别是2.0版的计划。

Bash Shell脚本学习小结 - 程序人生 - BlogJava
www.blogjava.net/terry6394/archive/2007/01/13/9355...

Bash Shell脚本学习小结

今天需要写一个Shell脚本。很简单,判断一个日志文件是否大大于2G,如果大于2G则删除。久了没有写bash,竟然一点都想不起来写了。于是复习了一下,下面对今天的学习做个小结:
1.字符截断:
如果是一般路径的字符截断可以用basenamedirname这两个工具:
basename可以从一个文件路径中截一个文件名
例如:

$ basename /home/file.tar
file
.tar

dirname可以从一个文件路径中截到一个目录路径
例如:

$ dirname /home/file.tar
/home

不使用外部工具进行字符截断
bash有自带的功能来对变量进行字符截断,一般使用"##", "#", "%%", "%", "*" 组合来实现。例如:

$ string=hellowbashshell
$ echo ${string
##*sh}
ell
$ echo ${string
#*sh}
shell
$ echo ${string
%%sh*}
hellowba
$ echo ${string
%sh*}
hellowbash

"#"表示从字符开始部分除去,一旦匹配则立即除去
"##"表示从字符开始部分除去,会搜整个字符串最长的和的匹配来除去
"%"表示从字符结束的部分除去,一旦匹配成公则立即除去
"%%"表示从字符结束的部分开始除去,会搜寻整个字符穿中最长的匹配来除去
"*"统配符,一般与“##”或"#"联用时放在搜索字符串的左边,例如:${String#*sh}(在sh的左边),与"%%"或"%"联用时会放在匹配字符串的右边,例如:${String%%sh*}

常用技巧:
在路径中取文件名:${path##*/}(与basename相同功能)
在路径中取目录路径:${path%/*}(与dirname相同功能)
取文件的扩展名:${path##*.}
2.自变量的接收
接收来自命令行传入的参数,第一个参数用$1表示,第二个参数$2表示,。。。以此类推。注意:$0表示脚本文件名。另外一个在shell编程中经常用到的是“$@”这个代表所有的参数,。你可以用一个循环来遍历这个参数。如果用java来类比的话,可以把$@看作是man函数中定义的那个数组

3.if语句:
格式:
if [ condition ]
then 
    action
fi

注意:“if”和“[”之间需要空格,如果你不空格,shell会报告语法错误的。我就被这个浪费了好一阵时间

conditon测试类型对照表
运算符描述示例
文件比较运算符
-e filename如果 filename存在,则为真 [ -e /var/log/syslog ]
-d filename如果 filename为目录,则为真 [ -d /tmp/mydir ]
-f filename如果 filename为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename如果 filename为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename如果 filename可读,则为真 [ -r /var/log/syslog ]
-w filename如果 filename可写,则为真 [ -w /var/mytmp.txt ]
-x filename如果 filename可执行,则为真 [ -L /usr/bin/grep ]
filename1-nt filename2如果 filename1filename2新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1-ot filename2如果 filename1filename2旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)
-z string如果 string长度为零,则为真 [ -z "$myvar" ]
-n string如果 string长度非零,则为真 [ -n "$myvar" ]
string1= string2如果 string1string2相同,则为真 [ "$myvar" = "one two three" ]
string1!= string2如果 string1string2不同,则为真 [ "$myvar" != "one two three" ]
算术比较运算符
num1-eq num2等于[ 3 -eq $mynum ]
num1-ne num2不等于[ 3 -ne $mynum ]
num1-lt num2小于[ 3 -lt $mynum ]
num1-le num2小于或等于[ 3 -le $mynum ]
num1-gt num2大于[ 3 -gt $mynum ]
num1-ge num2大于或等于[ 3 -ge $mynum ]

感觉bash 中的if相比其他的一些语言智能多了,在bash中,测试一个文件的存在跟比较两个数字的大小没有什么两样 ;)

4.for语句
bash里的语句总是那么的人性化,十分的接近自然语言,在for语句中几乎可以迭代任何类似与集合的数据类型(或许这样个说法不对,但我确实想不到更好的词来代替)。
看一个例子:
#!/bin/bash
for args in $@
do
        
echo $args
done

把上面这段代码录入保存为showargs.sh设置为可执行(chmod +x showargs.sh)执行:

./showargs.sh arg1 arg2 arg3 arg4
arg1
arg2
arg3
arg4
这个例子中,我们用到了之“$@”,它代表了所有的命令行参数。在这里用for对其进行遍历,系统迭代地从$@中取出命令行参数把他放到args中,最后使用echo $args进行输出。
for更经常用到的是遍历目录,下面的例子用于列出当前目录下的所有文件和文件夹的名称
for file in *
> do
> echo $file
> done
这里用*代表当前目录,列出的是所有的文件和文件夹的名称,在这里,文件夹和文件你是分不出来的,如果你需要,你应该用if [-d ${file}]来做一下判断。
对于文件遍历,更有趣的是,你可以在 “in” 后面接上多个表达式。也就是说,你可以一次在遍历多个目录。
下面这段代码能把当前目录下go文件夹和do文件夹里的文件复制到fo文件夹下
#!/bin/bash
for args in ./go/* ./do/*
do
  cp ${args} 
./fo
  echo 
"copying ${args} to ./fo/${args}"
done
Eclipse 修改 EXTjs的风格

在Eclipse中新建一个文件名称是: new_style.theme (注意一定要是.theme的)

eclipse如果有spket的插件, 会自动打开EXT theme的风格 编辑器,

然后选择ext的resource的folder:  /data/joopen/ext-2.1/resources

然后会显示出对应的图片folder列表


然后在Effect的选项中增加你想要的风格, 选择export,就可以导出你想要的style
使用Profile对用户Session会话进行资源限制 - Oracle Life
www.eygle.com/archives/2008/10/profile_session_lim...
过profile可以对用户会话进行一定的限制,比如IDLE时间。
将IDLE超过一定时间的会话断开,可以减少数据库端的会话数量,减少资源耗用。


使用这些资源限制特性,需要设置resource_limit为TRUE:
[oracle@test126 udump]$ sqlplus "/ as sysdba"

SQL*Plus: Release 10.2.0.1.0 - Production on Fri Oct 13 07:58:21 2006

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning and Data Mining options

SQL> show parameter resource

NAME                                TYPE        VALUE
------------------------------------ ----------- ------------------------------
resource_limit                      boolean    TRUE
resource_manager_plan                string

该参数可以动态修改:
SQL> alter system set resource_limit=true;

System altered.

数据库缺省的PROFILE设置为:
SQL> SELECT * FROM DBA_PROFILES;

PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
-------------------- -------------------------------- -------- ---------------
DEFAULT              COMPOSITE_LIMIT                  KERNEL  UNLIMITED
DEFAULT              SESSIONS_PER_USER                KERNEL  UNLIMITED
DEFAULT              CPU_PER_SESSION                  KERNEL  UNLIMITED
DEFAULT              CPU_PER_CALL                    KERNEL  UNLIMITED
DEFAULT              LOGICAL_READS_PER_SESSION        KERNEL  UNLIMITED
DEFAULT              LOGICAL_READS_PER_CALL          KERNEL  UNLIMITED
DEFAULT              IDLE_TIME                        KERNEL  UNLIMITED
DEFAULT              CONNECT_TIME                    KERNEL  UNLIMITED
DEFAULT              PRIVATE_SGA                      KERNEL  UNLIMITED
DEFAULT              FAILED_LOGIN_ATTEMPTS            PASSWORD 10
DEFAULT              PASSWORD_LIFE_TIME              PASSWORD UNLIMITED

PROFILE              RESOURCE_NAME                    RESOURCE LIMIT
-------------------- -------------------------------- -------- ---------------
DEFAULT              PASSWORD_REUSE_TIME              PASSWORD UNLIMITED
DEFAULT              PASSWORD_REUSE_MAX              PASSWORD UNLIMITED
DEFAULT              PASSWORD_VERIFY_FUNCTION        PASSWORD NULL
DEFAULT              PASSWORD_LOCK_TIME              PASSWORD UNLIMITED
DEFAULT              PASSWORD_GRACE_TIME              PASSWORD UNLIMITED

16 rows selected.

创建一个允许3分钟IDLE时间的PROFILE:
SQL> CREATE PROFILE KILLIDLE LIMIT IDLE_TIME 3;

Profile created.

新创建PROFILE的内容:
SQL> col limit for a10
SQL> select * from dba_profiles where profile='KILLIDLE';

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------
KILLIDLE                      COMPOSITE_LIMIT                  KERNEL  DEFAULT
KILLIDLE                      SESSIONS_PER_USER                KERNEL  DEFAULT
KILLIDLE                      CPU_PER_SESSION                  KERNEL  DEFAULT
KILLIDLE                      CPU_PER_CALL                    KERNEL  DEFAULT
KILLIDLE                      LOGICAL_READS_PER_SESSION        KERNEL  DEFAULT
KILLIDLE                      LOGICAL_READS_PER_CALL          KERNEL  DEFAULT
KILLIDLE                      IDLE_TIME                        KERNEL  3
KILLIDLE                      CONNECT_TIME                    KERNEL  DEFAULT
KILLIDLE                      PRIVATE_SGA                      KERNEL  DEFAULT
KILLIDLE                      FAILED_LOGIN_ATTEMPTS            PASSWORD DEFAULT
KILLIDLE                      PASSWORD_LIFE_TIME              PASSWORD DEFAULT

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------
KILLIDLE                      PASSWORD_REUSE_TIME              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_REUSE_MAX              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_VERIFY_FUNCTION        PASSWORD DEFAULT
KILLIDLE                      PASSWORD_LOCK_TIME              PASSWORD DEFAULT
KILLIDLE                      PASSWORD_GRACE_TIME              PASSWORD DEFAULT

16 rows selected.

测试用户:
SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ --------------------
EYGLE                          DEFAULT

修改eygle用户的PROFILE使用新建的PROFILE:
SQL> alter user eygle profile killidle;

User altered.

SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ --------------------
EYGLE                          KILLIDLE

进行连接测试:
[oracle@test126 admin]$ sqlplus eygle/eygle@eygle

SQL*Plus: Release 10.2.0.1.0 - Production on Fri Oct 13 08:07:13 2006
Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning and Data Mining options

SQL> select username,profile from dba_users where username='EYGLE';

USERNAME                      PROFILE
------------------------------ ------------------------------
EYGLE                          KILLIDLE


当IDLE超过限制时间时,连接会被断开:
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY
-------------------
2006-10-13 08:08:41

SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual
*
ERROR at line 1:
ORA-02396: exceeded maximum idle time, please connect again

InfoQ: 专访Restlet框架首席开发者Jérome Louvel
www.infoq.com/cn/articles/restlet-louvel-interview

专访Restlet框架首席开发者Jérome Louvel

作者 Stefan Tilkov译者 宋玮 发布于 2007年6月14日 下午10时26分

社区
Ruby,
SOA,
Java
主题
Web框架,
REST
标签
Restlet,
Ruby on Rails,
JSR 311

最近Restlet框架发布了它的1.0版。Jérome Louve是Java框架Restlet的领导开发者,InfoQ的编辑Stefan Tikov有机会和Jérome Louvel进行了一次对话,本次谈话的主题讨论了Restlet存在的原因、在Java Web服务框架中的REST支持、Ruby on Rails、对JSR 311的期望以及Restlet的路线图。

相关厂商内容

与Ola Bini一起探讨JRuby

SOY Framework:Java富客户端快速开发框架

利用Ruby简化你的Java测试(进阶篇)

免费迷你书下载:Grails入门指南

IDC:《软件商成长路线图》白皮书免费下载

相关赞助商

InfoQ中文站Ruby社区,面向Web和企业开发的Ruby,主要关注Ruby on Rails,通过新闻、文章、视频访谈和演讲以及迷你书等为中国Ruby社区提供一流资讯。

InfoQ:你能给我们简单地介绍下Restlet的目标吗?

Jérome Louvel(以下简称JL):Restlet是一个Java下的轻量级REST框架。通过拥抱REST(REST是一种Web架构风格)它模糊了Web站点和Web服务之间的界限,从而帮助开发人员构建Web应用。每一个主要的REST概念(REST concept)都有一个对应的Java类。你的REST化的Web设计和你的代码之间的映射是非常简单直接的。

Restlet是一个以CDDL或GPL发布的开源项目。该项目包含一个Restlet API,一个引用实现(Noelios Restlet引擎)以及一套扩展。

InfoQ:你为什么会觉得有必要创建另一种框架?难道Servlet API还不够好用吗?

JL:Servlet AIP在1998年发布,从那个时候起它的核心设计一直没有很大的变化。它是Java EE的众多API中最成功的一个,但是它的几个设计缺陷和一些限制损害了它。举个例子,URI模式和它的处理者(handler)之间的映射是受限制的,而且其配置都集中在一个配置文件中。还有,他把socket流的控制直接交给了应用系统开发人员,Servlet容器阻碍了我们充分使用NIO特性对IO操作进行优化。最后,他对一些HTTP特性,例如缓存、内容协商以及内容压缩支持的不好。这对开发人员来说是件痛苦的事,因为这阻碍了他们将精力集中在应用系统相关的代码上。

另一个主要问题是,Java EE Stack中新的HTTP客户端API的缺少。JDK的HttpURLConnection类很难用,而且许多HTTP特性都不支持,比如为内容协商而表达的客户端选择等。人们经常需要依赖第三方HTTP客户端API突破这些限制。但是,HttpURLConnection不支持NIO。

2005年,我看到了超越这些限制的机会:在REST原则下设计一个新的API。第一次,我们有了统一Web应用客户端和服务器端的机会,这个API完全支持NIO并能让开发人员编程控制Web容器、连接器(connector)等,而且不需要经常性的依赖XML描述符就能部署应用系统。

InfoQ:你怎么看在别的框架中对REST的支持(例如Axis2,或者CXF/XFire)?

JL:我想这些支持非常有效,但是作用非常有限。我的主要观点是设计这些项目是为了符合WS-*/SOAP Stack,它们与REST世界并不非常契合。在REST世界里,定义了一个全新的范例:面向资源的设计,而非通过远程方法调用这样的范例。

例如Axis2仅仅支持GET和POST两种HTTP方法,它需要远程方法的传递需要一个URI参数。这在REST中式不允许的,这种做法也不能被称之为REST化。

XFire1.2不支持REST,但是它发布了一个项目用于将POJO映射到REST化的Web服务。这有点类似最近发布的JSR-311,此JSR试图基于一套annotation和助手类标准化这种映射。

InfoQ:你是JSR 311专家组的成员,能否对JSR 311做一下展望?

JL:我期望它能在REST资源和POJO领域对象之间实现一个完好的映射。就像JPA在关系数据库和POJO之间实现了很好的映射那样,我们也希望这个JSR能做到像JPA那样。我希望以annotation为中心的API能够相当符合(complimentary)Restlet API,后者已经是一个将REST资源映射到POJO的以类为中心的API了。

这些annotation也能被像Axis2和XFire这样的项目实现,我认为这个JSR给了REST和WS-*阵营一个达成和解的机会。

InfoQ:你能告诉我们一些基于Restlet的项目吗?

JL:有几个不同规模的组织已经部署并应用了这样的应用系统,包括Overstock.com,这是一个在线购物方面的Internet领导者。Restlet项目也被作为支持技术用在覆盖REST构架风格的不同软件构架类别中。例如在加州Irvine大学,以及在INSA Rouen工程学院的使用。

我们自己的网站也是用Restlet引擎构建的。考虑到我们受到拒绝服务(denial of service)的攻击量,我们对我们系统的可伸缩性很自信。最近我们还发布了一个公用基准以证明了其性能品质。我们与流行的Servlet容器处在同一水平线上,而且有望在下一个加入完全的NIO优化的连接器(基于Glassfish的Grizzly NIO框架)的版本中比后者表现更为优异。

InfoQ:在构建REST化的应用系统中,能否比较一下Java和其他语言有何不同?

JL:流行的REST化技术,例如Rails或者Django这些技术的经验告诉我们,Java/Restlet这样的技术在支持REST化的应用中会有更好更高的性能表现。Rails和Django开始的设计并没有考虑到REST,REST的这些概念只是在后来被加进去的。相比Restlet,这导致了很多做作的(contrived)代码。以Django为例,它并不天然支持在URI和资源之间映射的URI模板。而Rails强迫在关系数据库和对数据的CRUD操作间使用一种不自然的映射,REST/HTTP方法导致一种令人不满意的结果:开发人员不得不在各种限制下工作,或者采用自己的面向资源的设计去迎合Rails。而Restlet不强迫你使用任何持久化技术,它让你自由的定义你的资源及其特定的表现形式(representation),以及它们怎么被映射到你的领域对象或你的数据库。

InfoQ:你能更详细的解释下你刚才对Rails的批评吗? 你认为它的CRUD映射什么地方不够自然?

JL:除了GET和DETLET这样的HTTP方法可以很好的映射到SQL的SELECT和DELETE外,我还发现Rails将HTTP的POST方法用来进行创建行为,这很不幸。在REST中,对于创建行为最好的方法是使用PUT,它也可以用于更新。PUT比POST优越的地方是如果操作行为失败了,它可以很安全的重复操作,而POST不行。

还有,资源列表是基于表名和行记录的数字型id映射的,在实践中这并不总是可行的。你不想失去对你的URI的控制,而URI既是应用系统用户界面的一部分,又是REST最基本的概念之一。在Restlet中,我们并不对你的URI强加任何限制,你可以自由的使用任一持久化技术(例如JPA的annotation化POJO,纯JDBC调用,对象数据库等等)在你的资源和表现形式(representation)之间进行映射。

我对Rails的另一个小小的批评是,Rails鼓励使用笨拙的“;edit”后缀访问一个资源的编辑Web页面。这有点误导,REST并不鼓励使用URI参数的非一致方法,应该使用分隔的Web表单资源,这样浏览器可以使用GET、POST或者PUT方法。

InfoQ:你好像在Restlet上花了不少时间。这个业余项目占用了你多少时间,你的公司期望能从这个项目中得到多大的商业成就?

JL:从开始这个项目就不是作为一个业余产品启动的。当我构建另一个很重要的私人项目是我就感觉到了对它的需要。我相信专业的开源项目,也希望Noelios Consulting能提供的专业服务(如支持计划,顾问服务)能让我们继续投入更多的精力。

InfoQ:第一版发布之后的路线图是什么?

JL:除了维护1.0版修改bug外,我们还将很快启动1.1版。一些我们曾想过的对WAR包(不再需要XML描述符)的增强将被加进来。用户可以选择通过一个XML描述符配置Restlet组件(可移植的应用系统和虚拟主机容器)从而简化管理员的工作。我们还有几个连接器原型要实现,一个是基于Grizzly NIO框架的HTTP服务器连接器,它将带来更多的可伸缩性和响应(responsiveness)。另外两个HTTP连接器是基于JXTA的虚拟socket(一个客户机和一个服务器)。

我们还想更深入的支持HTTP特性,例如内容范围(content range),Digest和WSSE授权。我们还计划在2008年将Restlet API提交给JCP。这有利于逐渐替代Servlet API。

InfoQ:谢谢你抽出时间接受我们的采访。


作者简介:Jérome Louvel是一位软件架构师,它是Noelios Consulting公司的创始人。在软件版本(Software edition)和咨询方面有超过8年的工作经验,它常年工作在欧洲和北美洲。他对Java、REST、语义网以及商业过程集成有浓厚的兴趣。

译者简介:宋玮,有多年软件开发经验,从2002年开始就使用Java,在各个项目开发过程中先后使用过Struts、Oracle ADF、AspectJ等。最近正在使用Spring及Ruby on Rails,对敏捷方法有比较大的兴趣并做过一些尝试。他的blog为http://www.donews.net/victorsong。参与InfoQ中文站内容建设,请邮件至china-editorial@infoq.com

Restlet指南[Matrix社区试读版] - [Matrix - 与 Java 共舞]
www.matrix.org.cn/resource/article/2007-11-30/1312...

Restlet指南[Matrix社区试读版]

cleverpig 发表于 2007-11-30 15:15:48
作者:cleverpig     来源:Matrix
评论数:8 点击数:2,116     投票总得分:5 投票总人次:1
关键字:Restlet,REST,指南,入门

摘要:

当复杂核心化模式日趋强大之时,面向对象设计范例已经不总是Web开发中的最佳选择,Java开发者需要认识到这一点,并且在开发新的Web服务端或是 AJAX Web客户端时开始思考更加RESTfully的设计。Restlet这个开源项目为那些要采用REST结构体系来构建应用程序的Java开发者提供了一个具体的解决方案。朋友们,下面就让我们开始Restlet探索之旅吧!
Restlet 指南[Matrix社区试读版]

作者:cleverpig


关于本指南

本指南的翻译工作经过了Restlet社区的官方授权,cleverpig作为贡献者完成了本文的翻译和整理工作。在此发布Matrix社区试读版的目的是为了让更多的技术爱好者阅读并提出翻译中的不足之处,以提高本指南的质量,以期修改后正式发布。

Servlet的限制

在2003年末,Jetty Web容器的作者、Servlet规范的贡献者:Greg Wilkins在其博客上对Servlet的问题进行了如下总计:

    * 没有对协议与应用之间的关系进行清洗的划分。
    * 由于在设计Servlet时存在对阻塞IO的假设,因此不能充分利用非阻塞NIO机制。
    * 所有的Servlet Web容器对于某些应用来讲是过度设计的。

他提出构思新的API规范,使其能够真实地脱离协议,并定义能够暴露内容和元数据的contentlets。这些想法就是Restlet项目创建的灵感源泉。在之后的文章中,Greg Wilkins解释了为什么当前Servlet API限制非阻塞NIO API得到高效使用的详细理由:这种传统的用法针对每个HTTP请求都创建独立的线程进行处理。并提出了他对下一代Servlet技术的设想

另一个主要问题就是Servlet API鼓励应用开发者在应用或者用户会话级别直接将session状态保存于内存中,尽管这看上去不错,但它造成了Servlet容器扩展性和高可用性的主要问题。为了克服这些问题,就必须实现复杂的负载均衡、session复制、持久化机制。这导致了可扩展性必然成为灾难。

Restlet简介

当复杂核心化模式日趋强大之时,面向对象设计范例已经不总是Web开发中的最佳选择,Java开发者需要认识到这一点,并且在开发新的Web服务端或是AJAX Web客户端时开始思考更加RESTfully的设计。Restlet这个开源项目为那些要采用REST结构体系来构建应用程序的Java开发者提供了一个具体的解决方案。它的非常简单易用的功能和RESTfully的Web框架,这使其成为了Web2.0开发中的又一利器。好吧,朋友们,下面就让我们开始Restlet探索之旅吧!

1. 注册一个Restlet实现

Restlet框架由两部分构成。第一部分是"Restlet API", 这个中立的API完美地实现了REST概念并简化了客户端和服务端应用的调用处理。在使用它之前,我们还需要一个支持此API的Restlet实现。Restlet的诸多实现可以通过开源项目或者商业产品获得。
image

API与实现的分离和Servlet API与web容器的分离(就像Jetty或Tomcat)、JDBC API与相应JDBC驱动的分离非常类似。目前,"Noelios Restlet Engine" (缩写为NRE)是Restle tAPI的参考实现之一。当下载Restlet发布版本时,API和NRE就绑定在一起,以备随时使用。如果你需要使用不同的实现,那么只需要添加JAR 文件到classpath,并删除com.noelios.restlet.jar这个NRE的JAR文件即可。

API实现的注册过程是完全自动的,如果你对此存在疑问,那么请参考JAR规范。当完成实现装载工作后,它将自动回调org.restlet.util.Engine.setInstance()方法,来进行自注册。

2. 接收Web页面的内容

正如我们在Restlet介绍中所提到的,Restlet框架即是一个客户端,又是一个服务端框架。例如,NRE能够简单地通过它的HTTP客户端 connector(连接器)访问远程资源。在REST中,connector是一种软件元素,它使两个component(组件)之间能够进行通讯,其典型的实现方式是通过某种网络协议完成通讯。NRE提供了多种客户端connector实现,这些实现都基于现存的开源项目。在connector一节中,列举出了所有可用的客户端、服务端connector,并解释了如何使用和配置它们。

下面,我们将获取一个现存资源的表示法(representation )并将其输出在JVM控制台:
// Outputting the content of a Web page
Client client = new Client(Protocol.HTTP);
client.get("http://www.restlet.org").getEntity().write(System.out);


请注意上面的示例使用了最简单的方式:通过通用的客户端类(generic Client class)调用。更加灵活的方式是创建一个新的Request对象,然后请求客户端去处理它。下面的示例展示了如何在调用时设置首选项(例如 referrer URI)。当然,也可以是接收回应时的首选语言或者媒体类型:
// Prepare the request
Request request = new Request(Method.GET, "http://www.restlet.org");
request.setReferrerRef("http://www.mysite.org");

// Handle it using an HTTP client connector
Client client = new Client(Protocol.HTTP);
Response response = client.handle(request);

// Write the response entity on the console
Representation output = response.getEntity();
output.write(System.out);


3. 侦听浏览器

现在,我们将了解一下Restlet框架是如何侦听客户端请求并作出回应的。这里,我们选用了NRE HTTP服务端connector(例如基于Jetty的HTTP服务端connector),返回简单的字符串表达式“Hello World!”。请注意在更加实际的应用中,我们可以创建一个独立的类,此类继承自Restlet类,而不依靠这里的匿名内部类。

Restlet类与Servlet非常相似,并且在RESTful应用中处理调用时提供了有限的帮助。我们后面将看到一个提供了一些特定子类的框架,它能够更抽象、简单地进行处理。下面让我们先看一个简单的示例:
// Creating a minimal Restlet returning "Hello World"
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        response.setEntity("Hello World!", MediaType.TEXT_PLAIN);
    }
};

// Create the HTTP server and listen on port 8182
new Server(Protocol.HTTP, 8182, restlet).start();


如果你运行并启动服务端,那么你可以打开浏览器输入http://localhost:8182。实际上,输入任何的URI都可以工作,你也可以尝试一下http://localhost:8182/test/tutorial。值得注意的是,如果你从另一台服务器上测试服务端,那么就需要将localhost替换为服务器的IP地址或者它的域名。

4. REST架构概述

让我们先从REST的视角审视一下典型的web架构。在下面的图表中,端口代表了connector,而后者负责component之间的通讯(组件在图中被表示为大盒子)。链接代表了用于实际通讯的特定协议(HTTP,SMTP等)。
image

请注意,同一个component能够具有任何数量的客户端/服务端connector。例如,Web服务器B就具有一个用于回应用户代理组件(User Agent component)的服务端connector,和多个发送请求到其它服务端的客户端connector。

5. Component、virtual hosts和applications

另外,为了支持前面所表述的标准REST软件架构元素,Restlet框架也提供了一套类:它们极大地简化了在单一JVM中部署多个应用的工作。其目的在于提供一种RESTful、可移植的、比现存的Servlet API更加灵活的框架。在下面的图表中,我们将看到三种Restlet,它们用于管理上述复杂情况:Components能够管理多个Virtual Hosts和Applications。Virtual Hosts支持灵活的配置,例如同一个IP地址能够分享多个域名、使用同一个域名实现跨越多个IP地址的负载均衡。最后,我们使用应用去管理一套相关的 Restlet、Resource、Representations。另外,应用确保了在不同Restlet实现、不同Virtual Hosts之上的可移植性和可配置性。这三种Restlet的协助为我们提供了众多的功能:譬如访问日志、请求自动解码、配置状态页设置等。image

为了展示这些类,让我们尝试一个简单的示例。首先,我们创建一个component,然后在其上添加一个HTTP服务端connector,并侦听 8182端口。接着创建一个简单的、具有追踪功能的Restlet,将它放置到组件默认的Virtual Hosts上。这个默认的主机将捕捉那些没有路由到指定Virtual Hosts的请求(详见Component.hosts属性)。在后面的一个示例中,我们还将介绍应用类的使用方法。请注意,目前你并不能在控制台输出中看到任何的访问日志。
// Create a new Restlet component and add a HTTP server connector to it
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8182);

// Create a new tracing Restlet
Restlet restlet = new Restlet() {
    @Override
    public void handle(Request request, Response response) {
        // Print the requested URI path
        String message = "Resource URI  : " + request.getResourceRef()
                + '\n' + "Root URI      : " + request.getRootRef()
                + '\n' + "Routed part   : "
                + request.getResourceRef().getBaseRef() + '\n'
                + "Remaining part: "
                + request.getResourceRef().getRemainingPart();
        response.setEntity(message, MediaType.TEXT_PLAIN);
    }
};

// Then attach it to the local host
component.getDefaultHost().attach("/trace", restlet);

// Now, let's start the component!
// Note that the HTTP server connector is also automatically started.
component.start();

让我们通过在浏览器中输入http://localhost:8182/trace/abc/def?param=123来进行测试,得到测试结果如下:
Resource URI  : http://localhost:8182/trace/abc/def?param=123
Root URI      : http://localhost:8182/trace
Routed part   : http://localhost:8182/trace
Remaining part: /abc/def?param=123


6. 为静态文件提供服务

你遇到过提供静态页面(类似Javadocs)服务的web应用?如果正在使用,那么可以直接编写一个Directory类,而无需为它建立Apache服务。请见下面如何使用:
// Create a component
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8182);
component.getClients().add(Protocol.FILE);

// Create an application
Application application = new Application(component.getContext()) {
    @Override
    public Restlet createRoot() {
        return new Directory(getContext(), ROOT_URI);
    }
};

// Attach the application to the component and start it
component.getDefaultHost().attach("", application);
component.start();

正如你所注意到的,我们通过传递应用的父组件上下文(context)的方式来实例化应用,而不是在第5章中提到的代码那样简单。而其主要原因是应用在分配客户端请求时,请求的分配工作需要客户端connector来完成,而后者被component所控制,并在所有被包含其中的应用之间贡献。

为了运行此示例,你需要为ROOT_URI提供一个有效值,该值依赖于你的Restlet安装路径。默认情况下,它被设置为"file:///D: /Restlet/www/docs/api/"。请注意,这里不需要任何附加的配置。如果你希望自定义在文件扩展名和元数据(metadata,包括媒体类型、语言、编码等)之间的映射,或是提供一个与众不同的索引名,你可以使用应用的“metadataService”属性。

7. 访问日志

有目的地记录web应用的活动是一种常见的需求。Restlet组件能够在默认的情况下生成类似Apache风格的日志、甚至自定义日志。通过使用 JDK内置的日志功能,logger能够配置为像任何标准JDK日志那样过滤信息、对它们进行重新格式化或者发送它们到指定位置。并且支持日志的循环(rotation);细节请查看java.util.logging包。

值得注意的是,你能够通过修改component的"logService"属性来为java.util.logging框架自定义logger名。如果希望完全掌控日志的配置,你需要通过设置系统属性来声明一个配置文件:
System.setProperty("java.util.logging.config.file", "/your/path/logging.config");


关于配置文件格式的细节,请查看JDK的LogManager类。

8. 显示错误页

另外一个常见的需求是:在调用处理过程中某些期望结果没有出现时,能够自定义返回的状态页面。也许它是某个资源没有找到或者一个可接受的表示是无效的。在这种情况下,或者遇到任何无法处理的异常时,Application或者Component将自动提供一个默认的状态页面。此服务与 org.restlet.util.StatusService类相关联,并可以作为被称为“statusService”的Application或者 Component的属性而被访问。

为了自定义默认的信息,你只需要简单地创建StatusService类的子类,并覆盖其getRepresentation(Status, Request, Response)方法。然后设置这个类的实例为指定的“statusService”属性即可。

9. 对敏感资源的访问保护

当你需要保护对某些Restlet的访问时,可以使用下面的方法:一种通用的方法是依靠cookie来识别客户端(或者客户端session),并根据你的应用状态检查给定的用户ID或者session ID,从而判断次访问是否被允许。Restlet通过访问Request或者Response中的CookieCookieSetting对象支持cookie。

另一种方法是基于标准HTTP认证机制。Neolios Restlet引擎目前允许基于简单HTTP方案的证书发送、接收和基于Amazon Web服务方案的证书发送。

当接收到调用时,开发者能够通过Request.challengeResponse.identifier/secret类中的Guard filter(保护过滤器)使用已经解析好的证书。过滤器是一种特殊的Restlet,它能够在调用相应Restlet之前进行预处理,或者在相应 Restlet调用返回后进行后期处理。如果你熟知Servlet API,这里的过滤器概念和Servlet API中的Filter接口非常接近。看一下我们如何修改从前的代码来对目录访问进行访问保护:
// Create a Guard
Guard guard = new Guard(getContext(),
        ChallengeScheme.HTTP_BASIC, "Tutorial");
guard.getSecrets().put("scott", "tiger".toCharArray());

// Create a Directory able to return a deep hierarchy of files
Directory directory = new Directory(getContext(), ROOT_URI);
guard.setNext(directory);
return guard;

image

请注意:认证和授权的最终结果是完全可定制的,这只需要通过authenticate()和authorize()方法便可完成。任何自定义的机制都能够被用来检查给定的证书是否有效、通过认证的用户是否被授权继续访问相应Restlet。下面是我们简单地硬编码了用户、密码对。为了测试,我们使用了客户端Restlet API:
// Prepare the request
Request request = new Request(Method.GET, "http://localhost:8182/");

// Add the client authentication to the call
ChallengeScheme scheme = ChallengeScheme.HTTP_BASIC;
ChallengeResponse authentication = new ChallengeResponse(scheme,
        "scott", "tiger");
request.setChallengeResponse(authentication);

// Ask to the HTTP client connector to handle the call
Client client = new Client(Protocol.HTTP);
Response response = client.handle(request);

if (response.getStatus().isSuccess()) {
    // Output the response entity on the JVM console
    response.getEntity().write(System.out);
} else if (response.getStatus()
        .equals(Status.CLIENT_ERROR_UNAUTHORIZED)) {
    // Unauthorized access
    System.out
            .println("Access authorized by the server, " +
                    "check your credentials");
} else {
    // Unexpected status
    System.out.println("An unexpected status was returned: "
            + response.getStatus());
}

你可以修改这里的user ID或者password,来检查服务端返回的response。请别忘记了在启动客户端之前,先执行Restlet服务端程序。请注意,如果你从另一台机器上测试服务端,那么在浏览器中输入URI时需要将"localhost"替换为服务器的IP地址或者域名。由于使用了默认接收任何类型URI的 VirtualHost,因此服务端无需任何修改。

10. URI重写和重定向

Restlet框架的另一个优点是对cool URI的内建支持。Jacob Nielsen在他的AlertBox中给出了对URI设计的重要性的绝佳描述

首先介绍的工具是Redirector,它能够将cool URI重写为另一个URI,并接着进行相应的自动重定向。这里支持一些重定向类型:通过客户端/浏览器的外部重定向、类似代理行为的connector重定向。在下面的例子中,我们将基于Google为名为"mysite.org"的站点定义一个检索服务。与URI相关的"/search"就是检索服务,它通过"kwd"参数接收一些检索关键字:
// Create an application
Application application = new Application(component.getContext()) {
    @Override
    public Restlet createRoot() {
        // Create a Redirector to Google search service
        String target =
           "http://www.google.com/search?q=site:mysite.org+{keywords}";
        return new Redirector(getContext(), target,
                Redirector.MODE_CLIENT_TEMPORARY);
    }
};

// Attach the application to the component's default host
Route route = component.getDefaultHost().attach("/search", application);

// While routing requests to the application, extract a query parameter
// For instance :
// http://localhost:8182/search?kwd=myKeyword1+myKeyword2
// will be routed to
// http://www.google.com/search?q=site:mysite.org+myKeyword1%20myKeyword2
route.extractQuery("keywords", "kwd", true);

请注意,Redirector只需要三个参数。第一个参数是父级上下文,第二个参数定义了如何基于URI模板重写URI。这里的URI模板将被Template类处理。第三个参数定义了重定向类型:出于简化的目的,我们选择了客户端重定向。

同时,当调用被传递给application时,我们使用了Route类从request中提取查询参数“kwd”。如果发现参数,参数将被复制到request的“keywords”属性中,以便Redirector在格式化目标URI时使用。

11. 路由器和分层URI

作为Redirector的补充,我们还具有另一个管理cool URI的工具:Router(路由器)。它们是一种特殊的Restlet,能够使其它Restlet(例如Finder和Filter)依附于它们,并基于URI模板进行自动委派调用(delegate call)。通常,你可以将Router设置为Application的根。

这里,我们将解释一下如何处理下面的URI模板:

   1. /docs/ 用于显示静态文件
   2. /users/{user} 用于显示用户帐号
   3. /users/{user}/orders 用于显示特定用户的所有订单
   4. /users/{user}/orders/{order} 用于显示特定的订单

实际上,这些URI包含了可变的部分(在大括号中)并且没有文件扩展名,这在传统的web容器中很难处理。而现在,你只需要做的只是使用URI模板将目标Restlet附着到Router上。在Restlet框架运行时,与request的URI最为匹配的Route将接收调用,并调用它所附着的 Restlet。同时,request的属性表也将自动更新为URI模板变量。
image

请看下面的具体实现代码。在真实的应用中,你可能希望创建单独的子类来代替我们这里使用的匿名类:
// Create a component
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8182);
component.getClients().add(Protocol.FILE);

// Create an application
Application application = new Application(component.getContext()) {
    @Override
    public Restlet createRoot() {
        // Create a root router
        Router router = new Router(getContext());

        // Attach a guard to secure access to the directory
        Guard guard = new Guard(getContext(),
                ChallengeScheme.HTTP_BASIC, "Restlet tutorial");
        guard.getSecrets().put("scott", "tiger".toCharArray());
        router.attach("/docs/", guard);

        // Create a directory able to expose a hierarchy of files
        Directory directory = new Directory(getContext(), ROOT_URI);
        guard.setNext(directory);

        // Create the account handler
        Restlet account = new Restlet() {
            @Override
            public void handle(Request request, Response response) {
                // Print the requested URI path
                String message = "Account of user \""
                        + request.getAttributes().get("user") + "\"";
                response.setEntity(message, MediaType.TEXT_PLAIN);
            }
        };

        // Create the orders handler
        Restlet orders = new Restlet(getContext()) {
            @Override
            public void handle(Request request, Response response) {
                // Print the user name of the requested orders
                String message = "Orders of user \""
                        + request.getAttributes().get("user") + "\"";
                response.setEntity(message, MediaType.TEXT_PLAIN);
            }
        };

        // Create the order handler
        Restlet order = new Restlet(getContext()) {
            @Override
            public void handle(Request request, Response response) {
                // Print the user name of the requested orders
                String message = "Order \""
                        + request.getAttributes().get("order")
                        + "\" for user \""
                        + request.getAttributes().get("user") + "\"";
                response.setEntity(message, MediaType.TEXT_PLAIN);
            }
        };

        // Attach the handlers to the root router
        router.attach("/users/{user}", account);
        router.attach("/users/{user}/orders", orders);
        router.attach("/users/{user}/orders/{order}", order);

        // Return the root router
        return router;
    }
};

// Attach the application to the component and start it
component.getDefaultHost().attach(application);
component.start();


请注意,变量的值是直接从URI中提取的,因此这是没有精确解码的。为了实现这样的工作,请查看手册中的decode(String)方法

12. 抵达目标资源

在前面的示例中,在从目标URI中提取那些有趣部分时,我们利用了Restlet框架非常灵活的路由特性对request进行路由。但是,我们没有注意request方法和客户端对于它所期望的response的偏好。于是,我们如何才能将Restlet处理器和后台系统、域对象联系在一起呢?

到目前为止,我们已经介绍了一些在Restlet中超越传统Servlet API的特性。但我们并没有在"Restlet"这个框架名称中使用"REST"。如果你还没有做的话,我推荐你学习一些关于REST架构风格和将其应用于Web应用的最佳实践。这里提供了相关的FAQ记录,希望能给你一些启示,同时我们也运营着很有用的REST搜索引擎(基于Google)。如果你对传统MVC框架有一定了解,那么你可以阅读一下另一个FAQ记录,它提供了对MVC与Restlet关系的详细说明。
image

总结一下,request中含有标识目标资源的URI,而目标资源就是调用的主旨。这种资源信息被保存在Request.resourceRef属性中,并能够像我们之前所见那样服务于路由机制。因此在处理request时的首要目标就是发现目标资源。。。Resource类的实例或者其子类中的某个。为了帮助我们完成此项任务,我们可以使用专用的Finder,一个Restlet子类,它将Resource类引用作为参数并在request到来时自动实例化它。然后Finder将动态将调用分配给最新创建的实例,实际上就是根据request方法调用它的handle*()方法中的某一个(handleGet,handleDelete等)。当然,我们可以自定义这种行为,甚至使用Router的attach()方法,将URI模板和 Resource类作为其参数透明地创建Finder!现在,让我们看一下展示了示例中主框架类之间关系的全景图表:

回到代码中,我们在这里重构了Application.createRoot()方法。出于简化目的,我们没有提供具有静态文件的目录。你可以发现将Resource类直接指派给Router的方法。
// Create a router
Router router = new Router(getContext());

// Attach the resources to the router
router.attach("/users/{user}", UserResource.class);
router.attach("/users/{user}/orders", OrdersResource.class);
router.attach("/users/{user}/orders/{order}",
        OrderResource.class);

// Return the root router
return router;


我们最后将重审一下UserResource类。这个类继承自org.restlet.resource.Resource类,因此它覆盖了具有三个参数的构造方法。此方法初始化了"context"、"request"和"response"属性。接着,我们使用从"/users/{user} "URI模板中提取出的"user"属性,将它的值保存在一个方便使用的成员变量中。然后,我们便可以在整个application中查找与"user" 相关的域对象了。最终,我们声明了用于暴露给用户的表示变量(representation variants),在这个简单的例子中只是文字而已。它将用于在运行时透明地完成一些内容导航,以便为每个request选择适合的变量,所有这些工作都是透明的。
public class UserResource extends Resource {
    String userName;

    Object user;

    public UserResource(Context context, Request request,
            Response response) {
        super(context, request, response);
        this.userName = (String) request.getAttributes().get("user");
        this.user = null; // Could be a lookup to a domain object.

        // Here we add the representation variants exposed
        getVariants().add(new Variant(MediaType.TEXT_PLAIN));
    }

    @Override
    public Representation getRepresentation(Variant variant) {
        Representation result = null;
        if (variant.getMediaType().equals(MediaType.TEXT_PLAIN)) {
            result = new StringRepresentation("Account of user \""
                    + this.userName + "\"");
        }
        return result;
    }
}


你可以查看本指南中提供的代码包并对应用进行测试,并能够以仅接受Get请求的方式获得在第十一章中的相同行为。如果你希望使用PUT方法,那么就需要在UserResource中创建一个"allowPut()"方法并简单地返回"true",并且添加一个"put (Representation)"方法来处理调用。关于详细内容请查阅Restlet的Javadocs。

结论

我们已经涵盖了Restlet框架的许多方面。在你打算行动之前,让我们先回顾一下展示了本指南的主要概念和它们之间关系的两个层次图表:
image

这里是核心表示类:
image

除了本指南,你最好的信息来源就是Restlet API的Javadocs、Restlet扩展和NRE。还可以阅读一下connector一节,它列举出了客户端和服务端connector,并解释了如何使用、配置它们。集成一节列出了提供可插入特性的所有可用扩展:例如与servlet容器的集成、动态表示的生成等。你还可以在我们的讨论组中提出问题并帮助别人。

相关资源:

http://www.restlet.org/documentation/1.0/tutorial
http://www.restlet.org/about/introduction
全面介绍:Oracle数据库日期处理 - Oracle - 4s资讯社--分享与交流 - www.4studio.cn
www.4studio.cn/www/51/2008-01/1144.html
全面介绍:Oracle数据库日期处理
作者:   2008-01-13 22:38   来源:  
相关标签: Oracle  数据库  日期处理

在oracle中处理日期大全

  TO_DATE格式

Day: 
dd number 12 
dy abbreviated fri 
day spelled out friday 
ddspth spelled out, ordinal twelfth 
Month: 
mm number 03 
mon abbreviated mar 
month spelled out march 
Year: 
yy two digits 98 
yyyy four digits 1998 

  24小时格式下时间范围为: 0:00:00 - 23:59:59....

  12小时格式下时间范围为: 1:00:00 - 12:59:59 ....

  1.日期和字符转换函数用法(to_date,to_char)

  2.select to_char( to_date(222,'J'),'Jsp') from dual

  显示Two Hundred Twenty-Two

  3.求某天是星期几

select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;  
星期一  
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;  
monday  

  设置日期语言

ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';

  也可以这样

TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

  4.两个日期间的天数

select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;

  5. 时间为null的用法

select id, active_date from table1  
UNION  
select 1, TO_DATE(null) from dual;  

  注意要用TO_DATE(null)

  6.a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')

  那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。

  所以,当时间需要精确的时候,觉得to_char还是必要的

  7. 日期格式冲突问题

  输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是:

'01-Jan-01'  
alter system set NLS_DATE_LANGUAGE = American  
alter session set NLS_DATE_LANGUAGE = American 

  或者在to_date中写

select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;

  注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,

  可查看

select * from nls_session_parameters  
select * from V$NLS_PARAMETERS  

8.

select count(*)  
from ( select rownum-1 rnum  
from all_objects  
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-  
02-01','yyyy-mm-dd')+1  
)  
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )  
not  
in ( '1', '7' )  

  查找2002-02-28至2002-02-01间除星期一和七的天数

  在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

  9.

select months_between(to_date('01-31-1999','MM-DD-YYYY'),  
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;  
1  

select months_between(to_date('02-01-1999','MM-DD-YYYY'),  
to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;  

1.03225806451613  

  10. Next_day的用法

Next_day(date, day)  

Monday-Sunday, for format code DAY  
Mon-Sun, for format code DY  
1-7, for format code D  

  11.select to_char(sysdate,'hh:mi:ss') TIME from all_objects

  注意:第一条记录的TIME 与最后一行是一样的

  可以建立一个函数来处理这个问题

create or replace function sys_date return date is  
begin  
return sysdate;  
end;  

select to_char(sys_date,'hh:mi:ss') from all_objects;  

  12.获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer  
SQL> select sysdate ,to_char(sysdate,'hh') from dual;  

SYSDATE TO_CHAR(SYSDATE,'HH')  
-------------------- ---------------------  
2003-10-13 19:35:21 07  

SQL> select sysdate ,to_char(sysdate,'hh24') from dual;  

SYSDATE TO_CHAR(SYSDATE,'HH24')  
-------------------- -----------------------  
2003-10-13 19:35:21 19  

  获取年月日与此类似

  13.年月日的处理

select older_date,  
newer_date,  
years,  
months,  
abs(  
trunc(  
newer_date-  
add_months( older_date,years*12+months )  
)  
) days  
from ( select  
trunc(months_between( newer_date, older_date )/12) YEARS,  
mod(trunc(months_between( newer_date, older_date )),  
12 ) MONTHS,  
newer_date,  
older_date  
from ( select hiredate older_date,  
add_months(hiredate,rownum)+rownum newer_date  
from emp )  
)  

  14.处理月份天数不定的办法

select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual

  15.找出今年的天数

select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual

  闰年的处理方法

to_char( last_day( to_date('02' || :year,'mmyyyy') ), 'dd' )

  如果是28就不是闰年

Gmail - 我心目中的编程高手(完整版) - zhaojinzhong@gmail.com
mail.google.com/mail/?zx=ld9f29v26rt7&shva=1#searc...
百度面试题--linux[转] - linux学习 - Linuxer William
blog.chinaunix.net/u1/53217/showart.php?id=1162477
百度面试题--linux[转]
  这篇文章是转载的哦,大家都误会了~我不是东软的
=========================================

1.假设Apache产生的日志文件名为access_log,在apache正在运行时,执行命令mv
access_log access_log.bak,执行完后,请问新的apache的日志会打印到哪里,为什么?
1、新的日志会打印在access_log.bak中,因为apache启动时会找到access_log文件,随时准备向文件中加入日志信息,
   虽然此时文件被改名,但是由于服务正在运行,因为它的inode节点的位置没有变,程序打开的fd仍然会指向原来那个inode,
   不会因为文件名的改变而改变。apache会继续向已改名的文件中追加日志,但是若重启apache服务,系统会检查access_log
   文件是否存在,若不存在则创建。
2.在Shell环境下,如何查看远程Linux系统运行了多少时间?
2、监控主机执行: ssh user@被监控主机ip "uptime"
   这样得到了被监控主机的uptime
3.处理以下文件内容,将域名取出并进行计数排序,如处理:
http://www.baidu.com/index.html
http://www.baidu.com/1.html
http://post.baidu.com/index.html
http://mp3.baidu.com/index.html
http://www.baidu.com/3.html
http://post.baidu.com/2.html
得到如下结果:
域名的出现的次数 域名
3 www.baidu.com
2 post.baidu.com
1 mp3.baidu.com
可以使用bash/perl/php/c任意一种
3、[root@localhost shell]# cat file | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn
      3 www.baidu.com
      2 post.baidu.com
      1 mp3.baidu.com
[root@codfei4 shell]# awk -F/ '{print $3}' file |sort -r|uniq -c|awk '{print $1"\t",$2}'
3        www.baidu.com
2        post.baidu.com
1        mp3.baidu.com

4.如果得到随机的字串,长度和字串中出现的字符表可定义,并将字串倒序显示,如
把0123456789作为基准的字串字符表,产生一个6位的字串642031,打印出的字串为
130246,可使用bash/perl/php/c任意一种.
4、[root@localhost ~]#  awk -v count=6 'BEGIN {srand();str="0123456789";len=length(str);for(i=count;i>0;i--) marry[i]=substr(str,int(rand()*len),1);for(i=count;i>0;i--) printf("%c",marry[i]);printf("\n");for

(i=0;i<=count;i++) printf("%c",marry[i]);printf("\n")}'
838705
507838
5.如何查看当前Linux系统的状态,如CPU使用,内存使用,负载情况等.
5、Linux系统中“/proc”是个伪文件目录,不占用系统空间,及时的反应出内存现在使用的进程情况......其中许多文件都保存系统运行状态和相关信息
对于“/proc”中文件可使用文件查看命令浏览其内容,文件中包含系统特定信息:
cpuinfo          主机CPU信息
filesystems       文件系统信息
meninfo          主机内存信息
version           Linux内存版本信息
diskstatus        磁盘负载情况
另外top命令可以动态的显示当前系统进程用户的使用情况,而且是动态的显示出来,尤其是在该命令显示出来的对上方对系统的情况进行汇总.
free命令呢可以查看真实使用的内存  一般用free -m
使用lsof 、ps -aux 可以查看详细的每个进程的使用状况
dmesg 也是常用来查看系统性能的命令
#######################################################################################################################################################################
#题目:有10台被监控主机、一台监控机,在监控机上编写脚本,一旦某台被监控机器/分区适用率大于80%, 就发邮件报警放到crontab里面, 每10分钟检查一次
#测试机器:虚拟机Linux as 4 
#1.首先建立服务器间的信任关系。拿两台机器做测试
本机ip:192.168.1.6
[root@codfei ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
/root/.ssh/id_rsa already exists.
Overwrite (y/n)? y (以为我是第2次建立关系所以此处覆盖原来的文件)
Enter passphrase (empty for no passphrase):(直接回车无须输入密钥)
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
04:37:13:2a:4b:10:af:c1:2b:03:3f:6b:27:ce:b9:62 root@codfei
[root@codfei ~]# cd .ssh/
[root@codfei .ssh]# ll
-rw-------  1 root root 883 Apr 25 17:51 id_rsa
-rw-r--r--  1 root root 221 Apr 25 17:51 id_rsa.pub
-rw-r--r--  1 root root 442 Apr 25 17:37 known_hosts
id_rsa是密钥文件,id_rsa.pub是公钥文件。
[root@codfei .ssh]# scp id_rsa.pub192.168.1.4:/root/.ssh/192.168.1.6
root@192.168.1.4's password:
id_rsa.pub                                    100%  221     0.2KB/s   00:00
这里把公钥文件取名为本机的ip地址就是为了以后和更多的机器建立信任关系不发生混淆。
现在登陆到192.168.1.4机器
[root@codfei ~]# cd .ssh/
[root@codfei .ssh]# cat 192.168.1.6 >> authorized_keys
然后回到192.168.1.6机器直接
[root@codfei .ssh]# ssh 192.168.1.4
Last login: Wed Aug  8 12:14:42 2007 from 192.168.1.6
这样就可以了,里面偶尔涉及到权限问题。一般./ssh文件夹是755 authorized_keys为600或者644


####脚本如下#######################

#!/bin/bash            
#SCRIPT:df_check.sh           
#Writeen by codfei Mon Sep  3 07:25:28 CST 2007        
#PURPOSE:This script is used to monitor for full filesystems.      
#######################Begining########################################
FSMAX="80"
remote_user='root'  #####完全可以不用root
remote_ip=(192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8 192.168.1.9 192.168.1.10 192.168.1.11 192.168.1.12 192.168.1.13 192.168.1.14  )
###这里填写你要监控的主机ip
ip_num='0'
while [ "$ip_num" -le "$(expr ${#remote_ip[@]} - 1)" ]
do       
 read_num='1'       
 ssh "$remote_user"@"${remote_ip[$ip_num]}" df -h > /tmp/diskcheck_tmp
 grep '^/dev/*' /tmp/diskcheck_tmp|awk '{print $5}'|sed 's/\%//g' > /tmp/diskcheck_num_tmp         
         while [ "$read_num" -le $(wc -l < /tmp/diskcheck_num_tmp) ]       
  do
 size=$(sed -n "$read_num"'p' /tmp/diskcheck_num_tmp)               
 if [ "$size" -gt "$FSMAX" ]              
 then               
 $(grep '^/dev/*' /tmp/diskcheck_tmp|sed -n $read_num'p' > /tmp/disk_check_mail) 
        $(echo ${remote_ip[$ip_num]} >> /tmp/disk_check_mail)               
 $(mail -s "diskcheck_alert" admin < /tmp/disk_check_mail)               
 fi       
read_num=$(expr $read_num + 1)       
done       
ip_num=$(expr $ip_num + 1)
done

#############over################################
################让脚本每十分钟执行一次#############
在cron表中加入
0/10 * * * * /home/codfei/diskcheck.sh 2>&1

 

##########################################################################
比如, ext2文件系统, 如果异常死机,开机如何修复文件系统?
如果异常关机,比如断电,通知机房的人开机之后,
我们需要远程修复、检查文件系统
除了/分区之外, 其他的分区:
umount /home
fsck -y /home
/ 分区需要开机之后, 由机房的人来扫描
随后我们再登录并扫描/home等其他分区
如何查看一个进程所使用的文件句柄?
看这里面 /proc/进程号/fd/
的个数就行了
简单的比如如何查看apache进程数
[root@localhost fd]# ps -ef|grep httpd|wc -l
1
如何统计apache的每秒访问数?
tail access_log  | awk '{print $1,$4}'
[root@localhost logs]# grep -c `date -d '3 second ago' +%T` access_log
0
#######################################################################################################################
#######################################################################################################################
1、/proc/sys 子目录的作用
该子目录的作用是报告各种不同的内核参数,并让您能交互地更改其中的某些。与 /proc 中所有其他文件不同,该目录中的某些文件可以写入,不过这仅针对 root。

其中的目录以及文件的详细列表将占据过多的篇幅,而且该目录的内容是依赖于系统的,而大部分的文件也仅仅对某些特殊的应用程序有用。然而,以下是该子目录的两个最常见的用途:

允许路由:即便是 Mandrakelinux 默认的内核也是允许路由的,您必需显式允许它这么做。为此,您只要以 root 身份键入以下命令:

$ echo 1 >/proc/sys/net/ipv4/ip_forward
 

如果您要禁用路由,请将上述命令中的 1 改为 0。

阻止 IP 欺骗:IP 欺骗会让人认为某个来自于外部的某个数据包是来自于它到达的那个接口。这一技术常被骇客(cracker)所使用。您可以让内核阻止这种入侵。请键入:

$ echo 1 >/proc/sys/net/ipv4/conf/all/rp_filter
 

这样,这种攻击就不再可能了。

这些改变仅当系统运行时有效。在系统重新启动之后,它们会改会它们的默认值。要在启动时就改动这些值,您可以将您在 shell 提示符后键入的命令添加到 /etc/rc.d/rc.local 中以免每次都键入它们。另一个方法是修改

/etc/sysctl.conf
2、将一个文本的奇数行和偶数行合并,第2行和第3行合并
[root@localhost bin]# cat 1
48      Oct     3bc1997 lpas    68.00   lvx2a   138
484     Jan     380sdf1 usp     78.00   deiv    344
483     nov     7pl1998 usp     37.00   kvm9d   644
320     aug     der9393 psh     83.00   wiel    293
231     jul     sdf9dsf sdfs    99.00   werl    223
230     nov     19dfd9d abd     87.00   sdiv    230
219     sept    5ap1996 usp     65.00   lvx2c   189
216     Sept    3zl1998 usp     86.00   kvm9e   234
[root@localhost bin]# sed '$!N;s/\n/  /g' 1
48      Oct     3bc1997 lpas    68.00   lvx2a   138  484     Jan     380sdf1 usp     78.00   deiv    344
483     nov     7pl1998 usp     37.00   kvm9d   644  320     aug     der9393 psh     83.00   wiel    293
231     jul     sdf9dsf sdfs    99.00   werl    223  230     nov     19dfd9d abd     87.00   sdiv    230
219     sept    5ap1996 usp     65.00   lvx2c   189  216     Sept    3zl1998 usp     86.00   kvm9e   234
[root@localhost bin]# sed -n -e 2p -e 3p 1|sed '$!N;s/\n/ /'
484     Jan     380sdf1 usp     78.00   deiv    344 483     nov     7pl1998 usp     37.00   kvm9d   644
3、read 命令5秒后自动退出
[root@localhost bin]# read -t 5
4、自动ftp上传
#!/bin/sh
ftp -n<<END_FTP
open 192.168.1.4
user codfei duibuqi   //用户名codfei 密码duibuqi
binary
prompt off    //关闭提示
mput test    //上传test
close
bye
END_FTP
   自动ssh登陆 从A到B然后再到c
#!/usr/bin/expect -f
set timeout 30
spawn ssh codfei@B
expect "password:"
send "pppppp\r"
expect "]*"
send "ssh codfei@C\r"
expect "password:"
send "pppppp\r"
interact

5、#打印第一个域
[root@localhost bin]# cat 3
eqeqedadasdD
eqeqdadfdfDD
fdsfdsfQWEDD
DSADASDSADSA
[root@localhost bin]#
[root@localhost bin]#
[root@localhost bin]# awk -F "" '{print $1}' 3
e
e
f
D
6、实现字符串翻转
[root@localhost bin]# cat 8
qweqewqedadaddas
[root@localhost bin]# rev 8
saddadadeqweqewq
########################################第2次电面
7、sed awk grep哪个最好
我答的是 哪个掌握的精通,都很好,但是还是问我哪个最好,我只能说awk了,对于行操作和列操作都可以操作的很好。
8、grep -E -P 是什么意思
我说的是-E, --extended-regexp 采用规则表示式去解释样式。 -P不太清楚
9、还问了我对运维这个工作的理解,和应该具备的素质。
…………


后记:百度面试的这些日子,很刻苦的学习了一个阶段。脚本编写能力有了很大的提高。但是还是很遗憾,没有去到那。打算在大连找个运维的工作,继续我的理想。工作几年之后,我还会继续努力的。
3年前,我是个连电脑开机关机都不会的农村孩子,现在我感觉自己已经对于Linux入门了,我很有成就感,但是我还是被百度通知,我没有发展潜力。我是东软的学生,我总是认为计算机这个行业不看
出身,只要有实力就可以了。但是第一次电面我没有被提前通知会电面,突然打来的电话,当时正在睡觉,头脑一片空白……进入到第2次面试的时候,没有慌张准备的很充分,但是还是没有最终被录取。
面试的考官问我,你最失落的事是什么,我说我最失落的事是我高考前意外受伤休学了,我现在才意识到,我当时应该回答他,我最失落的时刻应该是我得知被百度拒绝的那一刻。
已经付出了努力,即使失败也很坦然。

大型网站架构演变和知识体系 - BlueDavy之技术Blog - BlogJava
www.blogjava.net/BlueDavy/archive/2008/09/03/22674...

之前也有一些介绍大型网站架构演变的文章,例如LiveJournal的、ebay的,都是非常值得参考的,不过感觉他们讲的更多的是每次演变的结果,而没有很详细的讲为什么需要做这样的演变,再加上近来感觉有不少同学都很难明白为什么一个网站需要那么复杂的技术,于是有了写这篇文章的想法,在这篇文章中 将阐述一个普通的网站发展成大型网站过程中的一种较为典型的架构演变历程和所需掌握的知识体系,希望能给想从事互联网行业的同学一点初步的概念,:),文中的不对之处也请各位多给点建议,让本文真正起到抛砖引玉的效果。

架构演变第一步:物理分离webserver和数据库

最开始,由于某些想法,于是在互联网上搭建了一个网站,这个时候甚至有可能主机都是租借的,但由于这篇文章我们只关注架构的演变历程,因此就假设这个时候 已经是托管了一台主机,并且有一定的带宽了,这个时候由于网站具备了一定的特色,吸引了部分人访问,逐渐你发现系统的压力越来越高,响应速度越来越慢,而这个时候比较明显的是数据库和应用互相影响,应用出问题了,数据库也很容易出现问题,而数据库出问题的时候,应用也容易出问题,于是进入了第一步演变阶段:将应用和数据库从物理上分离,变成了两台机器,这个时候技术上没有什么新的要求,但你发现确实起到效果了,系统又恢复到以前的响应速度了,并且支撑住了更高的流量,并且不会因为数据库和应用形成互相的影响。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

这一步架构演变对技术上的知识体系基本没有要求。

架构演变第二步:增加页面缓存

好景不长,随着访问的人越来越多,你发现响应速度又开始变慢了,查找原因,发现是访问数据库的操作太多,导致数据连接竞争激烈,所以响应变慢,但数据库连 接又不能开太多,否则数据库机器压力会很高,因此考虑采用缓存机制来减少数据库连接资源的竞争和对数据库读的压力,这个时候首先也许会选择采用squid 等类似的机制来将系统中相对静态的页面(例如一两天才会有更新的页面)进行缓存(当然,也可以采用将页面静态化的方案),这样程序上可以不做修改,就能够 很好的减少对webserver的压力以及减少数据库连接资源的竞争,OK,于是开始采用squid来做相对静态的页面的缓存。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

前端页面缓存技术,例如squid,如想用好的话还得深入掌握下squid的实现方式以及缓存的失效算法等。

 

架构演变第三步:增加页面片段缓存

增加了squid做缓存后,整体系统的速度确实是提升了,webserver的压力也开始下降了,但随着访问量的增加,发现系统又开始变的有些慢了,在尝 到了squid之类的动态缓存带来的好处后,开始想能不能让现在那些动态页面里相对静态的部分也缓存起来呢,因此考虑采用类似ESI之类的页面片段缓存策略,OK,于是开始采用ESI来做动态页面中相对静态的片段部分的缓存。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

页面片段缓存技术,例如ESI等,想用好的话同样需要掌握ESI的实现方式等;

 

架构演变第四步:数据缓存

在采用ESI之类的技术再次提高了系统的缓存效果后,系统的压力确实进一步降低了,但同样,随着访问量的增加,系统还是开始变慢,经过查找,可能会发现系 统中存在一些重复获取数据信息的地方,像获取用户信息等,这个时候开始考虑是不是可以将这些数据信息也缓存起来呢,于是将这些数据缓存到本地内存,改变完毕后,完全符合预期,系统的响应速度又恢复了,数据库的压力也再度降低了不少。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

缓存技术,包括像Map数据结构、缓存算法、所选用的框架本身的实现机制等。

 

架构演变第五步: 增加webserver

好景不长,发现随着系统访问量的再度增加,webserver机器的压力在高峰期会上升到比较高,这个时候开始考虑增加一台webserver,这也是为了同时解决可用性的问题,避免单台的webserver down机的话就没法使用了,在做了这些考虑后,决定增加一台webserver,增加一台webserver时,会碰到一些问题,典型的有:
1
、如何让访问分配到这两台机器上,这个时候通常会考虑的方案是Apache自带的负载均衡方案,或LVS这类的软件负载均衡方案;
2
、如何保持状态信息的同步,例如用户session等,这个时候会考虑的方案有写入数据库、写入存储、cookie或同步session信息等机制等;
3
、如何保持数据缓存信息的同步,例如之前缓存的用户数据等,这个时候通常会考虑的机制有缓存同步或分布式缓存;
4
、如何让上传文件这些类似的功能继续正常,这个时候通常会考虑的机制是使用共享文件系统或存储等;
在解决了这些问题后,终于是把webserver增加为了两台,系统终于是又恢复到了以往的速度。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

负载均衡技术(包括但不限于硬件负载均衡、软件负载均衡、负载算法、linux转发协议、所选用的技术的实现细节等)、主备技术(包括但不限于ARP欺骗、linux heart-beat等)、状态信息或缓存同步技术(包括但不限于Cookie技术、UDP协议、状态信息广播、所选用的缓存同步技术的实现细节等)、共享文件技术(包括但不限于NFS等)、存储技术(包括但不限于存储设备等)。

 

架构演变第六步:分库

享受了一段时间的系统访问量高速增长的幸福后,发现系统又开始变慢了,这次又是什么状况呢,经过查找,发现数据库写入、更新的这些操作的部分数据库连接的 资源竞争非常激烈,导致了系统变慢,这下怎么办呢,此时可选的方案有数据库集群和分库策略,集群方面像有些数据库支持的并不是很好,因此分库会成为比较普遍的策略,分库也就意味着要对原有程序进行修改,一通修改实现分库后,不错,目标达到了,系统恢复甚至速度比以前还快了。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

这一步更多的是需要从业务上做合理的划分,以实现分库,具体技术细节上没有其他的要求;

但同时随着数据量的增大和分库的进行,在数据库的设计、调优以及维护上需要做的更好,因此对这些方面的技术还是提出了很高的要求的。

 

架构演变第七步:分表、DAL和分布式缓存
随着系统的不断运行,数据量开始大幅度增长,这个时候发现分库后查询仍然会有些慢,于是按照分库的思想开始做分表的工作,当然,这不可避免的会需要对程序 进行一些修改,也许在这个时候就会发现应用自己要关心分库分表的规则等,还是有些复杂的,于是萌生能否增加一个通用的框架来实现分库分表的数据访问,这个在ebay的架构中对应的就是DAL,这个演变的过程相对而言需要花费较长的时间,当然,也有可能这个通用的框架会等到分表做完后才开始做,同时,在这个阶段可 能会发现之前的缓存同步方案出现问题,因为数据量太大,导致现在不太可能将缓存存在本地,然后同步的方式,需要采用分布式缓存方案了,于是,又是一通考察和折磨,终于是将大量的数据缓存转移到分布式缓存上了。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

分表更多的同样是业务上的划分,技术上涉及到的会有动态hash算法、consistent hash算法等;

DAL涉及到比较多的复杂技术,例如数据库连接的管理(超时、异常)、数据库操作的控制(超时、异常)、分库分表规则的封装等;

 

架构演变第八步:增加更多的webserver

在做完分库分表这些工作后,数据库上的压力已经降到比较低了,又开始过着每天看着访问量暴增的幸福生活了,突然有一天,发现系统的访问又开始有变慢的趋势 了,这个时候首先查看数据库,压力一切正常,之后查看webserver,发现apache阻塞了很多的请求,而应用服务器对每个请求也是比较快的,看来 是请求数太高导致需要排队等待,响应速度变慢,这还好办,一般来说,这个时候也会有些钱了,于是添加一些webserver服务器,在这个添加 webserver服务器的过程,有可能会出现几种挑战:
1
Apache的软负载或LVS软负载等无法承担巨大的web访问量(请求连接数、网络流量等)的调度了,这个时候如果经费允许的话,会采取的方案是购 买硬件负载,例如F5NetsclarAthelon之类的,如经费不允许的话,会采取的方案是将应用从逻辑上做一定的分类,然后分散到不同的软负载集群中;
2
、原有的一些状态信息同步、文件共享等方案可能会出现瓶颈,需要进行改进,也许这个时候会根据情况编写符合网站业务需求的分布式文件系统等;
在做完这些工作后,开始进入一个看似完美的无限伸缩的时代,当网站流量增加时,应对的解决方案就是不断的添加webserver

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

到了这一步,随着机器数的不断增长、数据量的不断增长和对系统可用性的要求越来越高,这个时候要求对所采用的技术都要有更为深入的理解,并需要根据网站的需求来做更加定制性质的产品。

 

架构演变第九步:数据读写分离和廉价存储方案

突然有一天,发现这个完美的时代也要结束了,数据库的噩梦又一次出现在眼前了,由于添加的webserver太多了,导致数据库连接的资源还是不够用,而这个时候又已经分库分表了,开始分析数据库的压力状况,可能会发现数据库的读写比很高,这个时候通常会想到数据读写分离的方案,当然,这个方案要实现并不 容易,另外,可能会发现一些数据存储在数据库上有些浪费,或者说过于占用数据库资源,因此在这个阶段可能会形成的架构演变是实现数据读写分离,同时编写一些更为廉价的存储方案,例如BigTable这种。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

数据读写分离要求对数据库的复制、standby等策略有深入的掌握和理解,同时会要求具备自行实现的技术;

廉价存储方案要求对OS的文件存储有深入的掌握和理解,同时要求对采用的语言在文件这块的实现有深入的掌握。

 

架构演变第十步:进入大型分布式应用时代和廉价服务器群梦想时代

经过上面这个漫长而痛苦的过程,终于是再度迎来了完美的时代,不断的增加webserver就可以支撑越来越高的访问量了,对于大型网站而言,人气的重要毋 庸置疑,随着人气的越来越高,各种各样的功能需求也开始爆发性的增长,这个时候突然发现,原来部署在webserver上的那个web应用已经非常庞大 了,当多个团队都开始对其进行改动时,可真是相当的不方便,复用性也相当糟糕,基本是每个团队都做了或多或少重复的事情,而且部署和维护也是相当的麻烦, 因为庞大的应用包在N台机器上复制、启动都需要耗费不少的时间,出问题的时候也不是很好查,另外一个更糟糕的状况是很有可能会出现某个应用上的bug就导 致了全站都不可用,还有其他的像调优不好操作(因为机器上部署的应用什么都要做,根本就无法进行针对性的调优)等因素,根据这样的分析,开始痛下决心,将 系统根据职责进行拆分,于是一个大型的分布式应用就诞生了,通常,这个步骤需要耗费相当长的时间,因为会碰到很多的挑战:
1
、拆成分布式后需要提供一个高性能、稳定的通信框架,并且需要支持多种不同的通信和远程调用方式;
2
、将一个庞大的应用拆分需要耗费很长的时间,需要进行业务的整理和系统依赖关系的控制等;
3
、如何运维(依赖管理、运行状况管理、错误追踪、调优、监控和报警等)好这个庞大的分布式应用。
经过这一步,差不多系统的架构进入相对稳定的阶段,同时也能开始采用大量的廉价机器来支撑着巨大的访问量和数据量,结合这套架构以及这么多次演变过程吸取的经验来采用其他各种各样的方法来支撑着越来越高的访问量。

看看这一步完成后系统的图示:


这一步涉及到了这些知识体系:

这一步涉及的知识体系非常的多,要求对通信、远程调用、消息机制等有深入的理解和掌握,要求的都是从理论、硬件级、操作系统级以及所采用的语言的实现都有清楚的理解。

运维这块涉及的知识体系也非常的多,多数情况下需要掌握分布式并行计算、报表、监控技术以及规则策略等等。

说起来确实不怎么费力,整个网站架构的经典演变过程都和上面比较的类似,当然,每步采取的方案,演变的步骤有可能有不同,另外,由于网站的业务不同,会有不同的专业技术的需求,这篇blog更多的是从架构的角度来讲解演变的过程,当然,其中还有很多的技术也未在此提及,像数据库集群、数据挖掘、搜索等,但在真实的演变过程中还会借助像提升硬件配置、网络环境、改造操作系统、CDN镜像等来支撑更大的流量,因此在真实的发展过程中还会有很多的不同,另外一个大型网站要做到的远远不仅仅上面这些,还有像安全、运维、运营、服务、存储等,要做好一个大型的网站真的很不容易,写这篇文章更多的是希望能够引出更多大型网站架构演变的介绍,:)


ps:最后附上几篇LiveJournal架构演变的文章:
从LiveJournal后台发展看大规模网站性能优化方法
http://blog.zhangjianfeng.com/article/743   
另外从这里:http://www.danga.com/words/大家可以找到更多关于现在LiveJournal网站架构的介绍。
WebDAV: 协同工作 - 蓝白色的7号 - DonewsBlog
blog.donews.com/piojo007/archive/2006/09/24/104542...
假设你所在的小组要做一个重要的公司报告。芝加哥的Mary负责写任务报告,西雅图的Sam加入销售情况报表,加里福尼亚的Charles制作精彩的图片,还有其它各地区办公室的负责人用文字将这些部分连接在一起。最后生成的文件将是完美协作的成果,展现了公司的实力和富于创新的精神。但是稍等一下,这个特别的文件是有许多部分组成,在该文件完成之前每个部分要经过大量的修改,校正和更新。如何与其他人一起共享这些改动呢?如何跟踪文件中的每一处的变动呢?到底要持续多长时间?

 

    直到最近,类似的项目仍然是一个工作统筹方面的恶梦:因为它意味着无休止地不断地查阅文件,或是并行查阅哪里的更新需要仔细地校对整理。Web甚至都不能提供多少帮助,因为它的用于协作的工具都不适合制作共享文件。

 

    但是,计算机科学家经过一段时间的研究,将超文本传输协议(HTTP)扩展到在分布式的网络环境中,实现了协作的文件制作和编辑。这种扩展被称为基于Web的分布式创作和控制协议,即WebDAV,业内人士简称之为DAV(发音与DAVE相同)。WebDAV的开发源自1998年,现在Adobe、IBM、Microsoft以及Oracle等许多大公司的相关产品已经支持这一协议了。

 

    为什么这一协议正在成为主流呢?原因之一可能是在这个技术背后的技术:它是Microsoft Internet Information Server中的机制:允许你浏览Web文件夹。同时,它也并入到像Microsoft Windows 2000 、Windows XP以及Mac OS X Server这样的操作系统中。WebDAV也进入到例如Xerox's DocuShare这样的文件管理系统和Microsoft Office 2000以及Adobe Photoshop这样的套件中。简言之,WebDAV了改变我们在Web上协同式工作的方式。

 

从HTTP到WebDAV

 

    大家都知道,HTTP是网络服务器和客户端(例如浏览器) 进行通信时使用的协议。当你单击网页中一个文件链接时, 浏览器将发送请求消息,这个消息包含消息头和方法参考。一般情况下,浏览器消息是:“使用GET方法访问位于在www.mysite.com/myPage.html的文件”。我们不必仔细研究技术细节, 记住请求的消息头包含的各种信息即可:发出请求的客户浏览器,被请求文件的名称和位置等等。服务器的工作是处理这个请求, 激活要求的方法(GET),并在响应信息中将结果发送给客户。这样的话,响应是回流到浏览器的HTML文件。浏览器显示此 HTML,然后与服务器的连接被释放。

 

    HTTP是一个特别简单的协议。消息传输的模型直观。此外,HTTP仅支持可数的几个方法来连接服务器,发送请求消息并接收响应。HTTP的简单使得WEB获得了极大的成功。但是,简单也导致了它的局限性。例如,HTTP是一个无状态的协议,用一句易于理解的话说就是:“当你最后离开我们的站点时,我们不记得你做了些什么,因此你必须从断开处重建你的搜索”。

 

   此外HTTP还有更多的局限,例如它不提供向远程服务器写文件的方法。短言之,仅仅使用HTTP是不够的,内容管理和真正的合作仍需要专用的方案。而WebDAV协议看上去似乎可以解决这些问题。

 

 扩展的HTTP

 

   WebDAV扩展了HTTP的基本请求/响应模型,新的方法使创作者能够在远程服务器上直接创建和修改基于WEB的文件。从我们已知的消息来看,WebDAV标准如HTTP一样不受WWW (World Wide Web)联盟的控制。相反地,WebDAV被Internet Engineering Task Force (IETF)中的一个网络工作组Network Working Groups所管理。其规范是一个IETF的请求说明,并列为RFC2518。

 

     依据此规范,WebDAV的目标是提供一种让客户能够远程的创作WEB内容的标准;DAV-分布式创作和控制—在WebDAV中表明了一个创造交互式与协作应用的框架。正是这些特性使得WebDAV激动人心。

 

     目前WebDAV的功能分为三类:命名空间管理、锁和所有权管理。WebDAV增加了基本的操作(拷贝和移动方法),允许应用程序拷贝和移动单个的文件。另外,WebDAV提供mkcol方法,使得工具能收集文件并提取文件的分级信息(例如,传统文件系统中的目录列表)。技术上讲,这些方法属于命名空间管理类。他们通过允许创建目录和文件来实现基本的创作目标。

 

     分布式创作的一个重要方面是协作。为了支持这个特征,WebDAV采用了两个方法(加锁和解锁),以使一个用户在编辑文件时将其锁住以防止并发问题,并避免多个协作者相互覆盖其他人的改动。

 

    WebDAV的所有权机制是它最有用的特征之一。本质上讲,在WebDAV中,所有权是元信息—表明谁创建这个文件、谁最后修改了这个文件等等。但是,在分布式创作环境中,问题会变得更加复杂。例如,你想编辑的资源是否可以获得,创作者是否有权限删除这个文件?通过所有权,可以发现和管理资源,并且,所有权可以使你实现更加高级的特性。该规范建议创建一个“主题” 所有权,允许以这些“主题”来检索所有的资源。

 

    为支持这些特征,WebDAV提供了“Propfind”方法来查寻文件的各种所有权。同样有一个“Proppatch”方法,允许客户端工具设置,修改和删除一个所有权。一旦所有权被设置,一种被称为“DASL(DAV查找和定位协议)”的辅助技术允许应用根据所有权值来查找Web资源。

 

     对于互操作性,一个分布式创作应用应当既独立于服务器平台——不管它是IIS、Apache或是其它的服务器,同时也应独立于浏览器——不管它是微软的IE,Netscape的Navigator或是PALM的Pilot。因为WebDAV基于HTTP,所以它必定独立于平台。通过保留旧的HTTP的消息格式和增加新的HTTP消息头WebDAV保留了平台独立的体系结构。这些消息头携带支持新的WebDAV应用的信息参数,以允许应用访问和设置所有权信息等等。而且,请求和响应消息以XML格式编码,此编码易于在以后增加新的特征,如所有权域。

 

支持软件

 

     为了寻找WebDAV的支持,你可能从三个层次入手:操作系统层、WEB服务器层和包括WEB创作工具的应用层。在操作系统层,WebDAV通常提供基于Web联接的分布式文件共享服务。例如,微软利用WebDAV的优点实现了在Windows Explore上包含Web文件夹。Windows 2000和Windows XP提供了浏览远端目录、创建和操作文件的能力。同样地,苹果公司的MacOS X Server现在也包括了一个单独的WebDAV模块来为Mac客户提供文件服务。苹果甚至在将来想以WebDAV代替苹果文件共享。

 

    由于Web服务器将可能提供巨多的分布式文件,你可能会看到WebDAV将在这个层次上实现得更加完备:方法就是安装WebDAV。对于Apache,最通用的方法是安装名为mod_dav的开放源代码模块。作为一个首先实现WebDAV协议的参照,mod_dav完全支持RFC2518。而且,mod_dav是Apache中八个最流行的模块。依据2001年11月Apache模块报告(在www.securityspace.com/s_survey/data/man.200110/apachemods.html 中可以查到),接近2%的公共站点已经安装了它。

 

    IBM在其IBM HTTP服务器和WebSphere产品中使用mod_dav,表明WebDAV 同样可用于Intranet环境中。IBM Alphaworks同样允许Java开发者通过它的Dav4J项目来试着创建WebDAV应用。Dav4J是一个WebDAV客户的Java实现,它可以和Apache(通过mod_dav)或IBM WebSphere一起工作。

 

    WebDAV的应用广泛:包括创作工具、内容管理系统和大量企业软件。当前的应用经常相互集成,例如,一个最流行的Web创作工具:Macromedia的Dreamweaver,依赖WebDAV来集成其领先的使用WebDAV协议的内容管理系统。Dreamweaver当前集成了Vignette、Documentum、BroadVision和ATG。

 

    这个协议的最大的支持者之一Adobe在Adobe Acrobat 5.0 和 GoLive中集成了WebDAV。Acrobat利用WebDAV的优点来让多个检查者同时对在线的Adobe PDF文件增加说明。GoLive 5.0是Adobe的专业Web站点创作、制作和管理工具,它包括一个WebDAV浏览器,以允许Web设计者按工作组的方式进行工作:浏览远端文件夹或编辑远端文件。为了流水化协作,这个工具允许你登录、检查、锁定文件,以使你正在工作的文件不会由于同组的成员的误操作而被修改。

 

    现在有无数其它的商业程序支持WebDAV。例如,Oracle使用一种定制的版本mod_dav来支持到本公司的内容管理系统的Web接口。Rational使用mod_dav的一种定制的版本来支持WebDAV用于ClearCase存贮。支持该标准的商用和开放源代码软件的部分目录可以在WebDAV站点找到。(见下文中的资源工具条。)

 

结论

 

     与WebDAV用途一样,RFC2518具有DAV协议的第一部分:分布式创作。第二部分关于控制的规范还没有出台。有关控制的工作正在进行中,并且也处在由Delta/V项目(www1.ietf.org/mail-archive/ietf-announce/Current/msg14617.html)赞助的开发之中。这就意味着支持WebDAV的工具必需依靠版本管理产品来管理这方面的协作。例如,Dreamweaver 与Microsoft的Visual SourceSafe结合在一起来提供版本管理的功能。显然,这不是一个通用的解决方案。

 

     最后,WebDAV没有考虑安全性的问题。但是同XML在一起,你应该遵守常识规则,并且注意使用现有的基础设施来保护。例如,在允许一个客户浏览,打开以及修改一个资源之前,你应该对这个客户进行身份认证。通常使用的方法是口令认证。由于基本的认证能够在一个不安全的通道内被截获,所以建议您使用安全连接机制,例如传输层安全。



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1045428

关闭apache的文件list功能, 文件列表
make sure you remove option indexes between

<Directory "/usr/local/apache/htdocs">;
   option indexes ...
...
</Directory>;

下面是最常用的40个CSS/JS风格和功能技术处理表单元素,真是收集的很全。

 

1-Styling dropdown select boxes-  修饰下拉列表。

form field


2-<select> Something New, Part 1-  使用一点 DOM scripting 和一些有创意的CSS,你能让下拉列表好看的多。

form field


3-Styling even more form controls- 这是对HTML表单元素的控制,通过CSS能控制checkbox选择的不同显示效果。

form field


4-Check it, don’t select it- 当多选框选择元素太多,让选择项可以滚动的效果。demo代码在这里: here.

form field


5-DropDown - xHTML/CSS/Javascript replacement of classic selectbox- 这是一个替代传统下拉列表的demo。

form field


6-Masked Input Plugin- 这是对jQuery库进行修改后的效果,提供给用户更方便输入和进行验证。代码在 Internet Explorer 6/7, Firefox 1.5/2, Safari, 和 Opera上测试通过.

form field


7-Custom Checkbox with jQuery- 提供定制化的checkbox效果。有 Safari skin 和 default skin两种皮肤供选择。

form field


8-LiveValidation- LiveValidation 是一个小开源 javascript 库,提供客户端输入验证。

form field


9-FancyForm- FancyForm 是一个强大的checkbox替代脚本,在外观和功能方面提供最强的灵活性。

 

form field


10-Styling disabled text inputs-  一个不可输入的文本输入框。查看demo代码: Styling disabled form controls with CSS

form field


11-PrettyCheckboxes- 一个简单的 jQuery 插件 来定制checkbox和radio buttons的外观。

form field


12- Building a better web forms: Context highlighting using jQuery- 当用户输入焦点变化时,输入框效果变化,demo代码在这里:here

form field


13-Control.SelectMultiple  这是下拉列表和checkbox同时使用的例子,很酷。

 

form field


14- Justify elements using jQuery and CSS- 创建一个表单,内部元素需要精确定位对齐,你可以使用jQuery轻松做到这一点.

form field


15-jQuery Form Input Example Plugin- 一个 jQuery 插件,在用户输入焦点进入后提示文字消失,很多网站用这一招。demo代码在这里: here.

form field


16-Jquery-Autotab- 自动tab跳转,也是一个 jQuery 插件。

 

form field


17-jquery-asmselect- 下拉列表的增强版。demo代码这里: here and here.

form field


18-jQuery.AddToList- 一个非常方便定制的jQuery插件,下拉显示更多内容,通过AJAX方式新增内容,如果新增成功,成为下拉菜单的选项之一。很有用的技巧,Demo代码这里: here.

form field


19-Easy Multi Select Transfer with jQuery- 一个jQuery完美的菜单选择例子。

form field


20-fValidator- fValidator 是一个开源免费 javascript 工具,提供简单表单验证。例子在这里: examples .

form field


21-Grow a textarea- 提供重新定义textarea框大小的功能。

 

form field


22-jQuery selectbox replacement-  一个 jQuery 插件,提供更好界面替换HTML下拉列表。demo代码在这里: here.

form field


23-Unobtrusive Slider Control V2- 通过输入值滑动块定位,以及改变颜色等。demo例子在这里: here.

form field


24- jQuery Field Plug-in- jQuery插件,提供强大的form表单控制功能,比如文件上传类型等。

 

form field


25-jquery.combobox- jquery.combobox是一个有用的创建HTML风格combobox工具。 demo代码在这里: here.

 

form field


26-Checkboxes, Radio Buttons, Select Lists, Custom HTML Form Elements- 这个 JavaScript 和 CSS 提供可定制的图片作为背景给checkbox, radio buttons 和 select lists.

form field


27-ToggleFormText plug-in example- ToggleFormText 是一个 jQuery 插件提供输入框帮助文字显示。

 

form field


28-Password field with strength meter- extjs库,显示密码强度。

 

form field


29-STYLING FILE INPUTS WITH CSS AND THE DOM- 优美的文件输入框设计。

 

form field


30-Pin plugin for Prototype, Remember Field’s Values- prototype 的 Pin 插件提供记录某个输入框值的功能。demo代码: here.

form field


31-accessible, javascript-enhanced, css-able form elements for mootools- 一个mootools javascript-class 客户定制元素,能够通过CSS定制你的 checkboxes 和 radiobuttons 。

form field


32-Resizeable Textboxes- 重定义text输入框的大小。

form field


33-Resizeable Textboxes- 用图片代替按钮,用 JavaScript 和 jQuery写的.  demo 这里:here.

form field


34-jQuery AlphaNumeric- jQuery AlphaNumeric 是一个 javascript控制插件,限制textboxes 或者 textareas输入字符长度。

form field


35-Mootools Form Hints- Mootools/Javascript Form 提供输入框在线帮助。

 

form field


36-MultiSelect- 下拉选择框+checkbox效果。例子在这里: here.

form field


37- Watermark Input Plugin- 这是一个jQuery插件,显示附加信息的输入框。

form field


38-Select box manipulation

form field


39-Spinner Control 

form field


40-Autohelp

form field

 

每位用户都拥有“魔盘”上的网络空间。您可以阅览、共享文件夹及各种类型的文件。照片、图片、Word文档等,都不在话下。您更可以用手机安全地访问您电脑中的文件资料,也可将文件直接下载到手机中。

要使用远程访问这个功能请下载并安装魔橙桌面端软件,并在“文件功能”中选择 “允许远程访问”。

魔盘主界面,可查看自己魔盘和共享魔盘文件,可远程访问电脑硬盘。点击“打开”访问魔盘文件和电脑硬盘(电脑必须在线)。
查看并共享魔盘里的文件。查看并共享电脑硬盘里的文件。
存放文件到魔盘,对好友共享魔盘,上传即拍照片到魔盘。远程访问您的“电脑桌面”。
点击“golden gate.jpg”打开文件。您现在可以在手机上看到这幅存在您电脑桌面的照片。
选择“通过邮件发送”把照片发给你的朋友。在“联系人”里面选择接收者。
编写邮件(“golden gate.jpg”已经成为附件)。
 

JDBC Connection

Thanks to Guo Meng.

What is JDBC/SQLJ

JDBC是什么不用说了,关键是SQLJ.直接扒拉讲义。

JDBC is an application programming interface (API) that Java applications use to access relational databases.

SQLJ provides support for embedded static SQL in Java applications.

In general, Java applications use :

  • JDBC for dynamic SQL
  • SQLJ for static SQL.

However, because SQLJ can inter-operate with JDBC, an application program can use JDBC and SQLJ within the same unit of work.

如何写JDBC程序

照抄吧,用的太多了。

In general, you need to do the following things:

  • Access the Java(TM) packages that contain JDBC methods.
  • Declare variables for sending data to or retrieving data from DB2’s tables.
  • Connect to a data source.
  • Execute SQL statements.
  • Handle SQL errors and warnings.
  • Disconnect from the data source.

如何写SQLJ程序

好像和JDBC区别不是太大。

In general, you need to do the following things:

  • Import the Java(TM) packages that contain SQLJ and JDBC methods.
  • Declare variables for sending data to or retrieving data from DB2’s tables.
  • Connect to a data source.
  • Execute SQL statements.
  • Handle SQL errors and warnings.
  • Disconnect from the data source.

如何实现JDBC/SQLJ的驱动程序

其实归根到底就是按照JDBC的标准,把规定要实现的接口都实现了。

JDBC有4种driver架构:

JDBC Driver Type 1

Drivers that implement the JDBC API as a mapping to another data access API, such as Open Database Connectivity (ODBC). Drivers of this type are generally dependent on a native library, which limits their portability. The JDBC-ODBC Bridge driver is an example of a type 1.

JDBC Driver Type 2

Drivers that are written partly in the Java programming language and partly in native code. The drivers use a native client library specific to the data source to which they connect. Because of the native code, their portability is limited.

JDBC Driver Type 3

Drivers that use a pure Java client and communicate with a server using a database-independent protocol. The server then communicates the client's requests to the data source.

JDBC Driver Type 4

Drivers that are pure Java and implement the network protocol for a specific data source. The client connects directly to the data source.

DB2的实现

DB2 Universal JDBC Driver提供了上述Type2和Type4的接口,还实现了SQLJ的function. DB2 Universal JDBC Driver 的其他名字还包括:

  • The IBM DB2 Universal Driver for SQLJ and JDBC
  • The DB2 Universal Driver for Java Common Connectivity
  • JCC driver
  • Universal Driver type 2 > the type 2 implementation in this driver
- Universal Driver type 4 > the type 4 implementation in this driver

JDBC/SQLJ Driver for OS/390 and z/OS 提供了上述Type 2的接口,其他名字包括:

  • JDBC/SQLJ Driver for OS/390 and z/OS with JDBC 2.0
  • JDBC/SQLJ 2.0 Driver for OS/390 and z/OS
  • Legacy driver

The JDBC/SQLJ Driver for OS/390 and z/OS 在以后的DB2版本中不会被支持了。

如何选择以上Type

对于Type 2

  • T2 LUW supports shared memory and network protocols other than TCPIP
  • T2 z/OS supports direct native RRSAF-based connectivity
  • T2 z/OS supports RRS-based transaction management
  • T2 performs better for local connections

对于Type 4

  • T4 has advantages of 100% Java client
  • T4 supports XA to DB2 z/OS v7 and v8, XA to DB2 LUW in v 8.2
  • T4 performs better for remote connections

因此:Driver selection based on data souce property or URL

对以上的总结:

  • JDBC VS SQLJ: language concept
  • TYPE 2 VS TYPE 4: Connection concept
  • JDBC Driver: Implement the connection interface
  • Application written in JDBC/SQLJ connect to DB2 using Type 2/4 with JDBC driver.
从oracle表中随机取记录,产生随机数和随机字符串 - 葛宏宾的专栏 - 博客园
www.cnblogs.com/binary/archive/2005/04/01/130552.h...
UNIX 技巧: UNIX 高手的另外 10 个习惯
www-128.ibm.com/developerworks/cn/aix/library/au-u...

UNIX 技巧: UNIX 高手的另外 10 个习惯

成为 UNIX 命令行高手

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送

英文原文

英文原文


级别: 中级

John Fronckowiak, 总裁, IDC Consulting Inc.

2008 年 7 月 24 日

作为 Michael Stutz 优秀文章的后续,本文将提供另外 10 个改进您的 UNIX® 命令行效率的好习惯。了解常见错误和克服它们的方法,并确切了解为何值得采用这 10 个 UNIX 习惯。

让我们面对现实吧:坏习惯很难改变。但是您已经熟悉的习惯可能更难克服。有时,重新审视某些事情可能让您遇到“啊哈,我没想到它能做到这一点!”的时刻。在 Michael Stutz 的优秀文章“UNIX 高手的 10 个习惯”的基础上,本文将提供另外 10 个 UNIX 命令行命令、工具和技术,可以使您成为更高效的 UNIX 命令行高手。

您应当采纳的其他 10 个好习惯包括:

  • 使用文件名自动完成功能 (file name completion)。
  • 使用历史扩展。
  • 重用以前的参数。
  • 使用 pushdpopd 管理目录导航。
  • 查找大型文件。
  • 不使用编辑器创建临时文件。
  • 使用 curl 命令行实用工具。
  • 最有效地利用正则表达式。
  • 确定当前用户。
  • 使用 awk 处理数据。
常用首字母缩写词
  • MB:兆字节
  • HTTP:超文本传输协议
  • HTTPS:HTTP over Secure Sockets Layer
  • FTP:文件传输协议
  • FTPS:FTP over Secure Sockets Layer
  • LDAP:轻型目录访问协议

使用文件名完成

如果不需要在命令提示符处键入长的、令人费解的文件名,这是不是很棒呢?的确,您不需要这样做。相反,您可以配置最流行的 UNIX Shell 以使用文件名完成。该功能在各个 Shell 中的工作方式略有不同,因此我将向您展示如何在最流行的 Shell 中使用文件名完成。文件名完成使您可以更快地输入并避免错误。懒惰?也许吧。效率更高?当然!

我正在运行哪种 Shell?

如果您不知道目前使用的是哪一种 Shell,会怎么样?虽然这个诀窍不是另外 10 个好习惯的正式组成部分,但它仍然很有用。如清单 1 所示,您可以使用 echo $0ps -p $$ 命令显示您正在使用的 Shell。对于我来说,运行的是 Bash Shell。


清单 1. 确定您的 Shell
                
$ echo $0
-bash
$ ps –p $$
PID TTY           TIME CMD
6344 ttys000    0:00.02 –bash

C Shell

C Shell 支持最直接文件名完成功能。设置 filec 变量可启用该功能。(您可以使用命令 set filec。)在您开始键入文件名后,可以按 Esc 键,Shell 将完成文件名,或完成尽可能多的部分。例如,假设您拥有名为 file1、file2file3 的文件。如果您键入 f,然后按 Esc 键,将填充 file,而您必须键入 123 来完成相应的文件名。

Bash

Bash Shell 也提供了文件名完成,但使用 Tab 键代替 Esc 键。您在 Bash Shell 中不需要设置任何选项即可启用文件名完成,该选项是缺省设置的。Bash 还实现了其他功能。键入文件名的一部分后,按 Tab 键,如果有多个文件满足您的请求,并且您需要添加文本以选择其中一个文件,那么您可以多按 Tab 键两次,以显示与您目前键入的内容相匹配的文件的列表。使用之前名为 file1、file2file3 的文件示例,首先键入 f。当您按一次 Tab 键时,Bash 完成 file;再按一次 Tab 键时,将展开列表 file1 file2 file3

Korn Shell

对于 Korn Shell 用户,文件名完成取决于 EDITOR 变量的值。如果 EDITOR 设置为 vi,那么您键入部分名称,然后按 Esc 键,后跟反斜杠 (\) 字符。如果 EDITOR 设置为 emacs,那么您键入部分名称,然后按两次 Esc 键以完成文件名。

使用历史扩展

如果您为一系列命令使用相同的文件名,会发生什么情况?当然,有一种快捷方式可以快速获得您上次使用的文件名。如清单 2 所示,!$ 命令返回前一个命令使用的文件名。从文件 this-is-a-long-lunch-menu-file.txt 中搜索单词 pickles 的出现位置。搜索结束后,使用 vi 命令来编辑 this-is-a-long-lunch-menu-file.txt 文件,而不需要重新键入文件名。您使用感叹号 (!) 来访问历史,然后使用美元符号 ($) 返回前一命令的最后字段。如果您反复用到长文件名,那么这是一个非常好的工具。


清单 2. 使用 !$ 获得前一个命令使用的文件名
                
$ grep pickles this-is-a-long-lunch-menu-file.txt
pastrami on rye with pickles and onions
$ vi !$		    

重用以前的参数

!$ 命令返回某个命令使用的上一个文件名参数。但如果某个命令使用多个文件名,而您只希望重用其中一个文件名,该如何做?!:1 操作符返回某个命令使用的第一个文件名。清单 3 中的示例显示可以如何将此操作符与 !$ 运算符组合使用。在第一个命令中,将一个文件重新命名为更有意义的名称,但为了保持原始文件名可用,创建了一个符号链接。重新命名文件 kxp12.c 以提高可读性,然后使用 link 命令来创建到原始文件名的符号链接,以防在其他位置使用该文件名。!$ 操作符返回 file_system_access.c 文件名,而 !:1 操作符返回 kxp12.c 文件名,该文件名是上个命令的第一个文件名。


清单 3. 组合使用 !$ 和 !:1
                
$ mv kxp12.c file_system_access.c
$ ln –s !$ !:1

使用 pushd 和 popd 管理目录导航

UNIX 支持各种目录导航工具。我最喜欢的两款提高工作效率的工具是 pushdpopd。您当然了解 cd 命令用于更改您的当前目录。如果您要在多个目录中导航,但希望能够快速返回某个位置,该如何做?pushdpopd 命令创建一个虚拟目录堆栈,pushd 命令用来更改您的当前目录并将其存储在堆栈中,而 popd 命令用来从堆栈的顶部移除目录并使您返回该位置。您可以使用 dirs 命令来显示当前目录堆栈,而不会压入或弹出新目录。清单 4 显示如何使用 pushdpopd 命令在目录树中快速导航。


清单 4. 使用 pushd 和 popd 在目录树中导航
                
$ pushd .
~ ~
$ pushd /etc
/etc ~ ~
$ pushd /var
/var /etc ~ ~
$ pushd /usr/local/bin
/usr/local/bin /var /etc ~ ~
$ dirs
/usr/local/bin /var /etc ~ ~
$ popd
/var /etc ~ ~
$ popd
/etc ~ ~
$ popd
~ ~
$ popd

pushdpopd 命令还支持使用参数处理目录堆栈。使用 +n -n 参数,其中 n 是一个数字,您可以向左或向右移动堆栈,如清单 5 所示。


清单 5. 旋转目录堆栈
                
$ dirs
/usr/local/bin /var /etc ~ ~
$ pushd +1
/var /etc ~ ~ /usr/local/bin
$ pushd -1
~ /usr/local/bin /var /etc ~

查找大型文件

是否需要找出您的所有空闲磁盘空间被什么占用了?您可以使用以下几个工具来管理您的存储设备。如清单 6 所示,df 命令为您显示每个可用卷上已使用的块的总数,以及空闲空间的百分比。


清单 6. 确定卷的使用情况
                
$ df
Filesystem                            512-blocks      Used  Available Capacity  Mounted on
/dev/disk0s2                           311909984 267275264   44122720    86%    /
devfs                                        224       224          0   100%    /dev
fdesc                                          2         2          0   100%    /dev
map -hosts                                     0         0          0   100%    /net
map auto_home                                  0         0          0   100%    /home

是否希望查找大型文件?使用 find 命令时附带 -size 参数。清单 7 显示了如何使用 find 命令来查找大于 10MB 的文件。请注意,-size 参数以 KB 为单位计量大小。


清单 7. 查找大于 10MB 的所有文件
                		  
$ find / -size +10000k –xdev –exec ls –lh {}\;

不使用编辑器创建临时文件

以下是一个简单示例:您需要快速创建一个简单临时文件,但不希望启动您的编辑器。使用带有 > 文件重定向操作符的 cat 命令。如清单 8 所示,使用不带文件名的 cat 命令只回显向标准输入键入的任何内容;> 重定向将该输入捕获到指定的文件中。请注意,您在结束键入时必须提供文件结束字符,通常为 Ctrl-D。


清单 8. 快速创建临时文件
                	
$ cat > my_temp_file.txt
This is my temp file text
^D
$ cat my_temp_file.txt
This is my temp file text

需要执行相同操作,但是附加到现有文件而不是创建新文件。如清单 9 所示,改用 >> 操作符。>> 文件重定向操作符向现有文件附加内容。


清单 9.快速向文件附加内容
                
$ cat >> my_temp_file.txt
More text
^D
$ cat my_temp_file.txt
This is my temp file text
More text

使用 curl 命令行实用工具

我是否可以从命令行访问 Web?你疯了吗?没有,这就是 curl 的用途!curl 命令使您可以使用 HTTP、HTTPS、FTP、FTPS、Gopher、DICT、TELNET、LDAP 或 FILE 协议从服务器检索数据。如清单 10 所示,我可以使用 curl 命令从美国国家气象局了解我所在位置(纽约州布法罗市)的当前天气状况。当与 grep 命令组合使用时,我可以检索布法罗市的天气状况。使用 -s 命令行选项来禁止 curl 处理输出。


清单 10. 使用 curl 检索当前天气状况
                
$ curl –s http://www.srh.noaa.gov/data/ALY/RWRALY | grep BUFFALO
BUFFALO        MOSUNNY   43  22  43 NE13      30.10R

清单 11 所示,您也可以使用 curl 命令来下载 HTTP 托管的文件。使用 -o 参数来指定保存输出的位置。


清单 11. 使用 curl 下载 HTTP 承载的文件
                
$ curl -o archive.tar http://www.somesite.com/archive.tar

这实际上只是您使用 curl 命令可以完成的操作的提示。您只需在命令提示符处键入 man curl 显示 curl 命令的完整使用信息,就可以开始了解更多内容。

最有效地利用正则表达式

大量 UNIX 命令使用正则表达式作为参数。从技术角度而言,正则表达式 是表示某种模式的字符串(也就是说,由字母、数字和符号组成的字符序列),用于定义零或更长的字符串。正则表达式使用元字符(例如,星号 [*] 和问号 [?])来匹配其他字符串的部分或全部内容。正则表达式不一定包含通配符,但通配符可以使正则表达式在搜索模式和处理文件时发挥更大的作用。表 1 显示了一些基本正则表达式序列。


表 1. 正则表达式序列
序列说明
脱字符 (^)匹配出现在行首的表达式,例如 ^A
美元符号 ($)匹配出现在行末的表达式,例如 A$
反斜杠 (\)取消下一个字符的特殊含义,例如 \^
方括号 ([])匹配括起来的任一字符,例如 [aeiou](使用连字符 [-] 表示范围,例如 [0-9])。
[^ ] 匹配除括起来字符以外的任一字符,例如 [^0-9]
句点 (.)匹配除行尾之外的任意单个字符
星号 (*)匹配零个或多个前驱字符或表达式
\{x,y\} 匹配出现过 xy 个和前面相同的内容
\{x\} 精确匹配出现过 x 个和前面相同的内容
\{x,\} 匹配出现过 x 个或更多和前面相同的内容

清单 12 显示了与 grep 命令一起使用的一些基本正则表达式。


清单 12. 使用正则表达式和 grep
                
$ # Lists your mail
$ grep '^From: ' /usr/mail/$USER   
$ # Any line with at least one letter  
$ grep '[a-zA-Z]'  search-file.txt
$ # Anything not a letter or number
$ grep '[^a-zA-Z0-9] search-file.txt
$ # Find phone numbers in the form 999-9999 
$ grep '[0-9]\{3\}-[0-9]\{4\}' search-file.txt
$ # Find lines with exactly one character
$ grep '^.$' search-file.txt
$ #  Find any line that starts with a period "."          
$ grep '^\.' search-file.txt 
$ # Find lines that  start with a "." and 2 lowercase letters
$ grep '^\.[a-z][a-z]' search-file.txt

有大量书籍专门讲述正则表达式。有关命令行正则表达式的深入描述,建议您阅读 developerWorks 文章“对话 UNIX,第 9 部分:正则表达式。”

确定当前用户

有时,您可能希望确定某个特定用户是否运行过您的管理脚本。为找出答案,您可以使用 whoami 命令来返回当前用户的名称。清单 13 显示了独自运行的 whoami 命令;清单 14 显示了使用 whoami 确保当前用户不是根用户的 Bash 脚本的摘录。


清单 13. 从命令行使用 whoami
                
$ whoami
John


清单 14. 在脚本中使用 whoami
                
if [ $(whoami) = "root" ]
then
   echo "You cannot run this script as root."
   exit 1
fi

使用 awk 处理数据

awk 命令似乎始终处在 Perl 的阴影下,但它对于简单、基于命令行的数据处理来说是一个快速、实用的工具。清单 15 显示了如何开始使用 awk 命令。若要获取文件中每行文本的长度,请使用 length() 函数。若要查看字符串 ing 是否出现在文件文本中,请使用 index() 函数,该函数返回 ing 首次出现的位置,这样您就可以使用它来进行进一步的字符串处理。若要 tokenize(也就是说,将一行拆分为单词长度的片段)某个字符串,请使用 split() 函数。


清单 15. 基本 awk 处理
                
$ cat text
testing the awk command
$ awk '{ i = length($0); print i }' text
23
$ awk '{ i = index($0,”ing”); print i}' text
5
$ awk 'BEGIN { i = 1 } { n = split($0,a," "); while (i <= n) {print a[i]; i++;} }' text
testing 
the
awk
command

打印文本文件中的指定字段是一项简单的 awk 任务。在清单 16 中,sales 文件包含每个销售人员的姓名,后跟每月销售数字。您可以使用 awk 命令来快速获得每个月的销售总额。缺省情况下,awk 将每个以逗号分隔的值视为不同的字段。您使用 $n 操作符来访问每个字段。


清单 16. 使用 awk 对数据进行汇总
                
$cat sales
Gene,12,23,7
Dawn,10,25,15
Renee,15,13,18
David,8,21,17
$ awk -F, '{print $1,$2+$3+$4}' sales
Gene 42
Dawn 50
Renee 46
David 46

awk 命令可以很复杂并应用于广泛的情景中。若要更完整地学习 awk 命令,请从命令 man awk 开始,并参阅参考资料部分提供的资源。

结束语

成为命令行高手需要进行一些实践。按照相同的方式处理问题很简单,因为您已经习惯了。扩展您的命令行资源可以显著提高您的工作效率,并促使您朝着 UNIX 命令行高手的方向前进!



参考资料

学习

讨论


关于作者

John Fronckowiak 是 IDC Consulting Inc. 的总裁兼创始人,他还是曼达尔大学成人和继续教育学院计算机信息系统的临床助理教授。他还撰写了几本关于 Web 应用程序开发、编程、数据库设计和开发以及网络方面的书籍和多篇文章。

UNIX 高手的 10 个习惯

克服不良的 UNIX 使用模式

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

将打印机的版面设置成横向打印模式

打印本页

将此页作为电子邮件发送

将此页作为电子邮件发送


级别: 中级

Michael Stutz (stutz@dsl.org), 作家, 顾问

2007 年 2 月 09 日

采用 10 个能够提高您的 UNIX® 命令行效率的好习惯——并在此过程中摆脱不良的使用模式。本文循序渐进地指导您学习几项用于命令行操作的技术,这些技术非常好,但是通常被忽略。了解常见错误和克服它们的方法,以便您能够确切了解为何值得采用这些 UNIX 习惯。
本文的续篇《UNIX 高手的另外 10 个习惯》已经推出,又继续向您介绍了 10 个新的 UNIX 使用习惯,欢迎您访问。

引言

当您经常使用某个系统时,往往会陷入某种固定的使用模式。有时,您没有养成以尽可能最好的方式做事的习惯。有时,您的不良习惯甚至会导致出现混乱。纠正此类缺点的最佳方法之一,就是有意识地采用抵制这些坏习惯的好习惯。本文提出了 10 个值得采用的 UNIX 命令行习惯——帮助您克服许多常见使用怪癖,并在该过程中提高命令行工作效率的好习惯。下面列出了这 10 个好习惯,之后对进行了更详细的描述。

采用 10 个好习惯

要采用的十个好习惯为:

  1. 在单个命令中创建目录树
  2. 更改路径;不要移动存档
  3. 将命令与控制操作符组合使用
  4. 谨慎引用变量
  5. 使用转义序列来管理较长的输入
  6. 在列表中对命令分组
  7. find 之外使用 xargs
  8. 了解何时 grep 应该执行计数——何时应该绕过
  9. 匹配输出中的某些字段,而不只是对行进行匹配
  10. 停止对 cat 使用管道

在单个命令中创建目录树

清单 1 演示了最常见的 UNIX 坏习惯之一:一次定义一个目录树。


清单 1. 坏习惯 1 的示例:单独定义每个目录树
                
~ $ mkdir tmp
~ $ cd tmp
~/tmp $ mkdir a
~/tmp $ cd a
~/tmp/a $ mkdir b
~/tmp/a $ cd b
~/tmp/a/b/ $ mkdir c
~/tmp/a/b/ $ cd c
~/tmp/a/b/c $

使用 mkdir-p 选项并在单个命令中创建所有父目录及其子目录要容易得多。但是即使对于知道此选项的管理员,他们在命令行上创建子目录时也仍然束缚于逐步创建每级子目录。花时间有意识地养成这个好习惯是值得的:


清单 2. 好习惯 1 的示例:使用一个命令来定义目录树
                
~ $ mkdir -p tmp/a/b/c
            

您可以使用此选项来创建整个复杂的目录树(在脚本中使用是非常理想的),而不只是创建简单的层次结构。例如:


清单 3. 好习惯 1 的另一个示例:使用一个命令来定义复杂的目录树
                
~ $ mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
            

过去,单独定义目录的唯一借口是您的 mkdir 实现不支持此选项,但是在大多数系统上不再是这样了。IBM、AIX®、mkdir、GNU mkdir 和其他遵守单一 UNIX 规范 (Single UNIX Specification) 的系统现在都具有此选项。

对于仍然缺乏该功能的少数系统,您可以使用 mkdirhier 脚本(请参见参考资料),此脚本是执行相同功能的 mkdir 的包装:

~ $ mkdirhier project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
            

更改路径;不要移动存档

另一个不良的使用模式是将 .tar 存档文件移动到某个目录,因为该目录恰好是您希望在其中提取 .tar 文件的目录。其实您根本不需要这样做。您可以随心所欲地将任何 .tar 存档文件解压缩到任何目录——这就是 -C 选项的用途。在解压缩某个存档文件时,使用 -C 选项来指定要在其中解压缩该文件的目录:


清单 4. 好习惯 2 的示例:使用选项 -C 来解压缩 .tar 存档文件
                
~ $ tar xvf -C tmp/a/b/c newarc.tar.gz
            

相对于将存档文件移动到您希望在其中解压缩它的位置,切换到该目录,然后才解压缩它,养成使用 -C 的习惯则更加可取——当存档文件位于其他某个位置时尤其如此。





回页首


将命令与控制操作符组合使用

您可能已经知道,在大多数 Shell 中,您可以在单个命令行上通过在命令之间放置一个分号 (;) 来组合命令。该分号是 Shell 控制操作符,虽然它对于在单个命令行上将离散的命令串联起来很有用,但它并不适用于所有情况。例如,假设您使用分号来组合两个命令,其中第二个命令的正确执行完全依赖于第一个命令的成功完成。如果第一个命令未按您预期的那样退出,第二个命令仍然会运行——结果会导致失败。相反,应该使用更适当的控制操作符(本文将描述其中的部分操作符)。只要您的 Shell 支持它们,就值得养成使用它们的习惯。

仅当另一个命令返回零退出状态时才运行某个命令

使用 && 控制操作符来组合两个命令,以便仅当 第一个命令返回零退出状态时才运行第二个命令。换句话说,如果第一个命令运行成功,则第二个命令将运行。如果第一个命令失败,则第二个命令根本就不运行。例如:


清单 5. 好习惯 3 的示例:将命令与控制操作符组合使用
                
~ $ cd tmp/a/b/c && tar xvf ~/archive.tar
            

在此例中,存档的内容将提取到 ~/tmp/a/b/c 目录中,除非该目录不存在。如果该目录不存在,则 tar 命令不会运行,因此不会提取任何内容。

仅当另一个命令返回非零退出状态时才运行某个命令

类似地,|| 控制操作符分隔两个命令,并且仅当第一个命令返回非零退出状态时才运行第二个命令。换句话说,如果第一个命令成功,则第二个命令不会运行。如果第一个命令失败,则第二个命令才会 运行。在测试某个给定目录是否存在时,通常使用此操作符,如果该目录不存在,则创建它:


清单 6. 好习惯 3 的另一个示例:将命令与控制操作符组合使用
                
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c
            

您还可以组合使用本部分中描述的控制操作符。每个操作符都影响最后的命令运行:


清单 7. 好习惯 3 的组合示例:将命令与控制操作符组合使用
                
~ $ cd tmp/a/b/c || mkdir -p tmp/a/b/c && tar xvf -C tmp/a/b/c ~/archive.tar
            





回页首


谨慎引用变量

始终要谨慎使用 Shell 扩展和变量名称。一般最好将变量调用包括在双引号中,除非您有不这样做的足够理由。类似地,如果您直接在字母数字文本后面使用变量名称,则还要确保将该变量名称包括在方括号 ([]) 中,以使其与周围的文本区分开来。否则,Shell 将把尾随文本解释为变量名称的一部分——并且很可能返回一个空值。清单 8 提供了变量的各种引用和非引用及其影响的示例。


清单 8. 好习惯 4 的示例:引用(和非引用)变量
                
~ $ ls tmp/
a b
~ $ VAR="tmp/*"
~ $ echo $VAR
tmp/a tmp/b
~ $ echo "$VAR"
tmp/*
~ $ echo $VARa

~ $ echo "$VARa"

~ $ echo "${VAR}a"
tmp/*a
~ $ echo ${VAR}a
tmp/a
~ $





回页首


使用转义序列来管理较长的输入

您或许看到过使用反斜杠 (\) 来将较长的行延续到下一行的代码示例,并且您知道大多数 Shell 都将您通过反斜杠联接的后续行上键入的内容视为单个长行。然而,您可能没有在命令行中像通常那样利用此功能。如果您的终端无法正确处理多行回绕,或者您的命令行比通常小(例如在提示符下有长路经的时候),反斜杠就特别有用。反斜杠对于了解键入的长输入行的含义也非常有用,如以下示例所示:


清单 9. 好习惯 5 的示例:将反斜杠用于长输入
                
~ $ cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar
            

或者,也可以使用以下配置:


清单 10. 好习惯 5 的替代示例:将反斜杠用于长输入
                
~ $ cd tmp/a/b/c \
>                 || \
> mkdir -p tmp/a/b/c \
>                    && \
> tar xvf -C tmp/a/b/c ~/archive.tar
            

然而,当您将输入行划分到多行上时,Shell 始终将其视为单个连续的行,因为它总是删除所有反斜杠和额外的空格。

注意:在大多数 Shell 中,当您按向上箭头键时,整个多行输入将重绘到单个长输入行上。





回页首


在列表中对命令分组

大多数 Shell 都具有在列表中对命令分组的方法,以便您能将它们的合计输出向下传递到某个管道,或者将其任何部分或全部流重定向到相同的地方。您一般可以通过在某个 Subshell 中运行一个命令列表或通过在当前 Shell 中运行一个命令列表来实现此目的。

在 Subshell 中运行命令列表

使用括号将命令列表包括在单个组中。这样做将在一个新的 Subshell 中运行命令,并允许您重定向或收集整组命令的输出,如以下示例所示:


清单 11. 好习惯 6 的示例:在 Subshell 中运行命令列表
                
~ $ ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"
            

在此示例中,该存档的内容将提取到 tmp/a/b/c/ 目录中,同时将分组命令的输出(包括所提取文件的列表)通过邮件发送到地址 admin

当您在命令列表中重新定义环境变量,并且您不希望将那些定义应用于当前 Shell 时,使用 Subshell 更可取。

在当前 Shell 中运行命令列表

将命令列表用大括号 ({}) 括起来,以在当前 Shell 中运行。确保在括号与实际命令之间包括空格,否则 Shell 可能无法正确解释括号。此外,还要确保列表中的最后一个命令以分号结尾,如以下示例所示:


清单 12. 好习惯 6 的另一个示例:在当前 Shell 中运行命令列表
                
~ $ { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"
            





回页首


在 find 之外使用 xargs

使用 xargs 工具作为筛选器,以充分利用从 find 命令挑选的输出。find 运行通常提供与某些条件匹配的文件列表。此列表被传递到 xargs 上,后者然后使用该文件列表作为参数来运行其他某些有用的命令,如以下示例所示:


清单 13. xargs 工具的经典用法示例
                
~ $ find some-file-criteria some-file-path | \
> xargs some-great-command-that-needs-filename-arguments
                
            

然而,不要将 xargs 仅看作是 find 的辅助工具;它是一个未得到充分利用的工具之一,当您养成使用它的习惯时,将会希望进行所有试验,包括以下用法。

传递空格分隔的列表

在最简单的调用形式中,xargs 就像一个筛选器,它接受一个列表(每个成员分别在单独的行上)作为输入。该工具将那些成员放置在单个空格分隔的行上:


清单 14. xargs 工具产生的输出示例
                
~ $ xargs
                a
                b
                c
                
                    Control-D
                
a b c
~ $

您可以发送通过 xargs 来输出文件名的任何工具的输出,以便为其他某些接受文件名作为参数的工具获得参数列表,如以下示例所示:


清单 15. xargs 工具的使用示例
                
~/tmp $ ls -1 | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
~/tmp $ ls -1 | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable
~/tmp $

xargs 命令不只用于传递文件名。您还可以在需要将文本筛选到单个行中的任何时候使用它:


清单 16. 好习惯 7 的示例:使用 xargs 工具来将文本筛选到单个行中
                
~/tmp $ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh
~/tmp $

谨慎使用 xargs

从技术上讲,使用 xargs 很少遇到麻烦。缺省情况下,文件结束字符串是下划线 (_);如果将该字符作为单个输入参数来发送,则它之后的所有内容将被忽略。为了防止这种情况发生,可以使用 -e 标志,它在不带参数的情况下完全禁用结束字符串。





回页首


了解何时 grep 应该执行计数——何时应该绕过

避免通过管道将 grep 发送到 wc -l 来对输出行数计数。grep-c 选项提供了对与特定模式匹配的行的计数,并且一般要比通过管道发送到 wc 更快,如以下示例所示:


清单 17. 好习惯 8 的示例:使用和不使用 grep 的行计数
                
~ $ time grep and tmp/a/longfile.txt | wc -l
2811

real    0m0.097s
user    0m0.006s
sys     0m0.032s
~ $ time grep -c and tmp/a/longfile.txt
2811

real    0m0.013s
user    0m0.006s
sys     0m0.005s
~ $ 

除了速度因素外,-c 选项还是执行计数的好方法。对于多个文件,带 -c 选项的 grep 返回每个文件的单独计数,每行一个计数,而针对 wc 的管道则提供所有文件的组合总计数。

然而,不管是否考虑速度,此示例都表明了另一个要避免地常见错误。这些计数方法仅提供包含匹配模式的行数——如果那就是您要查找的结果,这没什么问题。但是在行中具有某个特定模式的多个实例的情况下,这些方法无法为您提供实际匹配实例数量 的真实计数。归根结底,若要对实例计数,您还是要使用 wc 来计数。首先,使用 -o 选项(如果您的版本支持它的话)来运行 grep 命令。此选项 输出匹配的模式,每行一个模式,而不输出行本身。但是您不能将它与 -c 选项结合使用,因此要使用 wc -l 来对行计数,如以下示例所示:


清单 18. 好习惯 8 的示例:使用 grep 对模式实例计数
                
~ $ grep -o and tmp/a/longfile.txt | wc -l
3402
~ $

在此例中,调用 wc 要比第二次调用 grep 并插入一个虚拟模式(例如 grep -c)来对行进行匹配和计数稍快一点。





回页首


匹配输出中的某些字段,而不只是对行进行匹配

当您只希望匹配输出行中特定字段 中的模式时,诸如 awk 等工具要优于 grep

下面经过简化的示例演示了如何仅列出 12 月修改过的文件。


清单 19. 坏习惯 9 的示例:使用 grep 来查找特定字段中的模式
                
~/tmp $ ls -l /tmp/a/b/c | grep Dec
-rw-r--r--  7 joe joe  12043 Jan 27 20:36 December_Report.pdf
-rw-r--r--  1 root root  238 Dec 03 08:19 README
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
~/tmp $

在此示例中,grep 对行进行筛选,并输出其修改日期和名称中带 Dec 的所有文件。因此,诸如 December_Report.pdf 等文件是匹配的,即使它自从一月份以来还未修改过。这可能不是您希望的结果。为了匹配特定字段中的模式,最好使用 awk,其中的一个关系运算符对确切的字段进行匹配,如以下示例所示:


清单 20. 好习惯 9 的示例:使用 awk 来查找特定字段中的模式
                
~/tmp $ ls -l | awk '$6 == "Dec"'
-rw-r--r--  3 joe joe   5096 Dec 14 14:26 archive.tar
-rw-r--r--  1 root root  238 Dec 03 08:19 README
~/tmp $

有关如何使用 awk 的更多详细信息,请参见参考资料





回页首


停止对 cat 使用管道

grep 的一个常见的基本用法错误是通过管道将 cat 的输出发送到 grep 以搜索单个文件的内容。这绝对是不必要的,纯粹是浪费时间,因为诸如 grep 这样的工具接受文件名作为参数。您根本不需要在这种情况下使用 cat,如以下示例所示:


清单 21. 好习惯和坏习惯 10 的示例:使用带和不带 cat 的 grep
                
~ $ time cat tmp/a/longfile.txt | grep and
2811

real    0m0.015s
user    0m0.003s
sys     0m0.013s
~ $ time grep and tmp/a/longfile.txt
2811

real    0m0.010s
user    0m0.006s
sys     0m0.004s
~ $ 

此错误存在于许多工具中。由于大多数工具都接受使用连字符 (-) 的标准输入作为一个参数,因此即使使用 cat 来分散 stdin 中的多个文件,参数也通常是无效的。仅当您使用带多个筛选选项之一的 cat 时,才真正有必要在管道前首先执行连接。





回页首


结束语:养成好习惯

最好检查一下您的命令行习惯中的任何不良的使用模式。不良的使用模式会降低您的速度,并且通常会导致意外错误。本文介绍了 10 个新习惯,它们可以帮助您摆脱许多最常见的使用错误。养成这些好习惯是加强您的 UNIX 命令行技能的积极步骤。



参考资料

学习
Top 10 Concepts That Every Software Engineer Should Know - ReadWriteWeb
www.readwriteweb.com/archives/top_10_concepts_that...

Top 10 Concepts That Every Software Engineer Should Know

Written by Alex Iskold / July 22, 2008 8:21 PM / 55 Comments

The future of software development is about good craftsmen. With infrastructure like Amazon Web Services and an abundance of basic libraries, it no longer takes a village to build a good piece of software.

These days, a couple of engineers who know what they are doing can deliver complete systems. In this post, we discuss the top 10 concepts software engineers should know to achieve that.

A successful software engineer knows and uses design patterns, actively refactors code, writes unit tests and religiously seeks simplicity. Beyond the basic methods, there are concepts that good software engineers know about. These transcend programming languages and projects - they are not design patterns, but rather broad areas that you need to be familiar with. The top 10 concepts are:

  1. Interfaces
  2. Conventions and Templates
  3. Layering
  4. Algorithmic Complexity
  5. Hashing
  6. Caching
  7. Concurrency
  8. Cloud Computing
  9. Security
  10. Relational Databases

10. Relational Databases

Relational Databases have recently been getting a bad name because they cannot scale well to support massive web services. Yet this was one of the most fundamental achievements in computing that has carried us for two decades and will remain for a long time. Relational databases are excellent for order management systems, corporate databases and P&L data.

At the core of the relational database is the concept of representing information in records. Each record is added to a table, which defines the type of information. The database offers a way to search the records using a query language, nowadays SQL. The database offers a way to correlate information from multiple tables.

The technique of data normalization is about correct ways of partitioning the data among tables to minimize data redundancy and maximize the speed of retrieval.

9. Security

With the rise of hacking and data sensitivity, the security is paramount. Security is a broad topic that includes authentication, authorization, and information transmission.

Authentication is about verifying user identity. A typical website prompts for a password. The authentication typically happens over SSL (secure socket layer), a way to transmit encrypted information over HTTP. Authorization is about permissions and is important in corporate systems, particularly those that define workflows. The recently developed OAuth protocol helps web services to enable users to open access to their private information. This is how Flickr permits access to individual photos or data sets.

Another security area is network protection. This concerns operating systems, configuration and monitoring to thwart hackers. Not only network is vulnerable, any piece of software is. Firefox browser, marketed as the most secure, has to patch the code continuously. To write secure code for your system requires understanding specifics and potential problems.

8. Cloud Computing

In our recent post Reaching For The Sky Through Compute Clouds we talked about how commodity cloud computing is changing the way we deliver large-scale web applications. Massively parallel, cheap cloud computing reduces both costs and time to market.

Cloud computing grew out of parallel computing, a concept that many problems can be solved faster by running the computations in parallel.

After parallel algorithms came grid computing, which ran parallel computations on idle desktops. One of the first examples was SETI@home project out of Berkley, which used spare CPU cycles to crunch data coming from space. Grid computing is widely adopted by financial companies, which run massive risk calculations. The concept of under-utilized resources, together with the rise of J2EE platform, gave rise to the precursor of cloud computing: application server virtualization. The idea was to run applications on demand and change what is available depending on the time of day and user activity.

Today's most vivid example of cloud computing is Amazon Web Services, a package available via API. Amazon's offering includes a cloud service (EC2), a database for storing and serving large media files (S3), an indexing service (SimpleDB), and the Queue service (SQS). These first blocks already empower an unprecedented way of doing large-scale computing, and surely the best is yet to come.

7. Concurrency

Concurrency is one topic engineers notoriously get wrong, and understandibly so, because the brain does juggle many things at a time and in schools linear thinking is emphasized. Yet concurrency is important in any modern system.

Concurrency is about parallelism, but inside the application. Most modern languages have an in-built concept of concurrency; in Java, it's implemented using Threads.

A classic concurrency example is the producer/consumer, where the producer generates data or tasks, and places it for worker threads to consume and execute. The complexity in concurrency programming stems from the fact Threads often needs to operate on the common data. Each Thread has its own sequence of execution, but accesses common data. One of the most sophisticated concurrency libraries has been developed by Doug Lea and is now part of core Java.

6. Caching

No modern web system runs without a cache, which is an in-memory store that holds a subset of information typically stored in the database. The need for cache comes from the fact that generating results based on the database is costly. For example, if you have a website that lists books that were popular last week, you'd want to compute this information once and place it into cache. User requests fetch data from the cache instead of hitting the database and regenerating the same information.

Caching comes with a cost. Only some subsets of information can be stored in memory. The most common data pruning strategy is to evict items that are least recently used (LRU). The prunning needs to be efficient, not to slow down the application.

A lot of modern web applications, including Facebook, rely on a distributed caching system called Memcached, developed by Brad Firzpatrick when working on LiveJournal. The idea was to create a caching system that utilises spare memory capacity on the network. Today, there are Memcached libraries for many popular languages, including Java and PHP.

5. Hashing

The idea behind hashing is fast access to data. If the data is stored sequentially, the time to find the item is proportional to the size of the list. For each element, a hash function calculates a number, which is used as an index into the table. Given a good hash function that uniformly spreads data along the table, the look-up time is constant. Perfecting hashing is difficult and to deal with that hashtable implementations support collision resolution.

Beyond the basic storage of data, hashes are also important in distributed systems. The so-called uniform hash is used to evenly allocate data among computers in a cloud database. A flavor of this technique is part of Google's indexing service; each URL is hashed to particular computer. Memcached similarly uses a hash function.

Hash functions can be complex and sophisticated, but modern libraries have good defaults. The important thing is how hashes work and how to tune them for maximum performance benefit.

4. Algorithmic Complexity

There are just a handful of things engineers must know about algorithmic complexity. First is big O notation. If something takes O(n) it's linear in the size of data. O(n^2) is quadratic. Using this notation, you should know that search through a list is O(n) and binary search (through a sorted list) is log(n). And sorting of n items would take n*log(n) time.

Your code should (almost) never have multiple nested loops (a loop inside a loop inside a loop). Most of the code written today should use Hashtables, simple lists and singly nested loops.

Due to abundance of excellent libraries, we are not as focused on efficiency these days. That's fine, as tuning can happen later on, after you get the design right.

Elegant algorithms and performance is something you shouldn't ignore. Writing compact and readable code helps ensure your algorithms are clean and simple.

3. Layering

Layering is probably the simplest way to discuss software architecture. It first got serious attention when John Lakos published his book about Large-scale C++ systems. Lakos argued that software consists of layers. The book introduced the concept of layering. The method is this. For each software component, count the number of other components it relies on. That is the metric of how complex the component is.

Lakos contended a good software follows the shape of a pyramid; i.e., there's a progressive increase in the cummulative complexity of each component, but not in the immediate complexity. Put differently, a good software system consists of small, reusable building blocks, each carrying its own responsibility. In a good system, no cyclic dependencies between components are present and the whole system is a stack of layers of functionality, forming a pyramid.

Lakos's work was a precursor to many developments in software engineering, most notably Refactoring. The idea behind refactoring is continuously sculpting the software to ensure it'is structurally sound and flexible. Another major contribution was by Dr Robert Martin from Object Mentor, who wrote about dependecies and acyclic architectures

Among tools that help engineers deal with system architecture are Structure 101 developed by Headway software, and SA4J developed by my former company, Information Laboratory, and now available from IBM.

2. Conventions and Templates

Naming conventions and basic templates are the most overlooked software patterns, yet probably the most powerful.

Naming conventions enable software automation. For example, Java Beans framework is based on a simple naming convention for getters and setters. And canonical URLs in del.icio.us: http://del.icio.us/tag/software take the user to the page that has all items tagged software.

Many social software utilise naming conventions in a similar way. For example, if your user name is johnsmith then likely your avatar is johnsmith.jpg and your rss feed is johnsmith.xml.

Naming conventions are also used in testing, for example JUnit automatically recognizes all the methods in the class that start with prefix test.

The templates are not C++ or Java language constructs. We're talking about template files that contain variables and then allow binding of objects, resolution, and rendering the result for the client.

Cold Fusion was one of the first to popularize templates for web applications. Java followed with JSPs, and recently Apache developed handy general purpose templating for Java called Velocity. PHP can be used as its own templating engine because it supports eval function (be careful with security). For XML programming it is standard to use XSL language to do templates.

From generation of HTML pages to sending standardized support emails, templates are an essential helper in any modern software system.

1. Interfaces

The most important concept in software is interface. Any good software is a model of a real (or imaginary) system. Understanding how to model the problem in terms of correct and simple interfaces is crucial. Lots of systems suffer from the extremes: clumped, lengthy code with little abstractions, or an overly designed system with unnecessary complexity and unused code.

Among the many books, Agile Programming by Dr Robert Martin stands out because of focus on modeling correct interfaces.

In modeling, there are ways you can iterate towards the right solution. Firstly, never add methods that might be useful in the future. Be minimalist, get away with as little as possible. Secondly, don't be afraid to recognize today that what you did yesterday wasn't right. Be willing to change things. Thirdly, be patient and enjoy the process. Ultimately you will arrive at a system that feels right. Until then, keep iterating and don't settle.

Conclusion

Modern software engineering is sophisticated and powerful, with decades of experience, millions of lines of supporting code and unprecidented access to cloud computing. Today, just a couple of smart people can create software that previously required the efforts of dozens of people. But a good craftsman still needs to know what tools to use, when and why.

In this post we discussed concepts that are indispensible for software engineers. And now tell us please what you would add to this list. Share with us what concepts you find indispensible in your daily software engineering journeys.

Image credit: cbtplanet.com

51ibm笔记本社区 thinkpad T61-6481-A21-笔记本电脑 - 淘宝网
auction1.taobao.com/auction/item_detail-0db1-f5d47...

T61-6481-A21

¥7200
未税
Core2 DuoT8100(2.1GHz)
512+512M RAM
120GB 5400rpm
nVIDIA Quadro NVS 140M128M显存
14.1 WXGA 1280X800

COMBO V.92 56K Modem
Intel PRO/1000 Gigabit/Intel 802.11AGN/指纹/蓝牙/6cLi-Ionbattin

随机带礼包:(含原装包,OEM鼠标,内胆包,清洁套装,转接头,网线),不要礼包可以减100元

详细配置:

  主要性能
处理器品牌INTEL
处理器类型Intel 迅驰 酷睿2 T8100
处理器主频(GHz)2.1GHz
二级缓存(MB)3MB
前端总线:800MHZ
迅驰技术 支持
内存类型DDR II 667
标准内存容量(MB)1024
最大支持内存(MB)4096 MB
  存储性能
硬盘容量(GB)120G
硬盘转速5400转 SATA
光驱类型COMBO
光驱速度
内置软驱
  显示屏
显示屏类型TFT WXGA
显示屏尺寸(英寸)14.1英寸
标准分辨率(dpi)1280*800
 是否宽屏                  是
  视频音频
显卡芯片NVIDIA Quadro NVS 140M
显存容量128MB
  
音频系统AC97兼容声卡
内置音箱
  网络设备
网卡,无线网络内置1000M自适应网卡,WLAN性能 802.11AGN(54Mbps)
MODEM56K
  输入输出
鼠标设备触摸板,IBM红点杆
I/O接口USB 2.0 x 3, ,耳机接口,电话线(RJ-11)接口,扩展槽接口,RJ-45接口,1394接口
PCMCIA槽数1个,Type II
读卡器
其它接口VGA接口,DC OUT,指纹识别 蓝牙 6芯电池 
  特征参数
外观特征THINKPAD经典小黑盒子
机壳材料上壳为:高弹性聚乙烯复合材料
底壳为:碳纤维复合材料更轻的重量,更高的强度
 机器重量                                  2.3KG

Jamesz's Blog: 給 Windows 使用者:你不該轉換到 Linux 的理由
blog.istudio.idv.tw/archives/2007/12/_windows_linu...

給 Windows 使用者:你不該轉換到 Linux 的理由

相信有人看到這個標題,一定會覺得我是不是吃錯藥了。為什麼一個使用 Linux 處理日常事務已經七八年的傢伙,會想寫這樣的東西阻止更多人跳進來用 Linux?

在我開始構思「我要怎麼讓人知道 Linux 的好?」這個問題時,我一直在思考著幾個重點:使用者的習慣、操作哲學、應用程式等等。因此以一個只「敢」用 Windows,卻可以順利地從 Windows 95, 98 一路升級使用到 Windows XP 的一般使用者角度來寫這篇,相信能有一定的公正度。只是我有一個先天不利點,很有可能讓這篇看起來沒那麼中肯實用:我是個使用 Linux 很久的使用者,而且我個人是反 M$ 商業行為的,雖然我在公司上班時都還是用 Windows。(順帶一提:這篇是我將我安裝 Ubuntu 7.10 的 Asus NB 帶到公司裡打的)

以一個使用 Windows XP 的使用者角度,我建議不要使用 Linux 的原因如下:

  • 硬體支援不足

這點真的是無與倫比的大不利。在 Windows 下可以正常使用的 BisonCam(ASUS Notebook 有不少款都附加這個 Webcam),在 Linux 下仍然沒有可用的驅動程式!這樣一來,既使最新的 Linux 版 Skype 已經支援視訊,仍然無法使用視訊交談。另外,一些 USB 電視棒也沒支援。我如果正好買到 Linux 目前不支援的電視棒,那錢不就白花了?

也許有人會問:這些廠商怎麼不出支援 Linux 的驅動程式呢?這我也不知道,只有廠商自己知道。當然,我們都已經看到許多有遠見的廠商正式將自己的硬體產品加入 Linux 的支援行列,而那些打死不支援的廠商,是他們短視近利、是他們沒有開發非 Windows 平台 driver 的能力、還是他們背後有 M$ 的金援而受限,只有廠商自己知道。

  • 常用的應用程式不足

這也是另外一個痛,尤其是好不容易「抓」到了 M$ Office 2007、Adobe Photoshop CS3 等等高級軟體時,卻不能在 Linux 下直接安裝使用(哦,我知道有 Wine,但使用者總是懶惰的,不能放入光碟片自動裝好的就不會裝。)

好啦,不酸了,我以正常的角度,先來說 Office 的問題:一般公家機關行號使用的 Office 系統,清一色都是 M$ Office 系列,釋出的公開檔案、在部內部外流通的檔案也都是 M$ DOC 格式。這已經是公家機關上班族的「習慣」,因此既使部份人士強調 M$ DOC 格式並非開放格式,應當將對外開放的文件以開放格式釋出時,他們不是不願意,而是不「懂」:什麼是開放格式?大家都在用 M$ Office,不用 M$ DOC 格式的人才是應該要自我反省的人,因為這些人並未配合政府機關,購入 M$ Office,統一使用 M$ DOC 格式。

而以一個美工人員身份來說...不提 Mac 上的軟體,單就 Windows 上的 Adobe Photoshop 來說就好了,這是絕大多數美工人員在學校上課時使用、熟悉的軟體,因此不論以什麼方式取得 Adobe Photoshop,滿足他們理由只有一個:「我只要 Adobe Photoshop,其他軟體我不要,因為我不會用,而且沒有軟體比 Adobe Photoshop 來得好用、來得強大。」有些人可能聽過 GIMP 或 GimpShop(Gimp 仿 Adobe Photoshop 外觀的變種),但因為「那不是 Adobe Photoshop」,所以他們不用。

  • 我想玩的遊戲在 Linux 上沒有

排除使用應用軟體處理日常事務的部份,因為絕大部份的遊戲都以 DirectX 當底層進行開發,在 Windows 上自然有許多重量級的遊戲可玩。但 Linux 呢?在台灣,絕大多數遊戲都只支援 DIrectX,廠商也「只」支援 Windows 上的各項服務,自然不可能去照顧其他平台的使用者(只有一個例外:魔獸世界的 Mac 支援),更遑論 Linux 了。就算要自己來,有什麼遊戲是可以讓我直接放入光碟片就直接安裝在 Linux 上面,也不用調整什麼就能直接跑的?幾乎沒有。

  • 沒有開始功能表

我沒開玩笑,這真的是一個大問題。許多人使用電腦的經驗,大多建立在螢幕左下方的「開始」那個鈕。M$ 將這個鈕命名為「開始」真是一個人性化的設計:所有要使用的功能都可以透過這個「開始」鈕,逐步找到自己需要的功能。也因此,Linux 上大部份流行的桌面系統上面沒有「開始」這個鈕是一項重大的失敗,因為使用者根本不知道自己如何「開始」使用自己需要的軟體。

也許會有 Linux 使用者會說「可是 Gnome 有大腳丫,KDE 有大齒輪,功能也跟『開始』鈕一樣呀!」那是完全不一樣的使用者經驗:大腳丫與大齒輪代表的意義,與「開始」這兩個字毫不相關,使用者根本不知道那就是在 Gnome 桌面與 KDE 桌面上的「開始」,怎麼可能知道「原來我按下大腳丫或是大齒輪就有跟『開始』一樣的功能了。」也許有人看到這裡已經笑出來了,但這是很實際的人機介面設計概念,而且 M$ 的確在這裡成功建立起使用者的習慣。

  • 新介面我看不習慣,用不習慣:
    • OpenOffice.org 的介面跟操作方式跟 M$ Office 不一樣,我用不習慣,太麻煩了。
    • 我在 Adobe Photoshop 上面使用的熱鍵、常用的插件、色盤、圖層使用方式都跟 GIMP 不一樣,既使 GIMP 就可以做到 Adobe Photohop 的大部份功能,但我實在無法習慣 GIMP,太麻煩了。
    • Linux 上面沒有暴風影音、沒有酒精(燒錄軟體)、沒有 Windows 上我常用的軟體,我實在無法習慣。

上述林林總總的抱怨,都是一個正常的 Windows 使用者會遇到的習慣問題。我們都知道「積習難改」,若一個新的作業系統沒辦法滿足我們在常用軟體上的操作習慣,既使這個軟體再怎麼安全、好用、易學,使用者仍然不可能去試著改變習慣。

  • 為什麼我要去學一個『高手』才會去用的作業系統?Windows 很簡單呀,有什麼必要轉換平台嗎?

回想一下第一次使用 Windows 的時候,滑鼠在圖示上面要點兩下才能去使用這個檔案;滑鼠移到畫面左下方的「開始」點一下滑鼠左鍵,就可以顯示功能表,然後使用滑鼠操作鼠標在功能表中移動,移到功能表上有三角形指向右邊的,這就是子項目...找到你要的功能之後,在那項功能上面點一下滑鼠左鍵,就可以開始使用這個功能了...

當使用者第一次操作系統時,大多是在摸索階段。而在摸索階段時,不論是什麼平台,都會有相當類似的操作與學習經驗。(這裡我提的「類似」是指 Linux 桌面環境,而非 Linux 的文字介面。我不可能拿文字介面跟 Windows 比較啦。)M$ 很成功地讓 Windows 使用者快速征服了摸索階段,讓使用者發現他要做的可以用很簡單的方式達成,建立起使用者的成功經驗,讓使用者在透過使用 Windows 的過程更加為自己的成就感到興奮與安心。

現在的 Linux 辦得到嗎?辦得到,但 Windows 的使用經驗跟 Linux 的畢竟不同。在使用習慣上面永遠都是「先佔先贏」,Windows 的勝利是必然的,既使 Linux 後來居上也是一樣。

  • 沒有防毒軟體的作業系統,怎麼用都不安心

在這個電腦隨時可能被人入侵、植入木馬竊取資料的網路時代,沒有防廣告、防木馬與防毒軟體,的確是令人不安。因此使用 Windows 的使用者莫不花費許多時間在防堵這類情事發生,比方說為了找到卡巴斯基的「永久有效」金鑰花費不少時間在網路上搜尋,好不容易找到後安裝起來才發現這組金鑰已經被官方封鎖失效了,於是又花時間開始一樣的過程...

Linux 上面不需要這些東西,因為 Linux 不會被植入「Windows 平台上的」廣告軟體、木馬與病毒,也因此不需要像卡巴斯基一樣強大的軟體來保護電腦。但也因為沒有這些軟體,反而造成一些已經習慣 Windows 平台的使用者的隱憂:真的不會中毒嗎?真的不會被植入木馬?我安裝 Linux 之後,不會跟以前一樣,還沒開完電腦就看到一大堆 IE 視窗,上面滿滿的賭博、色情跟借貸網站訊息,而且怎麼關也關不完?這是 Linux 的原罪:因為不需要這樣的軟體,反而造成「不信任」,因為一般使用者已經相當習慣且依賴防毒、防廣告、防木馬程式的存在了。因此,為了讓自己心安,不要考慮用 Linux。

當然堅持不轉換平台的理由還有很多,像是「我就已經花錢買了,何必轉換平台?」「別人都幫我裝好了,我何必找自己麻煩轉換平台?」「講那麼多做什麼啦,反正 Linux 就是有一堆 Windows 辦不到的,我才不要轉換平台咧!」我自己沒使用過 Windows Vista,所以我不說轉換到 Windows Vista 上面的問題,相信「願意學習 Windows Vista 平台的 Windows 使用者」,既使知道 Windows Vista 跟 Windows XP 有相當多的不同,比方說系統管理哲學啦、操作介面的改變啦、越來越高的系統需求啦等等,但就是願意由 Windows XP 轉換到 Windows Vista,原因是:「當 Windows Vista 更好用的時候,我就會跳到 Windows Vista,因為 Windows 是主流。我們一定要跟上主流!」讓我們為 Windows 使用者鼓掌吧!你們的堅持是對的,根本沒有必要轉換平台呀,要換也是從 Windows XP 換到 Windows Vista,因為「都是 M$ Windows 嘛,我信任 M$。」

說一句中肯的話作為本篇的結尾:無論如何,電腦是拿來解決問題的,若目前的作業系統環境已經解決自己的問題,的確不需要考慮轉換平台。

PS. 我反覆看過這篇,也承認我自己還是帶著「酸 Windows 使用者」的態度在寫,不過我仍然希望閱讀本篇的 Windows 使用者能提供更多「支持 Windows」的正面意見,也期望我們能在這些意見中得到更多的想法與啟發。

为什么每个人都应该尝试Ubuntu_网易科技
tech.163.com/07/0803/09/3KVAPLEI000929RV.html

为什么每个人都应该尝试Ubuntu

2007-08-03 09:46:05 来源: 译言 网友评论 0 进入论坛
  •   选择 Ubuntu 有以下两类理由:快速上手以及长久的生存能力。Ubuntu 提供不错的开发者联合平台,OEM 顾客不断增长以及——最重要的——全球庞大的用户基础。

原作者: Robert Strohmeyer 译者: sctronlin... (Blog) 原文链接

如果您是位狂热的 Gentoo 或者 Slackware 粉丝,请离开,不要继续读下去。您可能不会像我说的那样。(但是向您保证,我尊敬并欣赏您的目标,致力于运行您自己可以完成的简单的 GNU/Linux 安装。我会注意保护您选择的自由。)而现在,我开始说我的。

如果这两年,您才开始使用 Linux,就很可能使用 Ubuntu。如果您第一次考虑尝试 Linux时遇到困难,,您无疑应该考虑 Ubuntu。这儿是为什么。

选择 Ubuntu 有以下两类理由:快速上手以及长久的生存能力。快速上手,是指使用 Ubuntu 无需指导。花几分钟安装,立刻识别大部分硬件,隐藏 root(根)用户,避免有人弄乱它。接着预设配置,让您马上开始工作。Ubuntu 提供不错的开发者联合平台,OEM 顾客不断增长以及——最重要的——全球庞大的用户基础。

第一,上手部分。

实际上,几乎没有人喜欢安装操作系统。如果您碰到过最多数量的电脑,这可能意味着您在电脑里,那您或许是个例外。但是对于大部分人来说,操作系统安装是个无聊的,有时甚至烦躁的过程,这是绝大多数最终用户都希望避免的。不像大多数其他的发行版*,你可以从 Dell(戴尔)等电脑品牌商得到预装的 Ubuntu,意味着您可以跳过所有安装的障碍,马上在运行的电脑上开始工作。(最近传闻指出 HP 惠普马上也要加入安装 Ubuntu 客户行列。)

如果您选择自己安装 Ubuntu,您可能希望最流行的安装流程之一可以用于任何操作系统。当 Ubuntu 安装过程让您选择自定义硬盘分区时,您也可以马上点击下一步,只需要停下来输入时区、用户名和密码,直到安装完成。您体验到的与 Windows Vista 和 Mac OS X 几乎完全相同。

硬件兼容方面,Ubuntu 牢不可破。这些年来,我安装 Ubuntu 从基于 Power PC 的 Mac 到高端的游戏桌面电脑和一些笔记本。我也找到了一个它不能很容易支持的系统。我个人测试硬件兼容性平台是低端的 Gateway MX3228 笔记本,我经常使用其作为测试系统。(我刚才顺便在上面打字。)它集成 Via UniChrome GPU(图形处理器)、WXGA 显示器、Broadcom 4318 无线网卡、Via 集成声卡以及 Texas Instruments(德州仪器)多媒体读卡器。几乎每次我安装系统,都会碰到点小问题,包括 Windows Vista。花十多分钟从 Gateway 网站下载并安装正确 Vista 驱动,许多 Linux 发行版本也不能够直接显示。即使最新的 Sabayon 版本,其对于硬件支持方面自吹自擂,但对于我这种冷门笔记本也束手无策。但当我为此重装了 Ubuntu,极其少见地花了30多分钟配置所有硬件部分,终于现在机器完美运行。大部分要感谢所有 Ubuntu 论坛上乐于助人的朋友,他们慷慨地分享自己的经验。对于每一个疑难杂症简单地跟随一步一步指令做即可。

因为 Ubuntu 隐藏了 root(根)用户,运行管理员命令需使用 sudo。Ubuntu 保护了新用户自己。这很像 Windows Vista 的用户管理,只有较少的麻烦和更高的安全性。许多其他发行版本仍旧允许用户以 root 登录,对于喜欢乱弄的新手来说可能会带来一场灾难。

安装操作系统只是小部分的电脑经验。事实上,大多数电脑用户从来没有过那样的经历。一旦您第一次启动 Ubuntu,准备狂欢,做些真正的事情。Ubuntu 已经建立了一个高规格的平台带有预先配置好的软件,其中为您提供一个专业规格的办公软件包、强大的图形编辑软件、多功能的相片管理软件、智能的音乐播放器和其它普通人可能需要的软件——一起都准备好,可以马上运行。现在所有主要发行版本都做得同样出色,但我相信 Ubuntu 会掌握好安装所有软件包和避免不必要软件包之间的平衡。如果您遇到想要的软件没有安装,选择 Applications(应用软件) > Add/Remove...(添加/删除...),然后点击它。(或者如果更高级的用户,您可以在 Synaptic Package Manager(新立得软件包管理器)找到继续全部主要开源 Linux 应用软件。)买一台新 Mac 或者 Windows 电脑。在实际开始做事前,您还需要花费数小时安装所有经常用的软件。购买一台预装 Ubuntu 的电脑,您5分钟内就可以开始工作。

但是老实说,我认为 Ubuntu 拥有长期的生存能力重要于其短期的实用主义。最近几年来,对于改进 Linux 桌面方面,Ubuntu 做得比其他发行版本要多。这就是我已详细讨论的,其带来的实际好处,但它也有许多不明确的地方。感谢用户和主流科技媒体流露出值得纪念的表扬, Ubuntu 现在甚至比 Red Hat 在最终用户中更为流行。所有这些流言对于 Ubuntu 产生巨大的动力,让它成为家用桌面历史上支持最棒的 Linux 发行版。在完全一致的呼声中,最终用户使得 Ubuntu 成为 Dell 预装 Linux 系统的第一选择。鉴于流行广泛的影响,Ubuntu 开始克服所有 Linux 发行版面临的最大障碍之一:不为人所知。

历史上,支持 Linux 对于硬件开发者来说,是个麻烦的问题。令人怯步的任务是需要一系列的打包系统,这会让提供者感到惊愕。很难决定支持哪个发行版本,如果有的话。往往,提供者简单地放弃而不是解决这个问题。Ubuntu 倍受瞩目的状态给了开发者一个作为他们在 Linux 世界冒险的明显起始点,显著降低这个关键入门障碍。因为 Ubuntu 立足于家用桌面用户而不只是管理员与超级奇客。在高端图形硬件上更多可能有飞速发展,潜在地引领 Linux 游戏体验上需要的更多改进。

这里恰当的说,对于 Linux 来看,Ubuntu 总体上在桌面上是成功。它必须打造一个有别于其他落伍的、专业的操作系统的声誉。作为常识,它必然会得到大量批评。主要 GNU/Linux 世界出现分裂和潜在用户、开发者、提供者,类似大量批评是难以避免的。从我的角度看,Ubuntu 最有希望统一 Linux 社区,去邀请——而不是威胁——主要的软硬件提供者,满足非技术的最终用户。如果在未来一两年内 Ubuntu 控制住所面临的混乱增长,它有可能上升为世界桌面操作系统领域主要的第三种选择。目前没有一个其他的 Linux 发行版本能做到。

现在,那些有经验的 Linux 用户不理会我这种大胆的说法,或许会回避所有 Ubuntu 话题。但有一件事:Ubuntu 的成功也帮助了您的发行版。Ubuntu 易用且流行,对于用户及提供者,它都可以作为入门的发行版。人们一旦数量使用 Ubuntu,他们可能会转而尝试 Fedora。提供者一开始支持 Ubuntu,支持 PCLinuxOS 也很容易了。希望任何提供者提供对于所有发行版本支持是不明智的,循序渐进的支持有助于整个 Linux 的发展。虽然不可想像 Linux 会成为主流,但没有任何东西可以阻止300多个发行版本的出现(而且每天还在诞生更多版本),以及千百万程序员为此奋斗。

如果你刚刚进入 Linux 社区,你可能是激动的。现在所有的东西对你来说似乎都是新的、陌生的,但是如果你有兴趣,使用大量论坛和其它社区资源。你一会儿就成为了高手。一旦你掌握了现象的本质和使用过发行版的不同功能,你会发现自己的电脑有无限可能。

坦白说,任意两个 Linux 发行版本之间的差异是很小的。而且不知从何开始不会阻止人们进来。这就是我从这里开始,我推荐新手使用 Ubuntu。如果你感兴趣于进入更具技术挑战的领域,那请尝试 Gentoo 或者 Slackware,甚至某些开源的 BSD 版本。重要的是满足自己的需求,尝试新事物,让电脑自由。

太容易了。那就来吧。

Ubuntu Linux比Vista省电_逆流的鱼
hi.baidu.com/reversefish/blog/item/e2b1f782d9097e9...

Ubuntu 8.04为我们节省多少电能?

       当今,计算机操作系统也谈是否“节能”。大家都知道,笔记本电脑耗电的多少,是一个比较头疼的问题。近日,世界权威性测试机构Phoronix(被称为“ 书呆子气”,意思是说,办事“刻板”,斤斤计较)对Ubuntu8.04和VistaUltimate耗电性能进行了严格“比较”。结果怎样 呢?        4月25日,MichaelLarabel在“Ubuntu8.04 vs. Windows Vista Power Usage”一文指出:在LenovoThinkPad T60笔记本电脑(1GB内存、80GB硬盘、Intel双核处理器)上,在“待机”(加电,不工作)状态下,Ubuntu8.04耗电38瓦,而 Vista耗电43瓦,两者相差5瓦!前者比后者“节电”10%以上。这是什么原因呢?一是Intel的CPU节电性能(PowerTOP)的提高;二是 Linux内核的“tick-less”(“无滴答”)性能改进。非常明显的是,这是一项节电的“硬指标”,无论你怎么说(不管从哪方面来看)。
       4月24日,“TheVARGuy”(组织名称)发表文章,题为“FiveReasons Ubuntu Server Revolution BeginsToday”,指出:“从此以后的十年中,历史学家将会说,4月24日这一天将是Ubuntu服务器到达“尖点 ”(“TippingPoint”)的一天”。文章的主题思想非常明确:Ubuntu8.04(LTS)服务器版本的发布,因其性能和使用许可方式(绝对 的自由软件)的优异性,必将对整个Linux生态系统产生非常深远的影响。文章指出,当今,Ubuntu所缺少的是分销商、集成商和增值服务商,人们(一 特别是指那些笃信红帽和Novell“商业模式”的人群)还不完全理解Ubuntu给他们带来的商业机遇。如同“软件矿泉水”的Ubuntu,“本体”绝 对免费,难道还有商机吗?4月14日,Canonical推出的“Ubuntu桌面课程”(网络教学),每一个人的“学费”为100美元。假定在“结业” 之后,还能发给一份“Ubuntu(电子)证书”,我看,这是一个不错的“选择”嘛!
      (注:今后,我想写点“Ubuntu经营业务经”,给那些勇敢创业者出一些“馊主意”。)
NVIDIA显卡解决Ubuntu Linux分辨率问题-xxlinux.com
www.xxlinux.com/linux/article/accidence/internet/2...
NVIDIA显卡解决Ubuntu Linux分辨率问题
[ 作者:  加入时间:2008-02-22 09:56:02  来自:Linux联盟收集整理 ]
 

终于解决了显示分辨率的问题

问题:分辨率一直比较低,在系统--首选项--屏幕分辨率里边一直没有高一点的分辨率选项,虽然装了nvidia的驱动但是不知道如何使用,也找不到入口。

解决:用nvidia-settings命令调出nvidia的设置程序,并将分辨率设置成为1440x900(设置选项里有这个选项)。之后在系统--首选项--屏幕分辨率里面看到了当前的分辨率也是1440x900了。

问题:重新进X后分辨率又变成了登录时默认的1280x1024了。并且系统--首选项--屏幕分辨率里也没有1440x900的选项,就是上一步的设置没有保存下来。

解决:用sudo gedit /etc/X11/xorg.conf打开配置文件, 在"1280x1024"之前加上了"1440x900"(我实际上是将"1440x1440"改为了"1440x900"),所有的subsection都改了,整体内容如下:

Section "Screen"
Identifier "Default Screen"
Device "nVidia Corporation GeForce 7300 SE"
Monitor "LAW982"
DefaultDepth 24
Option "AddARGBVisuals" "True"
Option "AddARGBGLXVisuals" "True"
Option "NoLogo" "True"
SubSection "Display"
Depth 1
Modes "1440x900" "1280x1024" "1280x960" "1152x864"
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
SubSection "Display"
Depth 4
Modes "1440x900" "1280x1024" "1280x960" "1152x864"
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
SubSection "Display"
Depth 8
Modes "1440x900" "1280x1024" "1280x960" "1152x864" 
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
SubSection "Display"
Depth 15
Modes "1440x900" "1280x1024" "1280x960" "1152x864"
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
SubSection "Display"
Depth 16
Modes "1440x900" "1280x1024" "1280x960" "1152x864"
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
SubSection "Display"
Depth 24
Modes "1440x900" "1280x1024" "1280x960" "1152x864"
"1024x768" "832x624" "800x600" "720x400" "640x480"
EndSubSection
EndSection

之后保存退出,重新登录X,问题解决(X的登录框界面也是"1440x900"的了 ^_^)。

思考:X在选择分辨率时应该是在Modes中选择第一个显示器能支持的分辨率应用,原来的"1440x1440"我的显示器不支持,所以就自动选择了当时的第二项"1280x1024"了。

Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
 Ubuntu 基本技巧


http://linux.blogbus.com/logs/13826439.html

#安装
查看软件xxx安装内容

dpkg -L xxx

#查找软件

apt-cache search 正则表达式

#查找文件属于哪个包

dpkg -S filename
apt-file search filename

#查询软件xxx依赖哪些包

apt-cache depends xxx

# 查询软件xxx被哪些包依赖

apt-cache rdepends xxx

# 增加一个光盘源

sudo apt-cdrom add

# 系统升级

sudo apt-get update
sudo apt-get dist-upgrade

# 清除所有已删除包的残馀配置文件

dpkg -l |grep ^rc|awk '{print $2}' |tr ["\n"] [" "]|sudo xargs dpkg -P  -

# 编译时缺少h文件的自动处理

sudo auto-apt run ./configure

# 查看安装软件时下载包的临时存放目录

ls /var/cache/apt/archives

# 备份当前系统安装的所有包的列表

dpkg --get-selections | grep -v deinstall > ~/somefile

# 从上面备份的安装包的列表文件恢复所有包

dpkg --set-selections < ~/somefile
sudo dselect

# 清理旧版本的软件缓存

sudo apt-get autoclean

# 清理所有软件缓存

sudo apt-get clean

# 删除系统不再使用的孤立软件

sudo apt-get autoremove

# 查看包在服务器上面的地址

apt-get -qq --print-uris install ssh | cut -d\' -f2

# 系统
# 查看内核

uname -a

# 查看Ubuntu版本

cat /etc/issue

或者

lsb_release -a

# 查看内核加载的模块

lsmod

# 查看PCI设备

lspci

# 查看USB设备

lsusb

# 查看网卡状态

sudo ethtool eth0

# 查看CPU信息

cat /proc/cpuinfo

# 显示当前硬件信息

 sudo lshw

# 硬盘
# 查看硬盘的分区

sudo fdisk -l

# 查看IDE硬盘信息

sudo hdparm -i /dev/hda

# 查看STAT硬盘信息

sudo hdparm -I /dev/sda

sudo apt-get install blktool
sudo blktool /dev/sda id

# 查看硬盘剩馀空间

df -h
df -H

# 查看目录占用空间

du -hs 目录名

# 优盘没法卸载

sync
fuser -km /media/usbdisk

# 内存
# 查看当前的内存使用情况

free -m

# 进程
# 查看当前有哪些进程

ps -A

# 中止一个进程

kill 进程号(就是ps -A中的第一列的数字)
或者  killall 进程名

# 强制中止一个进程(在上面进程中止不成功的时候使用)

kill -9 进程号
或者  killall -9 进程名

# 图形方式中止一个程序

xkill 出现骷髅标志的鼠标,点击需要中止的程序即可

# 查看当前进程的实时状况

top

# 查看进程打开的文件

lsof -p

# ADSL
# 配置 ADSL

sudo pppoeconf

# ADSL手工拨号

sudo pon dsl-provider

# 激活 ADSL

sudo /etc/ppp/pppoe_on_boot

# 断开 ADSL

sudo poff

# 查看拨号日志

sudo plog

# 如何设置动态域名

 #首先去 http://www.3322.org 申请一个动态域名
#然後修改 /etc/ppp/ip-up 增加拨号时更新域名指令
sudo vim /etc/ppp/ip-up
#在最後增加如下行
w3m -no-cookie -dump 'http://username:password@members.3322.org/dyndns/update?system=dyndns&hostname=yourdns.3322.org'

# 网络
# 根据IP查网卡地址

arping IP地址

# 根据IP查电脑名

nmblookup -A IP地址

# 查看当前IP地址

ifconfig eth0 |awk '/inet/ {split($2,x,":");print x[2]}'

# 查看当前外网的IP地址

w3m -no-cookie -dump www.ip138.com|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
w3m -no-cookie -dump www.123cha.com|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
w3m -no-cookie -dump ip.loveroot.com|grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'

# 查看当前监听80端口的程序

lsof -i :80

# 查看当前网卡的物理地址

arp -a | awk '{print $4}'
ifconfig eth0 | head -1 | awk '{print $5}'

# 立即让网络支持nat

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -I POSTROUTING -j MASQUERADE

# 查看路由信息

netstat -rn
sudo route -n

# 手工增加删除一条路由

sudo route add -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1
sudo route del -net 192.168.0.0 netmask 255.255.255.0 gw 172.16.0.1

# 修改网卡MAC地址的方法

sudo ifconfig eth0 down #关闭网卡
sudo ifconfig eth0 hw ether 00:AA:BB:CC:DD:EE #然後改地址
sudo ifconfig eth0 up #然後启动网卡

# 统计当前IP连接的个数

netstat -na|grep ESTABLISHED|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n
netstat -na|grep SYN|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n

# 统计当前20000个IP包中大于100个IP包的IP地址

tcpdump -tnn -c 20000 -i eth0 | awk -F "." '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr | awk ' $1 > 100 '

# 屏蔽IPV6

echo "blacklist ipv6" | sudo tee /etc/modprobe.d/blacklist-ipv6

# 服务
# 添加一个服务

sudo update-rc.d 服务名 defaults 99

# 删除一个服务

sudo update-rc.d 服务名 remove

# 临时重启一个服务

/etc/init.d/服务名 restart

# 临时关闭一个服务

/etc/init.d/服务名 stop

# 临时启动一个服务

/etc/init.d/服务名 start

# 设置
# 配置默认Java使用哪个

sudo update-alternatives --config java

# 修改用户资料

sudo chfn userid

# 给apt设置代理

export http_proxy=http://xx.xx.xx.xx:xxx

# 修改系统登录信息

sudo vim /etc/motd

# 使用eclipse等其他自带java编译器的软件,换回sun的编译器方法

sudo update-java-alternatives -s java-1.5.0-sun (jdk1.5)
sudo update-java-alternatives -s java-6-sun (jdk6)

# 中文
# 转换文件名由GBK为UTF8

sudo apt-get install convmv
convmv -r -f cp936 -t utf8 --notest --nosmart *

# 批量转换src目录下的所有文件内容由GBK到UTF8

find src -type d -exec mkdir -p utf8/{} \;
find src -type f -exec iconv -f GBK -t UTF-8 {} -o utf8/{} \;
mv utf8/* src
rm -fr utf8

# 转换文件内容由GBK到UTF8

iconv -f gbk -t utf8 $i > newfile

# 转换 mp3 标签编码

sudo apt-get install python-mutagen
find . -iname “*.mp3” -execdir mid3iconv -e GBK {} \;

# 控制台下显示中文

sudo apt-get install zhcon
使用时,输入zhcon即可

# 文件
# 快速查找某个文件

whereis filename
find 目录 -name 文件名

# 查看文件类型

file filename

# 显示xxx文件倒数6行的内容

tail -n 6 xxx

# 让tail不停地读地最新的内容

tail -n 10 -f /var/log/apache2/access.log

或者

tailf /var/log/apache2/access.log

# 查看文件中间的第五行(含)到第10行(含)的内容

sed -n '5,10p' /var/log/apache2/access.log

# 查找包含xxx字符串的文件

grep -l -r xxx .

# 查找关于xxx的命令

apropos xxx
man -k xxx

# 通过ssh传输文件

scp -rp /path/filename username@remoteIP:/path  #将本地文件拷贝到服务器上
scp -rp username@remoteIP:/path/filename /path  #将远程文件从服务器下载到本地

tar cvzf - /path/ | ssh username@remoteip "cd /some/path/; cat -> path.tar.gz" #压缩传输
tar cvzf - /path/ | ssh username@remoteip "cd /some/path/; tar xvzf -" #压缩传输一个目录并解压

# 查看某个文件被哪些应用程序读写

lsof 文件名

# 把所有文件的後辍由rm改为rmvb

rename 's/.rm$/.rmvb/' *

# 把所有文件名中的大写改为小写

rename 'tr/A-Z/a-z/' *

# 删除特殊文件名的文件,如文件名:--help.txt

rm -- --help.txt 或者 rm ./--help.txt

# 查看当前目录的子目录

ls -d */. 或 echo */.

# 将当前目录下最近30天访问过的文件移动到上级back目录

find . -type f -atime -30 -exec mv {} ../back \;

# 将当前目录下最近2小时到8小时之内的文件显示出来

find . -mmin +120 -mmin -480 -exec more {} \;

# 删除修改时间在30天之前的所有文件

find . -type f -mtime +30 -mtime -3600 -exec rm {} \;

# 删除创建时间在30天之前的所有文件

find . -type f -ctime +30 -ctime -3600 -exec rm {} \;

# 查找guest用户的以avi或者rm结尾的文件并删除掉

find . -name '*.avi' -o -name '*.rm' -user 'guest' -exec rm {} \;

# 查找的不以java和xml结尾,并7天没有使用的文件删除掉

find . ! -name *.java ! -name ‘*.xml’ -atime +7 -exec rm {} \;

# 统计当前文件个数

ls /usr/bin|wc -w

# 统计当前目录个数

ls -l /usr/bin|grep ^d|wc -l

# 显示当前目录下2006-01-01的文件名

ls -l |grep 2006-01-01 |awk '{print $8}'

# 压缩
# 解压缩 xxx.tar.gz

tar -zxvf xxx.tar.gz

# 解压缩 xxx.tar.bz2

tar -jxvf xxx.tar.bz2

# 压缩aaa bbb目录为xxx.tar.gz

tar -zcvf xxx.tar.gz aaa bbb

# 压缩aaa bbb目录为xxx.tar.bz2

tar -jcvf xxx.tar.bz2 aaa bbb

# Nautilus
# 显示隐藏文件

Ctrl+h

# 显示地址栏

Ctrl+l

# 特殊 URI 地址

* computer:/// - 全部挂载的设备和网络
* network:/// - 浏览可用的网络
* burn:/// - 一个刻录 CDs/DVDs 的数据虚拟目录
* smb:/// - 可用的 windows/samba 网络资源
* x-nautilus-desktop:/// - 桌面项目和图标
* file:/// - 本地文件
* trash:/// - 本地回收站目录
* ftp:// - FTP 文件夹
* ssh:// - SSH 文件夹
* fonts:/// - 字体文件夹,可将字体文件拖到此处以完成安装
* themes:/// - 系统主题文件夹

# 查看已安装字体

在nautilus的地址栏里输入”fonts:///“,就可以查看本机所有的fonts

# 程序
# 详细显示程序的运行信息

strace -f -F -o outfile <cmd>

# 日期和时间
# 显示日历

cal                    # 显示当月日历
cal  2 2007       # 显示2007年2月的日历

# 设置日期

date -s mm/dd/yy

# 设置时间

date -s HH:MM

# 将时间写入CMOS

hwclock --systohc

# 读取CMOS时间

hwclock --hctosys

# 从服务器上同步时间

sudo ntpdate time.nist.gov
sudo ntpdate time.windows.com

# 工作区
# 不同工作区间切换

Ctrl + ALT + ←
Ctrl + ALT + →
或者,将滚轮鼠标放在工作区图标上滚动

# 控制台
# 指定控制台切换

Ctrl + ALT + Fn(n:1~7)

# 控制台下滚屏

SHIFT + pageUp/pageDown

# 控制台抓图

setterm -dump n(n:1~7)

# 数据库
# mysql的数据库存放在地方

/var/lib/mysql

# 从mysql中导出和导入数据

mysqldump 数据库名 > 文件名  #导出数据库
mysqladmin create 数据库名 #建立数据库
mysql 数据库名 < 文件名 #导入数据库

# 忘了mysql的root口令怎么办

sudo /etc/init.d/mysql stop
sudo mysqld_safe --skip-grant-tables &
sudo mysqladmin -u user password 'newpassword
sudo mysqladmin flush-privileges

# 修改mysql的root口令

sudo mysqladmin -u root -p password '你的新密码'

# 控制
# 如何使用命令关闭显示器

xset dpms force off

# 如何使用命令关闭笔记本的触摸板

synclient touchpadoff=1
那么开启触摸板就是:
synclient touchpadoff=0

# 统计
# 统计最常用的10条命令

history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10

# 统计80端口的连接个数并按照从大到小排列

netstat -na|grep :80|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -r -n

# 其它
# 如何禁用/启用某个帐户

sudo usermod -L username #锁定用户
sudo usermod -U username #解锁

# 下载网站文档

wget -r -p -np -k http://www.21cn.com
· -r:在本机建立服务器端目录结构;
· -p: 下载显示HTML文件的所有图片;
· -np:只下载目标站点指定目录及其子目录的内容;
· -k: 转换非相对链接为相对链接。

# 如何多线程下载

sudo apt-get install axel
axel -n 5 http://xxx.xxx.xxx.xxx/xxx.zip
或者
lftp -c "pget -n 5 http://xxx.xxx.xxx.xxx/xxx.zip

# 如何删除Totem电影播放机的播放历史记录

rm ~/.recently-used

# 如何更换gnome程序的快捷键

点击菜单,鼠标停留在某条菜单上,键盘输入任意你所需要的键,可以是组合键,会立即生效;
如果要清除该快捷键,请使用backspace

# vim 如何显示彩色字符

sudo cp /usr/share/vim/vimcurrent/vimrc_example.vim /usr/share/vim/vimrc


全新memcache client发布,提速20倍》的相关内容

相关讨论

memcache_engine + memcachedb = 高性能分布式内存数据库

memcachedb是一个由新浪网的开发人员开放出来的开源项目,给memcached分布式缓存服务器添加了Berkeley DB的持久化存储机制和异步主辅复制机制,让memcached具备了事务恢复能力、持久化能力和分布式复制能力,非常适合于需要超高性能读写速度,但是不需要严格事务约束,能够被持久化保存的应用场景,例如memcachedb被应用在新浪博客上面。 memcachedb给memcac ...
by robbin 2008-01-22 浏览 (2759) 回复 (18) 关键字: memcachedb

使用Filter方式实现用Memcached储存Session

这两天看到了帖子《扩展Tomcat 6.x,使用memcached存放session信息》,挺有意思,以前我也有采用Memcached管理Session的想法,就是一直没有实践,这两天就实践了一下,codeutil提供的采用扩展Tomcat的方式不错,不过我更喜欢用Resin,所以还是实现一个通用的模块吧,大家可以下载附件,里面有整个工程,如果要使用的话,参照web.xml,把Filter加入你自 ...
by laoer 2007-05-24 浏览 (4687) 回复 (10) 关键字: web

关于memcached client的选择

Memcached(http://www.danga.com/memcached/)是被广泛使用的分布式缓存技术,javaeye也使用memcached做对象缓存。 不同的语言有不同的memcached客户端程序,对于java客户端来说,memcached网站给了两个选择: 引用 1. A Java API is maintained by Greg Whalin from Meetup.com. ...
by andyao 2008-01-10 浏览 (1195) 回复 (8) 关键字: java memcached client

ruby on rails应用性能优化之道

这是一篇我们运营JavaEye网站将近半年时间所得到经验的总结。目前在整个rails社区,都极少有运营rails大访问量网站经验的人详细的谈这个话题。至于国内,rails应用都停留在学习和尝试阶段,真正投入商业运营的基本找不到,所以谈这个话题为时太早,颇有对牛弹琴的感觉。所以权当是个人的总结性文章吧,也不会很详细的展开谈论,能对大家有所启发就好。 一、硬件 1、CPU ruby解析器相对于JV ...
by robbin 2007-02-01 浏览 (15097) 回复 (15) 关键字: rails performance

关于实现一个rails smart cache 的思路草稿。

最近研究了一下 rails的cache设计,发现其中一些不尽如人意的地方: * cache expiry 编写繁琐 * 分页缓存的清除,现有cache实现的支持都不是很完善 * 在一次清除大量缓存的时候,脏数据读的问题。 我查阅了一些blog以及相关的文章,从他们的抱怨和设计中得到一些启发,我觉得cache可以做得更好,更智能,更能够减少开发人员的工作量。 下面是我设计思路的一些草稿,如 ...
by firebody 2007-12-10 浏览 (3046) 回复 (12) 关键字:

相关博客

memcache_engine + memcachedb = 高性能分布式内存数据库

memcachedb是一个由新浪网的开发人员开放出来的开源项目,给memcached分布式缓存服务器添加了Berkeley DB的持久化存储机制和异步主辅复制机制,让memcached具备了事务恢复能力、持久化能力和分布式复制能力,非常适合于需要超高性能读写速度,但是不需要严格事务约束,能够被持久化保存的应用场景,例如memcachedb被应用在新浪博客上面。 memcachedb给memcac ...
by robbin 2008-01-22 浏览 (3932) 回复 (18) 关键字: memcachedb

实战web2.0技术篇-MemCache深度分析 - zt

Memcached是“分布式”的内存对象缓存系统,那么就是说,那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源,即使是UNIX本地连接也一样。 在我之前的测试数据中显示,memcached本地读写速度要比直接PHP内存数组慢几十倍,而APC、共 ...
by huangxx 2008-03-29 浏览 (25) 回复 (0) 关键字:

Memcached在大型网站中应用

 memcached是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。起初作者编写它可能是为了提高动态网页应用,为了减轻数据库检索的压力,来做的这个缓存系统。它的缓存是一种分布式的,也就是可以允许不同 ...
by weiwu83 2007-06-12 浏览 (564) 回复 (1) 关键字: Memcache

memcached安装

【memcached安装】memcached 官方网站         http://www.danga.com/memcached/PHP memcached client       http://wikipedia.sourceforge.net/doc ...
by yanwenhan 2008-02-01 浏览 (138) 回复 (0) 关键字:

Memcached简介

  转自:http://hi.baidu.com/bydv/blog/item/2a223d7f47d8860829388a89.html    memcached是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。最初为了加速 LiveJo ...
by VerRan 2007-05-08 浏览 (795) 回复 (0) 关键字:

相关圈子讨论

关于海航股份和翔鹏团队系统单点登陆的实现

起因源于,翔鹏系统和海航股份系统业务相近,因此。翔鹏的用户希望能够在股份团队和翔鹏团队之间实现单点登陆,也就是在股份团队系统中登陆之后就可以在翔鹏系统不用再次登陆。鉴于用户上面的需求,项目组决定参考第三方的方案实现单点登陆。 最后我们选用CAS(Central Authentication Service) ,它是 Yale 大学发起的一个开源项目。据统计,大概每 10 个采用开源构建 Web ...
by wyyhzc 2007-09-25 浏览 (259) 回复 (0)

颓然忙了一天,却坚定了3.0早日上线的想法

今天是四月份的最后一天,我没有去上班,计划在家里好好的修改网站代码。我知道JavaEye网站的访问速度已经很慢了,即使排除爬虫的原因,也比以前慢多了,另外bug也非常多非常多,令人难以忍受。 我个人参与JavaEye网站代码编写基本上是阶段性的。在最早期写了一部分,中间集中精力运营网站则脱离了一段时间。到去年11月份又写了一段时间的代码,今年年初为了优化性能又写了一段时间,春节期间也写了一段时间 ...
by robbin 2007-04-30 浏览 (11187) 回复 (55)

打算建立一个小团队,收集点民意

通过这几天的讨论我感觉有必要组织一个小团队,合作一个项目,通过它来学习D语言。 这个帖子用来收集大家的想法,看看都想做哪些方面的项目,持续讨论一周时间吧。
by qiezi 2007-04-05 浏览 (3206) 回复 (94)

相关新闻

libmemcached发布了,ruby访问memcached提速20倍

1月13号一个全新的C写的memcached客户端libmemcached发布了,libmemcached不同于老的apr_memcache,他是一个全新设计的客户端,能够以更快的速度,更好的内存消耗来和memcached server通讯。 在libmemcached发布以后的,两个封装libmemcached的ruby软件包就先后发布了: 1、Caffeine 将近100%兼容目前纯ru ...
by robbin 2008-01-21 浏览 (1167) 回复 (1) 关键字: libmemcached

memcache_engine + memcachedb = 高性能分布式内存数据库

memcachedb是一个由新浪网的开发人员开放出来的开源项目,给memcached分布式缓存服务器添加了Berkeley DB的持久化存储机制和异步主辅复制机制,让memcached具备了事务恢复能力、持久化能力和分布式复制能力,非常适合于需要超高性能读写速度,但是不需要严格事务约束,能够被持久化保存的应用场景,例如memcachedb被应用在新浪博客上面。 memcachedb给memcac ...
by robbin 2008-01-22 浏览 (2703) 回复 (16) 关键字: memcached

基于memcached的分布式数据库缓存系统dbcached

dbcached是新浪的开发团队最近新发布的一个基于memcached的开源项目: http://code.google.com/p/dbcached/ dbcached和新浪另外一个开源项目memcached比较像,都是支持memcached协议,利用memcached进行内存缓存的产品。dbcached的架构图: 根据作者的博客介绍:   ● 兼容:Memcached 能做的,db ...
by robbin 2008-03-24 浏览 (675) 回复 (2) 关键字: dbcached
Linux下编译按装memcache分布式环境(笔记) - 我的文章 - 流水孟春
blog.chinaunix.net/u/27731/showart_413760.html
启动memcached
# /usr/local/bin/memcached -d -m 2048 -l 172.18.19.250 -p 11211 -u system_u

-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,
-u是运行Memcache的用户,我这里是system_u,
-l是监听的服务器IP地址,如果有多个地址的话,可以用多个 -l YOU_IP
-p是设置Memcache监听的端口,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件

如果要结束Memcache进程,执行:
用# ps -e 查看进程
# kill pid memcached的进程号
运行后有些系统还会提示-bash: kill: pid: arguments must be process or job IDs
,但是用# ps -e查看进程,已经没有memcached的进程了。
libeven、memcached、libmemcache安装
www.yayu.org/look.php?id=105
libeven、memcached、libmemcache安装
来源:芽雨快跑 时间: 2007-12-21 19:31:50  浏览: 269 次 评论: 0 篇   

    前端时间玩了一下memcached,由于工作关系得过一段时间在玩它。哎,工作就是这样,老变!

    libeven

    memcached的使用需要libeven的支持,我们得先装上libeven。
    官方网站:http://www.monkey.org/~provos/libevent/
    下载地址:http://www.monkey.org/~provos/libevent-1.4.0-beta.tar.gz
    libevent安装方式比较简单:
以下是代码片段:
./configure && make
make install
    这样就好

    检查如下:
以下是引用片段:
[root@localhost memcached-1.2.2]# ls -l /usr/local/lib/ | grep even
lrwxrwxrwx   1 root root      21 Nov 26 11:32 libevent-1.4.so.2 -> libevent-1.4.so.2.0.0
-rwxr-xr-x   1 root root  267334 Nov 26 11:32 libevent-1.4.so.2.0.0
-rw-r--r--   1 root root  351694 Nov 26 11:32 libevent.a
lrwxrwxrwx   1 root root      26 Nov 26 11:32 libevent_core-1.4.so.2 -> libevent_core-1.4.so.2.0.0
-rwxr-xr-x   1 root root  101485 Nov 26 11:32 libevent_core-1.4.so.2.0.0
-rw-r--r--   1 root root  139080 Nov 26 11:32 libevent_core.a
-rwxr-xr-x   1 root root     866 Nov 26 11:32 libevent_core.la
lrwxrwxrwx   1 root root      26 Nov 26 11:32 libevent_core.so -> libevent_core-1.4.so.2.0.0
lrwxrwxrwx   1 root root      27 Nov 26 11:32 libevent_extra-1.4.so.2 -> libevent_extra-1.4.so.2.0.0
-rwxr-xr-x   1 root root  214596 Nov 26 11:32 libevent_extra-1.4.so.2.0.0
-rw-r--r--   1 root root  273270 Nov 26 11:32 libevent_extra.a
-rwxr-xr-x   1 root root     873 Nov 26 11:32 libevent_extra.la
lrwxrwxrwx   1 root root      27 Nov 26 11:32 libevent_extra.so -> libevent_extra-1.4.so.2.0.0
-rwxr-xr-x   1 root root     831 Nov 26 11:32 libevent.la
lrwxrwxrwx   1 root root      21 Nov 26 11:32 libevent.so -> libevent-1.4.so.2.0.0

    看见有很多libevent,就可以放心了。

    memcached

    官方网站:http://www.danga.com/memcached/download.bml
    下载地址:http://www.danga.com/memcached/dist/memcached-1.2.2.tar.gz

    memcached安装需要些参数:
以下是代码片段:
./configure --prefix=/usr/local/memcached --with-libevent=/usr/local
make
make install

   我们来运行看看:
   运行:
以下是代码片段:
/usr/local/memcached/bin/memcached -d -m 10 -p 11211 -u root

    结果:
以下是引用片段:
[root@localhost memcached-1.2.2]# /usr/local/memcached/bin/memcached -d -m 10 -p 11211 -u root
/usr/local/memcached/bin/memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

    查找原因,解决方案如下:
以下是代码片段:
LD_DEBUG=libs /usr/local/memcached/bin/memcached -v

    有如下显示:
以下是引用片段:
[root@localhost memcached-1.2.2]# LD_DEBUG=libs /usr/local/memcached/bin/memcached -v
     18999:     find library=libevent-1.4.so.2 [0]; searching
     18999:      search cache=/etc/ld.so.cache
     18999:      search path=/lib/tls/i686/sse2:/lib/tls/i686:/lib/tls/sse2:/lib/tls:/lib/i686/sse2:/lib/i686:/lib/sse2:/lib:/usr/lib/tls/i686/sse2:/usr/lib/tls/i686:/usr/lib/tls/sse2:/usr/lib/tls:/usr/lib/i686/sse2:/usr/lib/i686:/usr/lib/sse2:/usr/lib          (system search path)
     18999:       trying file=/lib/tls/i686/sse2/libevent-1.4.so.2
     18999:       trying file=/lib/tls/i686/libevent-1.4.so.2
     18999:       trying file=/lib/tls/sse2/libevent-1.4.so.2
     18999:       trying file=/lib/tls/libevent-1.4.so.2
     18999:       trying file=/lib/i686/sse2/libevent-1.4.so.2
     18999:       trying file=/lib/i686/libevent-1.4.so.2
     18999:       trying file=/lib/sse2/libevent-1.4.so.2
     18999:       trying file=/lib/libevent-1.4.so.2
     18999:       trying file=/usr/lib/tls/i686/sse2/libevent-1.4.so.2
     18999:       trying file=/usr/lib/tls/i686/libevent-1.4.so.2
     18999:       trying file=/usr/lib/tls/sse2/libevent-1.4.so.2
     18999:       trying file=/usr/lib/tls/libevent-1.4.so.2
     18999:       trying file=/usr/lib/i686/sse2/libevent-1.4.so.2
     18999:       trying file=/usr/lib/i686/libevent-1.4.so.2
     18999:       trying file=/usr/lib/sse2/libevent-1.4.so.2
     18999:       trying file=/usr/lib/libevent-1.4.so.2
     18999:
/usr/local/memcached/bin/memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

    主要是看最后一行提示的错误,那么我们:
以下是代码片段:
ln -s /usr/local/lib/libevent-1.4.so.2 /usr/lib/libevent-1.4.so.2

    OK!再次运行:
以下是代码片段:
/usr/local/memcached/bin/memcached -d -m 10 -p 11211 -u root
    成功!

    貌似用“ldconfig”也可以解决这个问题

     libmemcache   

    libmemcache是memcached C的客户端之一。我准备使用这个玩意。
    官网:http://people.freebsd.org/~seanc/libmemcache/
    下载:http://people.freebsd.org/~seanc/libmemcache/libmemcache-1.4.0.rc2.tar.bz2
    编译:
以下是代码片段:
./configure
make
make install

     写一个有libmemcache函数的程序
     然后    

以下是代码片段:
gcc a.c -o a.cgi -L/usr/local/include -lmemcache


    运行
以下是代码片段:
./a.cgi

    提示类似上面的“error while loading shared libraries”的错误,查了一下可用"ldconfig"解决这个问题,那上面的可否用这个命令解决呢?

    上面的gcc编译的时候,带有参数“-lmemcache”。
    -l参数后面跟的库名有规则的,库的命名方式有libxxxx.so或libxxxx.a,编译时要用-lxxxx就可以了。
    而“-l”的意思就是代表是个“lib”了。

    所以在你自己编写动态库或者静态库时,命名还是得按照 libxxxx.so的形式来。

    不得不认为libmemcache有点糟糕,编译它自带的一个程序编译竟然有问题,很无语!
以下是引用片段:
[root@login benchmark]# gcc benchmark.c -L/usr/local/include -lmemcache
benchmark.c: In function `main':
benchmark.c:100: warning: passing arg 2 of `mc_set' discards qualifiers from pointer target type
benchmark.c:108: warning: passing arg 2 of `mc_set' discards qualifiers from pointer target type
benchmark.c:121: warning: passing arg 2 of `mc_req_add' discards qualifiers from pointer target type
benchmark.c:145: warning: passing arg 2 of `mc_delete' discards qualifiers from pointer target type
benchmark.c:153: warning: passing arg 2 of `mc_add' discards qualifiers from pointer target type
benchmark.c:167: warning: passing arg 2 of `mc_delete' discards qualifiers from pointer target type

    解决方法:

    找到passing arg 2这个参数的定义:
以下是引用片段:
const char *key;

    把const去了:
以下是引用片段:
char *key;

    这样就好了!

    然后:

以下是代码片段:
[root@login memcache-test]# ./a.out

    执行时可能报以下的错误:
以下是引用片段:
./a.out: error while loading shared libraries: libmemcache.so.0: cannot open shared object file: No such file or directory

    解决方法:

    执行ldconfig命令即可!


    附:

    http://kapoc.blogdriver.com/kapoc/1200549.html
    ldconfig命令 - - 动态链接库管理命令

    为了让动态链接库为系统所共享,还需运行动态链接库的管理命令--ldconfig.此执行程序存放在/sbin目录下.

    ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.

    ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.

理解缓存 - 蝈蝈俊.net - 博客堂
blog.joycode.com/ghj/archive/2007/09/01/107863.asp...

最近公司一直在招人,我作为主考官之一 。经常会提问的一个问题,就是让用户介绍自己在缓存方面的经验和心得。绝大多数的面试者只能说ASP.net的页面缓存和局部缓存,稍稍有点经验的,会提到企业库的缓存,只有很少的人会知道Memcached(一个分布式的缓存)。而对于缓存的一些基本思想,却没有一个人能说出来。

  现在的技术人员,很多时候,不管三七二十一,把一个个实体丢到缓存中,然后在用的时候,就从缓存中去找这个实体。而不会考虑缓存的其他方面因素。所以他们在提到缓存时,想到的才只能是一个个的缓存实现的方法,而不是缓存的思想。

  那么,肯定就有人问,蝈蝈俊,那你理解的缓存思想是如何的呢?下面我就一一来说出我理解的缓存。

 

Q:什么样的缓存才是好缓存?

  能解决问题的缓存就是好缓存。这句话简直就是废话,相当于白猫、黑猫,抓住老鼠的就是好猫。

  那在解决问题前提下,哪个缓存才是好缓存呢? 这个问题我的答案是:缓存命中率高的缓存是好缓存。

  在解决问题前提下,命中率高的缓存比命中率低的缓存,在硬件投入上可能会比较小,同时缓存的数量比命中率低的缓存数量也可能少,这样寻址的速度肯定比较快。所以命中率高的缓存是好缓存。

 

缓存的命中率

  一个缓存的实体在被丢到缓存中后,在这个实体被缓存的期间(这个实体被缓存的生命周期内),如果外部一次都没有使用过它,这个缓存实体的命中率就是0。这个实体被请求的次数越多,它的缓存命中率越高。

  上面说的是缓存中一个实体的命中率。对于缓存整体来说,它的命中率则是上面各个被缓存的个体的命中率分布图。

  对于缓存来说:通常最常使用的个体之占总体的很小一部分。最不常使用的占整体的很大一部分。如下图所示:

  所以我们经常会看到类似这样的数据:

  缓存的1万个元素中,有100个被频繁的使用,几乎每分钟都会被使用一次。2000个数据,每小时被请求一次。3000个数据,每天被请求一次,剩下的数据,被丢到缓存中后一次都没有被使用过。

  现在硬件发展很快,如果我们只是需要缓存1万个数据的话,我们完全可以做到不管这1万个数据是否被使用到,全部丢到缓存,这样只要找数据,肯定缓存中有这个数据。而不需要作额外的运算,或者不需要向数据库发出请求。

  但是:硬件发展快,数据量发展也快。小型的网站,缓存1万条数据,也就全部缓存了。但是大型网站最少也是上百万的数据量或者上T级别的数据,这些数据量显然不能都丢到缓存。这时候设计一个合理的缓存方案,提高缓存的命中率,就非常重要。而且是必须的。

 

提高缓存命中率的一些常见方法

  纯技术的角度来说,我们只有记录了用户的单位时间的请求数,并依照这个信息来把最常被使用的数据缓存起来。

  但更多的时候,我们是根据业务逻辑来提高缓存命中率的。比如:去年,前年发表的博客,这类文章的浏览请求,一般一天至少可怜的几次。一般不应该缓存到内存中。

  又比如,回复数多的帖子,一般被请求数会比回复数少的帖子会被更多人次看到。 

  我们应该通过上面逻辑,根据我们实际业务逻辑,提供一个缓存算法,提高缓存的命中率。让在我们硬件允许的条件下,缓存适当的数据,而不是所有数据。

 

  一个反面的例子就是:不管三七二十一,一个大型的博客站点,一篇文章被用户请求的时候,发现不在内存缓存中,就从数据库中读出,然后丢到缓存。

  要知道,现在爬虫程序很多的。另外,博客这类搜索引擎友好的站点,决大多数的访问压力是搜索引擎搜索过来的。而这些访问一般都是1小时,或者1天之内,对某篇文章只有几次甚至1次请求,之后再也没有了。上面作缓存的方法,命中率会非常低的。

  这里也许就有人会问,郭红俊,既然你不建议我缓存这些博客的内容,但是我如何提高我站点的性能呀,我至少得保证我博客站点不会速度慢的无法响应用户请求呀。

  这个问题的解决方案有很多,一个最简单的方法就是把这些博客做成静态Html页面,也就是文件系统的缓存,文件系统因为硬盘的原因,可以简单理解成可以无限扩容,这样就可以把很多命中率低的内容进行缓存。

  如果你的页面需要一些动态逻辑判断,你可以把数据缓存成XML文件,然后服务器段整合这些XML文件,或者是包含文件。这也是种不错的方法。

 

说了这么多缓存命中率的问题,简单汇总一下缓存命中率的观点

  1. 小型网站可以全部数据缓存,一般压力也不会很大,可以忽略缓存命中率问题。
  2. 大型服务无法全部数据缓存,只能部分数据缓存,这时候就需要架构师设计出对该业务逻辑适用的缓存方法,尽可能的提高缓存的命中率。
  3. 提高命中率的方法大多是跟业务逻辑捆绑的,需要跟具体问题具体分析
  4. 对于不能被内存缓存的数据,最简单的提高性能方法就是使用文件缓存。
  5. 文件缓存可以整个内容缓存成一个静态文件;也可以是整个页面的一个区域被缓存成一个文件,然后被包含;也可以是把一个实体序列化成XML文件进行缓存。

 

下面我们看看缓存的其他几个不那么重要的方面:

 

缓存的生命周期内的活动

  永久不过期,永久不变更的内容,这类东西就不应该放在缓存。缓存是临时的存储,而不是永久的,所以缓存的生命周期是有限的。

  它依次可能会经历如下活动:

  1. 进入缓存。(进入缓存的时候,可能需要指定它以后的过期策略,如果不指定,需要使用系统默认的过期策略)
  2. 从缓存中获得它,注意,这时候需要处理线程安全的问题。
  3. 更新缓存,注意,也需要考虑线程安全问题
  4. 离开缓存,这个可能是外部请求,也可能是缓存根据过期策略把它清理掉。

 

缓存的过期策略

  一般我会问,你所接触的缓存中,碰到过那些缓存过期策略?

  最常见的几种过期策略如下:

  多长时间没有被请求,则过期,最典型的就是ASP和ASP.net 提供的 Section 功能。其实它就是一个缓存。

  依赖于文件变更的缓存,一旦文件被修改,缓存则过期,典型的是 WEB站点的 Web.config ,一旦这个文件变更,不但缓存重起,IIS进程也会进行一次释放工作。

  在此基础上,可能看到很多依赖关系的缓存过期策略。比如依赖于数据库的缓存过期策略。

  当然,业务逻辑里可能会有更复杂的过期策略,必须CSDN新版积分制论坛中,帖子列表缓存会在列表数据缓存达到600时,把它清理到550条数据。

  又比如新积分制论坛帖子的缓存过期,则是没有任何列表引用这个帖子后,则这个帖子过期。

 

缓存的同步问题

  使用缓存,则意味着同样的数据,可能有多份并存。如果你的代码没有考虑某种情况,导致了这两份数据不一致了。这时候就会有问题发生。

  解决方法很简单,把你的业务逻辑,代码触发情况都考虑清楚,不要遗留没有触底的地方。

  简单的方法会导致你的代码逻辑变得非常复杂。

  这也就是有些人,在非必要的时候,建议你不要用缓存的原因。一旦开始使用缓存,你就应该准备增加大量的代码来处理数据同步的问题。

 

初始化填充缓存数据

  有时候在缓存被初始化后,还需要预先填充一些数据到缓存中。这就是缓存数据的初始化操作。

  缓存数据的初始化操作需要考虑以下问题:

  1. 需要多长时间进行初始化,一般如果是站点的话,我们可能在 Global.asa 的 Application_OnStart 中处理这个初始化工作。初始化的一般不能太久,这时候就是考验我们代码优化的能力了。
  2. 初始化的时候,一般是批量导入数据,而不是我们正常使用的时候,一次处理一个数据。

 

 总结:

  本文介绍了我对缓存的一些观点,而没有深入涉及到具体的缓存技术。希望通过本文的讲述,让只会缓存用法不懂缓存思想的人有初步的了解。

www.danga.com/
www.danga.com/

What is Danga?

Danga Interactive was Brad Fitzpatrick's company that developed LiveJournal and by necessity the backend software to drive it all. Since Danga's acqusition by Six Apart, the meaning of "Danga" is somewhat undefined. It mostly represents this website and this software. A lot of the contributors to this software, both old and new, work for SixApart, but just as many are from the larger community.... people like you.

Software

All Open Source, because we love Freedom.

memcached [svn] Distributed caching. Hit your database less. Speed up your website.
MogileFS [svn] Distributed (meta) file system. Spray files across cheap disks on your network. Pay less for storage. No proprietary on-disk file formats.
Perlbal [svn] Sexy reverse proxy load balancer and webserver, full of tricks.
DJabberd [svn] High-performance, low-overhead, everything-is-a-plugin extensible Jabber/XMPP server.
Gearman [svn] Low-latency remote function execution. Run code remotely, in parallel, load balanced, in other languages, etc.

The Source

To get the source for any project:

$ svn co http://code.sixapart.com/svn/<whatever>/trunk/ <directory>
Memcached在大型网站中应用
www.lifv.cn/?p=187

Memcached在大型网站中应用

Category: PHP, Author: jiading

    memcached是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。起初作者编写它可能是为了提高动态网页应用,为了减轻数据库检索的压力,来做的这个缓存系统。它的缓存是一种分布式的,也就是可以允许不同主机上的多个用户同时访问这个缓存系统, 这种方法不仅解决了共享内存只能是单机的弊端, 同时也解决了数据库检索的压力,最大的优点是提高了访问获取数据的速度!基于memcached作者对分布式cache的理解和解决方案。memcached完全可以用到其他地方 比如分布式数据库, 分布式计算等领域。
1、 memcached 协议理解
memcache是为了加快http://www.livejournal.com/访问速度而诞生的一个项目。
它的官方主页是:http://www.danga.com/memcached/
目前在网站开发中应用较少,主要的应用有:
http://www.danga.com/memcached/users.bml
在国内的网站开发中,还很少没见到有应用的,中文资料十分匮乏。
工作机制:通过在内存中开辟一块区域来维持一个大的hash表来加快页面访问速度,和数据库是独立的。但是目前主要用来缓存数据库的数据。允许多个server通过网络形成一个大的hash,用户不必关心数据存放在哪,只调用相关接口就可。存放在内存的数据通过LRU算法进行淘汰出内存。同时可以通过删除和设置失效时间来淘汰存放在内存的数据。
2、 memcached 使用入门
2.1 memcached的安装
  ?<1>memcached服务的安装
  先检查linux内核版本,建议将memcached 安装在2.6以上。
  因为memcached 需要用到libevent和 epoll 。
memcached安装前首先确定你的服务器上面安装了libevent库,
libevent下载地址( http://www.monkey.org/~provos/libevent/)。
下载memcached的源码( http://www.danga.com/memcached/download.bml)。
Memcached最初是用perl写的,现在的版本是用c写的。
下载后拷贝到一个目录,安装需要root用户来执行
tar -zxvf memcached-1.1.12.tar.gz
cd memcached-1.1.12
./configure
这里必须先要configure, 它会检测你的系统情况,然后生成一个config.h文件和其它的几个文件,另外和其它的configure一样,你可以配置它的安装路径等等。默认应用程序安装在/usr/local/bin目录下。
make //编译
make install //安装
<2>memcached客户端的安装
根据memcached协议,用户可以自己写出符合自己要求的客户端程序。目前http://www.danga.com/memcached/download.bml
提供perl,c,java,python,php等客户端程序供下载和参考。下面我就以perl客户端程序为例说明客户端的安装:
下载后拷贝到一个目录,安装需要root用户来执行
tar -zxvf Cache-Memcached-1.14.tar.gz
cd Cache-Memcached-1.14
perl makefile.pl
make
make install
make test
这样就安装好了memcahced, 启动memcached就可使用分布式缓存系统了!
2.2 快速入门
<1> memcached服务的启动
memcached的启动非常简单,它没有配置文件,只要配置好几个参数就可以使用了。下面我以一个实际应用的例子,具体说明一下:
memcached –d –m 500  -l 64.128.191.151 -p 11211 -vv >>/var/www/kelly/test/logs/memcached_$$.log
启动的这个memcached为一个后台守护进程模式(-d), 然后缓存的空间为500M(-m), 监听(-l)服务器64.128.191.15的11211号端口(-p).,将日志写道/var/www/kelly/test/logs/memcached_$$.log(-vv)。
其实memcached的参数也非常的有限,就下面这几个:
?  -p port number to listen on
?  -l interface to listen on, default is INDRR_ANY
?  -d run as a daemon
?  -r maximize core file limit
?  -u assume identity of (only when run as root)
?  -m max memory to use for items in megabytes, default is 64 MB
?  -M return error on memory exhausted (rather than removing items)
?  -c max simultaneous connections, default is 1024
          ?  -k lock down all paged memory
?  -v verbose (print errors/warnings while in event loop)
?  -vv very verbose (also print client commands/reponses)
?  -h print this help and exit
?  -i print memcached and libevent license
我们也可以将这个启动脚本写道/etc/rc.d或者/erc/rc.local,这样可以在服务器启动时候执行。
<2> memcached客户端的连接
下面我就以perl客户端程序为例说明客户端的连接:
启动两个memcached server
memcached –d –m 500  -l 64.128.191.151 -p 11211 -vv >>/var/www/kelly/test/logs/memcached_$$.log
memcached –d –m 500  -l 64.128.191.151 -p 11212 -vv >>/var/www/kelly/test/logs/memcached_$$.log
perl客户端程序
#!/usr/bin/perl
use Cache::Memcached;
my $memd = new Cache::Memcached {
    ’servers’ => [ “64.128.191.15:11211″ , “64.128.191.15:11212″],
  };
my $val = $memd->get( “my_key” );
if ( $val )
{
   print “Value is ‘$val’\n”;
}
# Set a value
$memd->set(”my_key”, “123″);
$memd->disconnect_all();
?运行测试
$ perl test-memcache.pl
$ perl test-memcache.pl
Value is ‘123′
可以看到,第一次没有取得my_key,第二次从memcached中得到my_key的值。
同时通过查看日志,可以发现的确存储在两个memcache  server中。
这个简单的例子,解释了如何在memcached中存取数据,以及memcache是真正的分布式缓存系统。
当然,这还只是很简单的例子,体现不出memcache的优势,下面将通过一个很具体的例子,给出详细的应用。
3、 memcached在Zorpia的应用
http://www.zorpia.com 是一个网页相册,博客,交友,论坛的大型网站公司。现在已有超过140万活跃使用者遍布美国,香港,东南亚,欧洲,澳洲,亚洲等其它地区。每天的访问量都在增长,已成为全世界排名第五的社会生活关系网。
Memcached也采用了memcached来提高网站的访问速度,并且取得了很好的效果,我在负责zorpia的memcached项目时候积累了一些经验,主要的做法如下:
1) 通过对memcache的perl客户端进行包装,定制自己的客户端。
2) 通过制定符合zorpia规范的hash key命名规范
?  ? memcache中需要存储的内容的key均由string组成。
这个string统一由一个memcache.pm的subroutine来实现。(假设这个subroutine是 get_key() )
?  ? memcache中存放两种形式的数据
  (1) result of SQL query :
  (2) 普通变量(variable)
  这两种数据的key的组合方式是不相同的,由get_key进行判断和完成
?  ? 关于get_key 和 naming rule
  get_key subroutine完成所有memcache key的命名,naming rule也是在它里边体现:
  (1)输入参数 -- hash结构,里边定义了当前需要存放的数据的信息
      结构
  (2)返回值 -- string,返回数据的key_name
?必须确定 get_key 的传入hash的结构,
      hash中主要有两个元素
      type — 定义当前数据结构的类型 ,有 ‘var’ , ’sql’两种值
      object — 存放当前数据结构的详细信息,
      当 type eq ‘var’时,object表示变量的名字,该名字由程序员指定
      当 type eq ’sql’时,object包含所存放sql的主要基本信息,hash结构,也由程序员按照规则制定
     ## 当variable 数据类型,比较简单
     $var_hash = {
             type => ‘var’,      ## var表示当前类型是 variable  
             object => ‘language’,  ##  language代表variable的名字
     };
生成的key是Zorpia::var| language
     ## sql 数据
     比如select first_name from user where user_id =2那么hash为
     $sql_hash = {
             type => ’sql’,
             object => {
                 table => {table2=>”user”,},         ## sql 查询的表
                 column => {column1=>”first_name”,},  ## sql所要查询的column
                 condition => { user_id =>”2″,},  ## sql条件
             },
     };
生成的key是Zorpia::sql|user|first_name| user_id =2
     get_key subroutine必须对传入hash进行判断,对不同类型的数据按照不同的方式组合,形成key,返回给使用者。这个key,必须保证其唯一性:
比如:所有字母小写,一些数组在组合成key之前必须首先排序
? ? get_key函数
sub get_key{
my $hash = shift;
return undef unless $hash && ref $hash eq “HASH”;
my $type = $hash->{type};
my $key_name;
if ($type eq ’sql’) {
my ($table_key,$column_key,$condition_key);
$table_key=_get_key($hash->{object}->{table});
$column_key=_get_key($hash->{object}->{column});
$condition_key=_get_key($hash->{object}->{condition});
$key_name = join(’|',$type,$table_key,$column_key,$condition_key);
#Currently the length limit of a key is set at 250 characters
if (length($key_name)>250)
{
$key_name=substr(0,250,$key_name);
}
}
elsif($type eq ‘var’)
{
$key_name = join(’|',$type,$hash->{object});
}
return $key_name;
}
sub _get_key
{
my $hash=shift;
return undef unless $hash && ref $hash eq “HASH”;
my ($t,$ret,$i);
foreach $i (sort keys %$hash)
{
  $i=~s/^\s+|\s+$//g;
  $hash->{$i}=~s/^\s+|\s+$//g;
   push(@$t,lc(”$i=$hash->{$i}”));
}
$ret=join(’:',sort { $a cmp $b } @$t);
return $ret;   
}
3) 制定需要应用memcached的规则
?经常访问的表user,user_details
?合理设定变量在memcached的生存周期
?将活跃用户的信息预先导入到memcached
?分别在多台机器上启动多个memcached服务
?编写脚本监控memcached服务是否活动
4) User表的具体应用举例
? 在 select时候
先查询memcahce里有没有,有的话,返回;否则从数据库select,在memcache里设置,返回。
my $sql_hash = {
         type => ’sql’,
         object => {
       table => {table1=>”user”,},
       column => {column1=>”user_id”,},
       condition => {email=>$user_id,},
        },
         };
        my $key=Zorpia::MemCache::get_key($sql_hash); 
        my $user_id_by_email=Zorpia::MemCache::get($key);
       if(!$user_id_by_email)
        {
        my $sth;
        my $query =”select user_id from user where email=?”;
        $sth = $dbh->prepare($query);
        $sth->execute($user_id);
        my $user1 = $sth->fetchrow_hashref();
        $user_id_by_email=$user1->{’user_id’};
        Zorpia::MemCache::set($key,$user_id_by_email,1800);
        }
 ?在 update,insert,delete时候
先在数据库update,insert,delete,在memcache里设置,返回。
&Zorpia::DB::data_entry_no_return($dbh,”user”,”COUNT(*)”,”$account_information_insert_statement user_id=$current_user_id”, “user_id=$current_user_id”);
 #add by kelly
 my $sql_hash = {
         type => ’sql’,
         object => {
       table => {table1=>”user”,},
       column => {column1=>”user_id”,},
       condition => {user_id=>$current_user_id,},
        },
         };
  my $key=Zorpia::MemCache::get_key($sql_hash);
  my $query = “Select *, user_id AS id  FROM   user  Where user_id=?”;
  my $sth_memc = $dbh->prepare($query);
  $sth_memc->execute($current_user_id);
  my $user_memc = $sth_memc->fetchrow_hashref();
  &Zorpia::MemCache::set($key,$user_memc,21600);
4、 memcached的应用展望
使用了memcached以后, 我发现以前做过的很多的项目都可以应用它提高效率,包括最近做的“大单追踪”, “数码搜索”等等。当然既然memcahced是分布式的缓存系统,那么它就是建立了一个分布式的平台, 我们可以用它来进行分布式的记数, 因为对于一个键值key我们可以设置它的数值以及有效期在参数中,另外还可以重新设置这个键值的数值。 所以我总结了一下目前可以应用到的地方:
<1>.数据库检索结果的缓存,也就是说可以有机的和数据库结合起来应用,提高效率。
    这也是目前memcached用到的最多的地方,比如用于大型网站等。
可以这样来实现:
打开memcached服务器连接
编写sql语句, 同时算出它的一个hash key值
获取这个hash值的memcached保存数据(get)
如果获取的这个hash值的数据存在。返回
否则连接数据库查找
把这个查找结果保存在memcached中(set),可以设置有效期
返回查找结果
 <2>.分布式计算
 <3>.分布式共享数据
 总之,memcached的机制比较灵活,可以适用于一切需要分布式缓存数据的地方,随着memcached逐渐为人所知,必将在更多的分布式应用领域大放异彩。

» 你可能感兴趣的文章
PHP & memcached
一、memcached 简介 在很多场合,我们都会听到 memcached 这个名字,但很多同...
YouTube 的架构扩展
在西雅图扩展性的技术研讨会上,YouTube 的 Cuong Do 做了关于 YouTube Scalability �...
memcached安装+php使用手记
本文简要介绍一下安装的情况,以及PHP模块memcache使用情况: 提要: 1。安...

可中止的线程池

发布日期: 2006-6-15 | 更新日期: 2006-6-15

Stephen Toub

下载本文的代码: NETMatters0603.exe (118KB)

问:在 2005 年 7 月的专栏 (.NET Matters: StringStream, Methods with Timeouts) 中,您演示了如何使用 Thread.Abort 来取消一个长期运行的操作。我知道您对该方法的可靠性提出了警告,但是我认为,就我目前的情况而言,这种风险是可接受的。我对将在线程池中执行的一长串工作项进行了排队。不久后,我需要取消其中一个操作(实际上,是一个手动超时),如果该操作尚未执行,则让它出列;如果该操作当前正在执行,则中止它。这种情况下,ThreadPool 好像并未公开任何功能。是否我只能编写自己的 ThreadPool 代码?

答:这是个不错的问题。回答问题的第一部分,ThreadPool 不公开让项目从其内部队列中出列的功能(尽管还有其他办法,您很快就能看到)。问题的第二部分经常以下面这种普通得不能再普通的形式出现:您如何决定排队工作项将在哪个线程上执行?当然,答案是:除非该线程已经执行,否则您不可能知道。毕竟,一个线程池的全部问题在于允许其中的任意线程完成请求的工作。这意味着,要想发现工作项在哪个线程上执行,最好的方法是让工作项一开始运行就通知您。例如,工作项方法的首要任务是对回调进行排序,并根据当前 Thread 对象的信息进行传递。在您描述的情况中,掌握工作项的 Thread,之后即可轻松地中止它。

但这种方法是很危险的。此时,接收通知并中止线程,最初的工作项可能已经结束了,以至于线程池中的线程已经移动到其他工作项。您将中止次要而不是想要中止的工作项,这会让您处于危险境地。另外,这需要您在每个排队进入线程池的方法中都有适当的回调逻辑。

相反,将向您传递回 cookie 的线程池实现视为排队工作项的分类。然后,线程池还将提供一个 Cancel 方法,用于获取其中一个 cookie 并取消相关的工作项,从队列中移除该工作项,或根据情况中止正在执行的工作项。执行该任务的一个自定义的线程池也许不是最好的主意,但是还有其他办法。(注意,执行自定义线程池是可能的;有关这一示例,请参阅我在 2005 年 2 月专栏中的文章 .NET Matters: File Copy Progress, Custom Thread Pools。)

在我的 2004 年 10 月、11 月和 12 月的专栏中,我解释了如何执行 ThreadPool 的静态包装,其中每一个包装完成不同的任务(等待已排队的工作项完成,优先某些已排队的项目,截断线程池的使用)。使用相同的技术可以创建线程池的包装,以允许取消工作项。图 1 显示所涉及处理的高级图示,图 2 显示其实现。


图 1 高级处理


要使用该类,只需在使用 ThreadPool 排队要取消的工作项的任意位置替换 AbortableThreadPool 即可。在使用 AbortableThreadPool 期间,仍旧对 ThreadPool.QueueUserWorkItem 进行调用虽然很好,但这些工作项不能被取消。一个典型的调用序列如下所示:

WorkItem item = AbortableThreadPool.QueueUserWorkItem(
  new WaitCallback(YourWorkMethod));
... // do other stuff here
WorkItemStatus status = AbortableThreadPool.Cancel(item, false);
Console.WriteLine("Status from Cancel: " + status);

对于以前的包装,这次我要做的是存储提供给 ThreadPool.QueueUserWorkItem 方法的信息,并且我已经创建了 WorkItem 类(依旧如图 2所示)。该类的一个实例存储了三段信息,其中包括两段由用户提供的信息(执行 WaitCallback,并将对象状态作为该方法的一个参数进行传递)。第三段信息是在调用 QueueUserWorkItem 时捕获的 ExecutionContext。

ExecutionContext 是 Microsoft® 的身份;它的同步上下文,它允许进行同步和异步操作以实现与适当的同步模型保持一致,例如在 Windows 窗体应用程序中使用 Control.Invoke 或 Control.BeginInvoke;它的逻辑调用上下文;还包括它的宿主执行上下文。ExecutionContext 的优点是,您可以捕获当前线程的 ExecutionContext,然后当运行任意代码时,使用该 ExecutionContext,尽管该代码不在最初捕获其上下文的线程中运行。

为什么说它是件好事?考虑发生以下情况,在线程池中排入队列中一个工作项,或使用 Control.Invoke 封送处理对 Windows 窗体应用程序的 GUI 线程的调用,或调用 Thread.Start 执行新线程中的一个方法,或异步调用一个委托。本质上是,一个线程请求另一个线程代表自己完成工作。由于两个线程不能共有任意基于线程的状态,如果未向目的线程传递任何有关源线程的内容,会发生断开连接并出现各种各样的问题。其中的一些问题会导致功能上的错误,例如,存储在源代码的线程本地存储中的数据在执行期间不可用,其他一些问题会导致安全性漏洞,例如,在不同的 Windows 身份下执行。

通过允许捕获以及从一个线程到另一个线程的执行上下文流程,.NET Framework 2.0 解决了这一断开连接问题。事实上,在大部分情况下,由于 ExecutionContext 在线程转换点(ThreadPool.QueueUserWorkItem、Thread.Start、委托异步调用等)之间是自动流动的,您将不能直接处理 ExecutionContext。当执行一些操作而引起该自动流程停止时,才能直接进行处理。鉴于此,WorkItem 存储 ExecutionContext 的原因就显而易见了。

图 2 所示的 AbortableThreadPool 类中有一些信息的集合。一个集合是 WorkItem 实例的一个链表,它包括利用尚未有机会执行的 AbortableThreadPool.QueueUserWorkItem 进行排队的工作项。另一个集合是字典,它将 WorkItem 实例映射到 Thread 对象;该集合用于跟踪工作项正在其中执行的线程池线程。

AbortableThreadPool.QueueUserWorkItem 是该类最简单的方法。它创建一个 WorkItem,用于存储提供的 WaitCallback 和用户状态对象,以及当前的 ExecutionContext。然后,该 WorkItem 进入到等待执行的工作项链表队列中。此外,将一个占位符回调插入到实际的 .NET ThreadPool 之中。该占位符不包含要执行的实际工作的信息,且仅指回 AbortableThreadPool.HandleItem 方法。由于当且仅当调用 AbortableThreadPool、QueueUserWorkItem 方法时对 HandleItem 的一个委托进行排队,因此,链表中的每个工作项都在实际的线程池中有一个相应的排队工作项。作为 cookie 的 WorkItem(本专栏以前讨论过)将返回给用户。

调用 HandleItem 时,它从工作项链表中删除下一个 WorkItem。然后,该 WorkItem 与当前的 Thread 实例(从 Thread.CurrentThread 检索)一起插入到运行工作项(WorkItem 作为字典中的键)表中。此时,从 WorkItem 检索 ExecutionContext,并用于执行排队的委托,为其提供相应的用户状态对象。委托完成执行后,WorkItem 到 Thread 的映射将从运行工作项的表中删除。

该系统使得无需考虑线程池中的工作项当前状态即可将其取消。具有从 QueueUserWorkItem 返回的 WorkItem 的用户可将实例传递给 Cancel 方法。Cancel 方法首先查看 WorkItems 链表;如果 WorkItem 未开始执行,它将插入该链表。如果找到项目,它将从队列中删除。这将导致链表中的 WorkItems 数和在托管线程池中排队的工作项数变成离散的,但是没关系。当 HandleItem 试图从队列中检索下一项时,如果没有更多项可用,则返回它。

然而,这种情况是您必需将 ExecutionContext 存储在 WorkItem 中,并在上下文中执行委托的原因之一。默认情况下,执行上下文的流方向为从将委托排入到线程池队列的线程到该委托的执行。但是,以这种方式取消一个工作项(托管线程池完全忽略该工作项)将导致工作项和流动的上下文无法保持同步。结果,一个工作项将在流动的上下文中为另一个工作项而执行。

尽管不能取消这些项,但仍需要存储带有工作项的执行上下文。每次从 ThreadPool 调用 HandleItem 时,将从队列中删除下一个 WorkItem。但实际情况是,线程池执行 HandleItem 方法,以便您无需考虑任何顺序问题即可对它们进行排队,这其中将执行这些 HandleItem 调用中的各种指令。对于在其他调用之前开始一个 HandleItem 调用而言,这相当可行;但对于第二个调用,则先要移除一个等待的 WorkItems。如果这再次发生,则在执行上下文的流中出现断开连接,此时您必需手工操作。

如果 Cancel 方法在链表中没有找到从 QueueUserWorkItem 返回的 WorkItem,那么只有其他两种可能。第一,工作项当前可能正在执行,在这种情况下,它将以键的形式在字典中显示,将 WorkItem 实例映射到 Thread 实例。此外,如果它在您可以轻松地检索 Thread 的表(委托在该表中执行)中,则您可根据需要将其中止。如果 WorkItem 不是该字典中的键,则它必需已经完成执行,因而没有可取消的内容。阻挡工作项执行并隔离对 Abort 调用的锁防止了中止不正确的线程;如果线程池中的 Thread 对象只返回到 AbortableThreadPool 用户,这将不会受到阻拦。

鉴于我在 2005 年 7 月刊中提供了方法超时示例,请您小心使用 Thread.Abort 控制线程的生命周期,特别是在您了解了一些中止代码实现的情况下。尽管单纯的中止会显著降低窗口灾难的可能性,但临界区内的中止会招致整个 AppDomain 的灾难,一次超出 1,000 可导致死锁或资源匮乏,或者更糟。根据工作负荷和中止率,这可能(或不会)随时间变化而迅速增长。有关其危险的原因以及解决方法的更多信息,请参阅我于 2005 年 10 月发表的有关可靠性的文章 (High Availability: Keep Your Code Running with the Reliability Features of the .NET Framework)。

也就是说,对于方法超时示例,恰好可以发挥 Thread.Abort 的强大功能。对于这些情况,AbortableThreadPool 很方便。既然实现了用 Cancel 方法接受指示当前执行的工作项是否应该中止的参数,当然就可以选择该代码来取消挂起的工作项,而不是取消已经开始的工作项。


将您的问题与评论发送到 netqa@microsoft.com

Stephen ToubMSDN Magazine 的一位技术编辑。

Ubuntu 7.04系统上安装Apache PHP MySQL - Ubuntu 7.04 - 技术应用 - 豆豆网
tech.ddvip.com/2007-09/119022106635023.html

1、安装 Apache2+PHP5+MySQL

  sudo apt-get install apache2 libapache2-mod-php5 php5 php5-gd mysql-server php5-mysql phpmyadmin

  joelhy 提醒 这一步可以使用新立得来安装,同样效果。

  打开新立得,编辑 –> 使用任务分组标记软件包 –> 勾选 LAMP Server

  然后再单独安装 phpmyadmin

  sudo apt-get install phpmyadmin

  2、启用 mod_rewrite 模块

  sudo a2enmod rewrite

  3、配置 apache2.conf

  sudo gedit /etc/apache2/apache2.conf

  去掉 AddHandler cgi-script .cgi 前的注释 “#”。

  然后在任意地方添加这么一段:

  &<60;&<60; &<60;DocumentRoot /var/www/

  &<60;&<60; &<60;

  &<60;&<60; &<60; &<60; &<60;Options FollowSymLinks

  &<60;&<60; &<60; &<60; &<60;AllowOverride all

  &<60;&<60; &<60;

  &<60;&<60; &<60;

  &<60;&<60; &<60; &<60; &<60;Options ExecCGI

  &<60;&<60; &<60;

  重启服务器

  sudo /etc/init.d/apache2 restart

  搞定。

  说明:PHP 程序放 /var/www/ 下面都可以,CGI 程序放 /var/www/cgi-bin/ 下面。

  是不是太简单了,除去下载的时间,要不了一分钟就可以完成配置,在 Ubuntu 上还需要 APM 包吗?还是记住以下几个命令和位置就行了。

  sudo /etc/init.d/apache2 restart (重启 apache)

  sudo gedit /etc/php5/apache2/php.ini (配置 php.ini)

  sudo gedit /etc/apache2/apache2.conf (配置 apache2.conf)

  /var/www/(主目录位置)

  以上服务器配置,经测试可以正常运行 WordPress、Habari、Movable Type。

满江红开放技术研究组织发布Seam 2.0中文文档RC版 - redsaga-notify | Google Groups
groups.google.com/group/redsaga-notify/browse_thre...

"你得知道,我想的比做的更多。如果你要做一个开源项目,必须设想好它的道路,它才会成功。"Gavin King这么说过。那时候他已经在新天地luna酒吧灌下大杯的法国葡萄酒,还要装作若无其事。不得不承认这个家伙相当聪明且自负。他做出的决定是深思熟虑的。

B/S程序和C/S不同,Request/Response模型让程序冗长的像裹脚布。你同时要处理多种数据失配:服务器端的RDBMS和浏览器展示出来的HTML之间,需要Servlet的渲染,数据经历了RDBMS Row ,ResultSet, 若有若无的DTO和浏览器Form数据这几个步骤,让数据变得支离破碎。实际上所有的Java框架的核心都是解决不同层面的这些破碎。Hibernate解决的是DTO和ResultSet之间的破碎。和大多数初学者认为的Hibernate是一种面向对象的ResultSet包装器的字面理解不同,Hibernate的目的是对RDBMS数据的便于进行缓存的细粒度切割,"面向对象"只是工具而非目的,缓存才是一切的本质,它让Hibernate真正成为了具有强大战斗力的武器而非可笑的对象封装器。

解决了这一失配后,Gavin King把目光放到了HTML Form和服务器对象之间的失配上。这一次的目的是简化,尽可能的简化,因为对Web编程而言,最大的瓶颈是开发效率,因此Seam的目的就是最大限度的简化复杂性。这一次的战线要比Hibernate宽广的多,Seam的好处因而也更加让人看得明白:它提升JSF的实力,让快速开发效果丰富的Web应用程序成为可能。从双向注入到Annotation,目的都是为了尽量减少服务器端的代码量,而RichFaces和JSF编辑器,则是为了让Seam的产出变得效果丰富。
但显然,HTML Form的表现力和可能的复杂性远远超过ORM中对象的关系的种类,因此,任何针对HTML的组件封装都必须以其高品质才能让用户感到信服。作为整合开发工具Seam的道路还很长,对Grid等复杂组件的支持尚不够,让2.0仍然无法达到Delphi在Windows开发界的广大影响力。换句话说,JSF的未来,在于其是否能成功的制造出组件产业链,一方面真正简化开发者的劳动,提高效率,另一方面让组件开发者能把经精力集中在开发高质量的组件上。在制造产业链这一目标上,JSF是领跑的,而JSF框架中,Seam是领跑的。

因此,你应该花些时间来看看Seam。

2007/12/30,发布对应Seam 2.0GA的中文文档RC版本:

……
Oracle关于时间/日期的操作
来源:TechTarget; 作者:
[字体: ]
  
  在oracle中有很多关于日期的函数,如:

  1、add_months()用于从一个日期值增加或减少一些月份

  date_value:=add_months(date_value,number_of_months)

  例:

  SQL> select add_months(sysdate,12) "Next Year" from dual;

  Next Year

  ----------

  13-11月-04

  SQL> select add_months(sysdate,112) "Last Year" from dual;

  Last Year

  ----------

  13-3月 -13

  SQL>

  2、current_date()返回当前会放时区中的当前日期

  date_value:=current_date

  SQL> column sessiontimezone for a15

  SQL> select sessiontimezone,current_date from dual;

  SESSIONTIMEZONE CURRENT_DA

  --------------- ----------

  +08:00 13-11月-03

  SQL> alter session set time_zone='-11:00'

  2 /

  会话已更改。

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  -11:00 12-11月-03 04.59.13.668000 下午 -11:

  00

  SQL>

  3、current_timestamp()以timestamp with time zone数据类型返回当前会放时区中的当前日期

  timestamp_with_time_zone_value:=current_timestamp([timestamp_precision])

  SQL> column sessiontimezone for a15

  SQL> column current_timestamp format a36

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  +08:00 13-11月-03 11.56.28.160000 上午 +08:

  00

  SQL> alter session set time_zone='-11:00'

  2 /

  会话已更改。

  SQL> select sessiontimezone,current_timestamp from dual;

  SESSIONTIMEZONE CURRENT_TIMESTAMP

  --------------- ------------------------------------

  -11:00 12-11月-03 04.58.00.243000 下午 -11:

  00

  SQL>

  4、dbtimezone()返回时区

  varchar_value:=dbtimezone

  SQL> select dbtimezone from dual;

  DBTIME

  ------

  -07:00

  SQL>

  5、extract()找出日期或间隔值的字段值

  date_value:=extract(date_field from [datetime_value|interval_value])

  SQL> select extract(month from sysdate) "This Month" from dual;

  This Month

  ----------

  11

  SQL> select extract(year from add_months(sysdate,36)) "3 Years Out" from dual;

  3 Years Out

  -----------

  2006

  SQL>

  6、last_day()返回包含了日期参数的月份的最后一天的日期

  date_value:=last_day(date_value)

  SQL> select last_day(date'2000-02-01') "Leap Yr?" from dual;

  Leap Yr?

  ----------

  29-2月 -00

  SQL> select last_day(sysdate) "Last day of this month" from dual;

  Last day o

  ----------

  30-11月-03

  SQL>

  7、localtimestamp()返回会话中的日期和时间

  timestamp_value:=localtimestamp

  SQL> column localtimestamp format a28

  SQL> select localtimestamp from dual;

  LOCALTIMESTAMP

  ----------------------------

  13-11月-03 12.09.15.433000

  下午

  SQL> select localtimestamp,current_timestamp from dual;

  LOCALTIMESTAMP CURRENT_TIMESTAMP

  ---------------------------- ------------------------------------

  13-11月-03 12.09.31.006000 13-11月-03 12.09.31.006000 下午 +08:

  下午 00

  SQL> alter session set time_zone='-11:00';

  会话已更改。

  SQL> select localtimestamp,to_char(sysdate,'DD-MM-YYYY HH:MI:SS AM') "SYSDATE" from dual;

  LOCALTIMESTAMP SYSDATE

  ---------------------------- ------------------------

  12-11月-03 05.11.31.259000 13-11-2003 12:11:31 下午

  下午

  SQL>

  8、months_between()判断两个日期之间的月份数量

  number_value:=months_between(date_value,date_value)

  SQL> select months_between(sysdate,date'1971-05-18') from dual;

  MONTHS_BETWEEN(SYSDATE,DATE'1971-05-18')

  ----------------------------------------

  389.855143

  SQL> select months_between(sysdate,date'2001-01-01') from dual;

  MONTHS_BETWEEN(SYSDATE,DATE'2001-01-01')

  ----------------------------------------

  34.4035409

  SQL>

  9、next_day()给定一个日期值,返回由第二个参数指出的日子第一次出现在的日期值(应返回相应日子的名称字符串)

  说明:

  单行日期函数

  单行日期函数操作data数据类型,绝大多数都有data数据类型的参数,绝大多数返回的也是data数据类型的值。

  add_months(,)

  返回日期d加上i个月后的结果。i可以使任意整数。如果i是一个小数,那么数据库将隐式的他转换成整数,将会截去小数点后面的部分。

  last_day()

  函数返回包含日期d的月份的最后一天

  months_between(,)

  返回d1和d2之间月的数目,如果d1和d2的日的日期都相同,或者都使该月的最后一天,那么将返回一个整数,否则会返回的结果将包含一个分数。

  new_time(,,)

  d1是一个日期数据类型,当时区tz1中的日期和时间是d时,返回时区tz2中的日期和时间。tz1和tz2时字符串。

  next_day(,)

  返回日期d后由dow给出的条件的第一天,dow使用当前会话中给出的语言指定了一周中的某一天,返回的时间分量与d的时间分量相同。

  select next_day(''01-jan-2000'',''monday'') "1st monday",next_day(''01-nov-2004'',''tuesday'')+7 "2nd tuesday") from dual;1st monday 2nd tuesday03-jan-2000 09-nov-2004

  round([,])

  将日期d按照fmt指定的格式舍入,fmt为字符串。

  syadate

  函数没有参数,返回当前日期和时间。

  trunc([,])

  返回由fmt指定的单位的日期d.

  单行转换函数

  单行转换函数用于操作多数据类型,在数据类型之间进行转换。

  chartorwid()

  c 使一个字符串,函数将c转换为rwid数据类型。

  select test_id from test_case where rowid=chartorwid(''aaaa0saacaaaaliaaa'')

  convert(,[,])

  c尾字符串,dset、sset是两个字符集,函数将字符串c由sset字符集转换为dset字符集,sset的缺省设置为数据库的字符集。

  hextoraw()

  x为16进制的字符串,函数将16进制的x转换为raw数据类型。

  rawtohex()

  x是raw数据类型字符串,函数将raw数据类转换为16进制的数据类型。

  rowidtochar()

  函数将rowid数据类型转换为char数据类型。

  to_char([[,)

  x是一个data或number数据类型,函数将x转换成fmt指定格式的char数据类型,如果x为日期nlsparm=nls_date_language 控制返回的月份和日份所使用的语言。如果x为数字nlsparm=nls_numeric_characters 用来指定小数位和千分位的分隔符,以及货币符号。

  nls_numeric_characters ="dg", nls_currency="string"

  to_date([,[,)

  c表示字符串,fmt表示一种特殊格式的字符串。返回按照fmt格式显示的c,nlsparm表示使用的语言。函数将字符串c转换成date数据类型。

  to_multi_byte()

  c表示一个字符串,函数将c的担子截字符转换成多字节字符。

  to_number([,[,)

  c表示字符串,fmt表示一个特殊格式的字符串,函数返回值按照fmt指定的格式显示。nlsparm表示语言,函数将返回c代表的数字。

  to_single_byte()

  将字符串c中得多字节字符转化成等价的单字节字符。该函数仅当数据库字符集同时包含单字节和多字节字符时才使用。

Oracle关于时间/日期的操作

  1.日期时间间隔操作

  当前时间减去7分钟的时间

  select sysdate,sysdate - interval '7' MINUTE from dual

  当前时间减去7小时的时间

  select sysdate - interval '7' hour from dual

  当前时间减去7天的时间

  select sysdate - interval '7' day from dual

  当前时间减去7月的时间

  select sysdate,sysdate - interval '7' month from dual

  当前时间减去7年的时间

  select sysdate,sysdate - interval '7' year from dual

  时间间隔乘以一个数字

  select sysdate,sysdate - 8 *interval '2' hour from dual

  2.日期到字符操作

  select sysdate,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-ddd hh:mi:ss') from dual

  select sysdate,to_char(sysdate,'yyyy-mm iw-d hh:mi:ss') from dual

  参考oracle的相关关文档(ORACLE901DOC/SERVER.901/A90125/SQL_ELEMENTS4.HTM#48515)

  3. 字符到日期操作

  select to_date('2003-10-17 21:15:37','yyyy-mm-dd hh24:mi:ss') from dual

  具体用法和上面的to_char差不多。

  4. trunk/ ROUND函数的使用

  select trunc(sysdate ,'YEAR') from dual

  select trunc(sysdate ) from dual

  select to_char(trunc(sysdate ,'YYYY'),'YYYY') from dual

  5.oracle有毫秒级的数据类型

  --返回当前时间 年月日小时分秒毫秒

  select to_char(current_timestamp(5),'DD-MON-YYYY HH24:MI:SSxFF') from dual;

  --返回当前 时间的秒毫秒,可以指定秒后面的精度(最大=9)

  select to_char(current_timestamp(9),'MI:SSxFF') from dual;

  6.计算程序运行的时间(ms)

  declare

  type rc is ref cursor;

  l_rc rc;

  l_dummy all_objects.object_name%type;

  l_start number default dbms_utility.get_time;

  begin

  for I in 1 .. 1000

  loop

  open l_rc for

  'select object_name from all_objects '||

  'where object_id = ' || i;

  fetch l_rc into l_dummy;

  close l_rc;

  end loop;

  dbms_output.put_line

  ( round( (dbms_utility.get_time-l_start)/100, 2 ) ||

  ' seconds...' );

  end;

Ubuntu中文 论坛 :: 阅读主题 - [分享]wget——Linux下Web文件提取工具 使用说明
forum.ubuntu.org.cn/viewtopic.php?t=41905
wget是一个Linux环境下用于从World Wide Web上提取文件的工具,这是一个GPL许可
证下的自由软件,其作者为Hrvoje Niksic <hniksic@srce.hr>。wget支持HTTP和FTP
协议,支持代理服务器和断点续传功能,能够自动递归远程主机的目录,找到合乎条
件的文件并将其下载到本地硬盘上;如果必要,wget将恰当地转换页面中的超级连接
以在本地生成可浏览的镜像。由于没有交互式界面,wget可在后台运行,截获并忽略
HANGUP信号,因此在用户推出登录以后,仍可继续运行。通常,wget用于成批量地下
载Internet网站上的文件,或制作远程网站的镜像。

语法:

wget [options] [URL-list]
URL地址格式说明:可以使用如下格式的URL:
http://host[:port]/path
例如:
http://fly.cc.fer.hr/
ftp://ftp.xemacs.org/pub/xemacs/xemacs-19.14.tar.gz
ftp://username:password@host/dir/file
在最后一种形式中,以URL编码形式为FTP主机提供了用户名和密码(当然,也可以使
用参数提供该信息,见后)。

参数说明:

wget的参数较多,但大部分应用只需要如下几个常用的参数:
-r 递归;对于HTTP主机,wget首先下载URL指定的文件,然后(如果该文件是
一个HTML文档的话)递归下载该文件所引用(超级连接)的所有文件(递归深度
由参数-l指定)。对FTP主机,该参数意味着要下载URL指定的目录中的所有文件,
递归方法与HTTP主机类似。

-N 时间戳:该参数指定wget只下载更新的文件,也就是说,与本地目录中的对
应文件的长度和最后修改日期一样的文件将不被下载。

-m 镜像:相当于同时使用-r和-N参数。

-l 设置递归级数;默认为5。-l1相当于不递归;-l0为无穷递归;注意,当递
归深度增加时,文件数量将呈指数级增长。

-t 设置重试次数。当连接中断(或超时)时,wget将试图重新连接。如果指
定-t0,则重试次数设为无穷多。

-c 指定断点续传功能。实际上,wget默认具有断点续传功能,只有当你使用别
的ftp工具下载了某一文件的一部分,并希望wget接着完成此工作的时候,才需要
指定此参数。

使用举例:
wget -m -l4 -t0 http://oneweb.com.cn/
将在本地硬盘建立http://oneweb.com.cn/的镜像,镜像文件存入当前目录下一个名为
oneweb.com.cn的子目录中(你也可以使用-nH参数指定不建立该子目录,而直接在当前
目录下建立镜像的目录结构),递归深度为4,重试次数为无穷(若连接出现问题,
wget将坚韧不拔地永远重试下去,知道任务完成!)

另外一些使用频率稍低的参数如下:
-A acclist / -R rejlist:
这两个参数用于指定wget接受或排除的文件扩展名,多个名称之间用逗号隔开。例如,
假设我们不想下载MPEG视频影像文件和.AU声音文件,可使用如下参数:
-R mpg,mpeg,au

其它参数还有:
-L 只扩展相对连接,该参数对于抓取指定站点很有用,可以避免向宿主主机
的其他目录扩散。例如,某个人网站地址为:http://www.xys.org/~ppfl/,使用
如下命令行:
wget -L http://www.xys.org/~ppfl/
则只提取该个人网站,而不涉及主机www.xys.org上的其他目录。

-k 转换连接:HTML文件存盘时,将其中的非相对连接转换成为相对连接。

-X 在下载FTP主机上的文件时,排除若干指定的目录

另外,下面参数用于设置wget的工作界面:
-v 设置wget输出详细的工作信息。
-q 设置wget不输出任何信息。

如果我们已经在一个HTML文档(或普通文本文档)中存储了所要提取的文件的连接,
可以让wget直接从该文件中提取信息,而不用在命令行中提供URL地址,参数格式为:
-i filename
地址文件也可以不是HTML文档,例如,一个普通的文本文件,其中有需要下载的URL列
表即可。
我们可以用以下技巧提高下载速度:由于Linux是一个多任务系统,我们可以同时运行
多个wget进程以提高下载速度,例如,先下载某主页文件(index.html),然后将该
文件所列出的所有地址分别用一个独立的wget进程进行下载。

至于其他的参数,可参考wget的man手册页,命令为:
man wget


WGet使用指南

wget是一个从网络上自动下载文件的自由工具。它支持HTTP,HTTPS和FTP协议,可以使用HTTP代理.

所谓的自动下载是指,wget可以在用户退出系统的之后在后台执行。这意味这你可以登录系统,启动一个wget下载任务,然后退出系统,wget将在后台执行直到任务完成,相对于其它大部分浏览器在下载大量数据时需要用户一直的参与,这省去了极大的麻烦。

wget可以跟踪HTML页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构。这又常被称作”递归下载”。在递归下载的时候,wget遵循Robot Exclusion标准(/robots.txt). wget可以在下载的同时,将链接转换成指向本地文件,以方便离线浏览。

wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性.如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。
wget的常见用法

wget的使用格式

Usage: wget [OPTION]... [URL]...

* 用wget做站点镜像:

wget -r -p -np -k http://dsec.pku.edu.cn/~usr_name/
# 或者
wget -m http://www.tldp.org/LDP/abs/html/

* 在不稳定的网络上下载一个部分下载的文件,以及在空闲时段下载

wget -t 0 -w 31 -c http://dsec.pku.edu.cn/BBC.avi -o down.log &
# 或者从filelist读入要下载的文件列表
wget -t 0 -w 31 -c -B ftp://dsec.pku.edu.cn/linuxsoft -i filelist.txt -o down.log &

上面的代码还可以用来在网络比较空闲的时段进行下载。我的用法是:在mozilla中将不方便当时下载的URL链接拷贝到内存中然后粘贴到文件filelist.txt中,在晚上要出去系统前执行上面代码的第二条。

* 使用代理下载

wget -Y on -p -k https://sourceforge.net/projects/wvware/

代理可以在环境变量或wgetrc文件中设定

# 在环境变量中设定代理
export PROXY=http://211.90.168.94:8080/
# 在~/.wgetrc中设定代理
http_proxy = http://proxy.yoyodyne.com:18023/
ftp_proxy = http://proxy.yoyodyne.com:18023/

wget各种选项分类列表

* 启动

-V, --version 显示wget的版本后退出
-h, --help 打印语法帮助
-b, --background 启动后转入后台执行
-e, --execute=COMMAND 执行`.wgetrc'格式的命令,wgetrc格式参见/etc/wgetrc或~/.wgetrc

* 记录和输入文件

-o, --output-file=FILE 把记录写到FILE文件中
-a, --append-output=FILE 把记录追加到FILE文件中
-d, --debug 打印调试输出
-q, --quiet 安静模式(没有输出)
-v, --verbose 冗长模式(这是缺省设置)
-nv, --non-verbose 关掉冗长模式,但不是安静模式
-i, --input-file=FILE 下载在FILE文件中出现的URLs
-F, --force-html 把输入文件当作HTML格式文件对待
-B, --base=URL 将URL作为在-F -i参数指定的文件中出现的相对链接的前缀
--sslcertfile=FILE 可选客户端证书
--sslcertkey=KEYFILE 可选客户端证书的KEYFILE
--egd-file=FILE 指定EGD socket的文件名

* 下载

--bind-address=ADDRESS 指定本地使用地址(主机名或IP,当本地有多个IP或名字时使用)
-t, --tries=NUMBER 设定最大尝试链接次数(0 表示无限制).
-O --output-document=FILE 把文档写到FILE文件中
-nc, --no-clobber 不要覆盖存在的文件或使用.#前缀
-c, --continue 接着下载没下载完的文件
--progress=TYPE 设定进程条标记
-N, --timestamping 不要重新下载文件除非比本地文件新
-S, --server-response 打印服务器的回应
--spider 不下载任何东西
-T, --timeout=SECONDS 设定响应超时的秒数
-w, --wait=SECONDS 两次尝试之间间隔SECONDS秒
--waitretry=SECONDS 在重新链接之间等待1...SECONDS秒
--random-wait 在下载之间等待0...2*WAIT秒
-Y, --proxy=on/off 打开或关闭代理
-Q, --quota=NUMBER 设置下载的容量限制
--limit-rate=RATE 限定下载输率

* 目录

-nd --no-directories 不创建目录
-x, --force-directories 强制创建目录
-nH, --no-host-directories 不创建主机目录
-P, --directory-prefix=PREFIX 将文件保存到目录 PREFIX/...
--cut-dirs=NUMBER 忽略 NUMBER层远程目录

* HTTP 选项

--http-user=USER 设定HTTP用户名为 USER.
--http-passwd=PASS 设定http密码为 PASS.
-C, --cache=on/off 允许/不允许服务器端的数据缓存 (一般情况下允许).
-E, --html-extension 将所有text/html文档以.html扩展名保存
--ignore-length 忽略 `Content-Length'头域
--header=STRING 在headers中插入字符串 STRING
--proxy-user=USER 设定代理的用户名为 USER
--proxy-passwd=PASS 设定代理的密码为 PASS
--referer=URL 在HTTP请求中包含 `Referer: URL'头
-s, --save-headers 保存HTTP头到文件
-U, --user-agent=AGENT 设定代理的名称为 AGENT而不是 Wget/VERSION.
--no-http-keep-alive 关闭 HTTP活动链接 (永远链接).
--cookies=off 不使用 cookies.
--load-cookies=FILE 在开始会话前从文件 FILE中加载cookie
--save-cookies=FILE 在会话结束后将 cookies保存到 FILE文件中

* FTP 选项

-nr, --dont-remove-listing 不移走 `.listing'文件
-g, --glob=on/off 打开或关闭文件名的 globbing机制
--passive-ftp 使用被动传输模式 (缺省值).
--active-ftp 使用主动传输模式
--retr-symlinks 在递归的时候,将链接指向文件(而不是目录)

* 递归下载

-r, --recursive 递归下载--慎用!
-l, --level=NUMBER 最大递归深度 (inf 或 0 代表无穷).
--delete-after 在现在完毕后局部删除文件
-k, --convert-links 转换非相对链接为相对链接
-K, --backup-converted 在转换文件X之前,将之备份为 X.orig
-m, --mirror 等价于 -r -N -l inf -nr.
-p, --page-requisites 下载显示HTML文件的所有图片

* 递归下载中的包含和不包含(accept/reject)

-A, --accept=LIST 分号分隔的被接受扩展名的列表
-R, --reject=LIST 分号分隔的不被接受的扩展名的列表
-D, --domains=LIST 分号分隔的被接受域的列表
--exclude-domains=LIST 分号分隔的不被接受的域的列表
--follow-ftp 跟踪HTML文档中的FTP链接
--follow-tags=LIST 分号分隔的被跟踪的HTML标签的列表
-G, --ignore-tags=LIST 分号分隔的被忽略的HTML标签的列表
-H, --span-hosts 当递归时转到外部主机
-L, --relative 仅仅跟踪相对链接
-I, --include-directories=LIST 允许目录的列表
-X, --exclude-directories=LIST 不被包含目录的列表
-np, --no-parent 不要追溯到父目录

_________________
我是个菜鸟,希望能走的快点/./././././././././././
ooooo oooooo
,.,.,.,.,.,.,.,.
ooo ooo
=-=-=-=-=-=-=
\\\ \\\
返回顶端
   
spaceyak
2楼






加入时间: 2006/08/03
文章: 24

专家分: 782

时间: 2007-2-21 周三, 13:16    标题:

参数太多让人眼花缭乱,我来献丑列举几个常见的用法:

1, wget www.aaa.com/bbb.zip
最简单,一目了然。

2, wget www.aaa.com/bbb.zip --ref=www.aaa.com/ccc.html
碰到需要引用相应页面的文件,主要是防止盗链。

3, wget -k -np -r www.aaa.com/bbb/
抓取www.aaa.com网站下bbb目录的文件并将相应链接转换成本地可浏览的链接形式,用于本地镜像一个网站。

4, 上次下载漫画时用的一个脚本,很简陋: