2007年6月27日星期三

O'Reilly radar

http://radar.oreilly.com   Oreilly 雷达 -- 技术类 Blog

这是你能够阅读到 Tim O'Reilly(著名的 O'Reilly 出版公司的创始人)和其它人讨论有关于网络、编程、开放源代码运动、知识产权、政策、Web 2.0 和其它前沿科技的地方。 每一篇 blog 还有语音阅读,可以练习英语听力 :)

O'Reilly Media,Inc. 是世界上在 UNIX、X、Internet 和其他开放系统图书领域具有领导地位的出版公司,同时是联机出版的先锋。尤其是在自由软件和开放源代码软件图书上占据着绝对领先的位置。

从最畅销的《The Whole Internet User's Guide & Catalog》(被纽约公共图书馆评为二十世纪最重要的50本书之一)到 GNN(最早的Internet门户和商业网站),再到 WebSite(第一个 桌面 PC 的 Web 服务器软件),O'Reilly Meida,Inc .一直处于 Internet 发展的最前沿。

我通过阅读 O'Reilly 出版的图书,学习了 Perl、MySQL、CSS 。O'Reilly 的图书作者大部分都是所在领域的专家、学者,更多是有实际经验的工程师,他们了解所有的技术实现细节,了解读者的需求。如果对计算机某个领域有兴趣,毫无疑问,O'Reilly 的图书是最好的向导。只是现在出版的很多书籍都没有中文版本,不过没关系,看原著吧,专家和工程师们已经用最朴实简洁的表达描绘了我们想知道和应该知道的一切。 :)

many jokes :)

"我看不清太远的东西,"病人对眼科医生说。
"请跟我来,"医生把病人带到外面,用手指着天上的太阳,问道,"你看那是什么?"
"太阳。"病人回答。
"那你还想看多远!"
----------------------------------
有一位病人来找精神科医师.
病人: 我一直觉得我是一只鸟.
医生: 喔.那很严重喔.从什么时候开始的?
病人: 从我还是一只小鸟的时候.
----------------------------------
有两个神经病患,从病院里逃出来。两人跑啊跑,爬到一棵树上。其中一个人从树上跳下来滚啊滚的,然後抬起头对上面的人说:喂------你怎么还不下来啊---------?
上面的那个人回答他:不---行---啊------我还没有熟透-----------
-----------------------------------
精神病人甲问乙说:"你看我最近完成的这本小说怎么样"?
乙看了看回答:"不错不错,不过,就是人物多了点儿。"
这时,精神病院的护士进来说:"你们把电话号码本给我放回去!"
-----------------------------------
两位精神病人A君B君同时康复,他们的主治医生对他们说:"如果你们其中的一个人犯病了,另外一个人就要马上把他送会医院。
"突然一天,医生的电话铃响了起来,
原来是A君:"不得了了,B君从今天早上开始爬在我家的厕所里,非说他是我的马桶。
""快,快把他送来啊!"
A君沉默片刻:"那……我不就没马桶了吗?"
---------------------------------
有一个神经病院,那里住着很多神经病。一天,那里的院长为了观察一下患者们恢复的情况,想了一个办法。
就对这些患者说:你们都过来。
说着在墙上画了一个门, 说:"今天,你们谁把这个门打开就可以回家了。"
精神病者们一听,便一拥而上,把那画的门围了起来。
院长觉得很失望,这时他发现有一个患者还坐在原来的位置没动,觉得还行,
就上前问到:"你为什么不去开门?"
他看了看院长,偷偷的说:"我这有钥匙。"

2007年6月21日星期四

a joke

From ChinaUnix bbs:

前几天我正在办公室用电脑打公文时.... 老板走到我身边,一看到电脑萤幕之后竟然大摇其头。

然后老板又说:“我说啊,虽然电脑是你打报告而批准买给你的,但你也不能这样嘛!年轻人~”

于是在老板的坚决要求下.... 我很无奈,

只好把桌面上 ....

打的时候还在发抖~~


2007年6月15日星期五

Traversing Contents in Perl

#! /usr/bin/perl
# 从一个目录开始,递归遍历此目录下的所有目录
use warnings;
use strict;

sub do_something {
    open(FILE, '>', 'text_file.txt') or die $!;
    print FILE 'Traversing Contents';
    close FILE;
}

sub traversing {
    chdir($_[0]);
    my @files = glob('*');

    for my $f (@files) {
        if (-d $f) {
            over_d($f);
            do_something(); # 此行在开始的目录下不执行
            chdir('..');
        }
    }
}

# main
traversing('./'); # 从当前目录开始, let's go :)

IBM - Blue Gene

2006年11月,在刚公布的全球超级计算机500强榜单中,基于IBM Power技术的超级计算机数量的大量增加帮助 IBM 在全球超级计算机500强榜单上继续保持排名第一。IBM的系统在全球最强大的500台超级计算机中占据了237台,同时占据了总处理能力的49.6%。

IBM 与美国能源部国家核安全管理局共同开发并安装在 Lawrence Livermore 国家实验室中的 IBM Blue Gene/L 系统在排行榜上名列第一,其连续计算性能高达每秒钟 280.6Teraflop(或每秒数万亿次浮点运算)。另外,基于 IBM BladeCenter JS21刀片服务器并安装在巴塞罗那超级计算中心的 IBM 超级计算机 MareNostrum 重新夺得欧洲最强大超级计算机的称号。

与今年6月公布的上一次榜单相比,基于 Power 架构的系统的数量从83个增加到91个,IBM 在不同计算平台上的优势进一步推进了 IBM 业界的领先地位。与上次榜单相比,Blue Gene 系统的数量从24个增加到了28个,而基于 AMD Opteron 的 IBM 集群系统的数量从31个增加到了55个。

自2006年 6月公布上次全球超级计算机500强榜单以来,IBM BladeCenter 系统的数量从132个增加到145个。在11月公布的榜单中,基于 IBM BladeCenter 技术的系统提供了超过636Teraflop的总性能。IBM BladeCenter 系统通过将服务器、存储、网络和软件全部融合在一个系统之中,为客户提供了一种创新和高密度的计算解决方案。

IBM 深度计算部门副总裁Dave Turek表示:"IBM 继续保持了在超级计算领域的领先地位,这同我们能够为客户提供当前业界最广泛的高性能计算解决方案系列是分不开的。IBM 的系统在很多情况下都是通过与我们客户的合作来完成设计和部署的,这些系统正在拓展科学发现的边界,并帮助我们的商业客户展现虚拟世界和高级仿真并推动实现深入创新。"

  同 Lawrence Livermore 国家实验室的 Blue Gene/L 系统共同进入500强前5名的超级计算机包括 IBM 自己的性能达到91.29Teraflop的 Blue Gene/L Watson 系统、Lawrence Livermore 国家实验室的现在性能达到75.76Teraflop的 ASC Purple 超级计算机,以及巴塞罗那超级计算中心的 MareNostrum 超级计算机,这台使用全新JS21刀片服务器升级的超级计算机性能达到了62.63Teraflop, 比以前增加了一倍。其中,Blue Gene/L 系统和 Purple 系统都是属于美国国家核安全管理局高级仿真和计算(ASC)计划的系统,专门用于确保在无需进行地下核试验的情况下保证美国核武器库的安全性、保密性和可靠性。

在这次公布的全球超级计算机500强榜单上,超级计算机的计算性能总和达到3.527Petaflop,而 IBM 技术提供了其中超过1.75Petaflop的处理能力,比差距最小的竞争对手多出1Petaflop以上。IBM的系统在榜单上最强的10席中占据了4 席。另外,IBM 还在前100席中占据了44席。

全球超级计算机500强中有关IBM的重点内容:

在全球最强大的超级计算机前5名中占据了4个,它们是:Blue Gene/L系统(美国能源部/NNSA/LLNL,处理能力280.6Teraflop)、Watson 研究中心的 Blue Gene/W 系统、Lawrence Livermore 国家实验室的 ASC Purple 超级计算机,以及巴塞罗那超级计算中心的 MareNostrum JS21集群;

在全球超级计算机500强榜单中占据237个,占总数的47.4%;

在3527 Teraflop的已安装总处理能力中占据了1750 Teraflop的处理能力,占总处理能力的49.6%;

在前10名超级计算机中占据4个,是所占数量最多的单独厂商;

  在前20名超级计算机中所占数量最多,达到6个,占30%;

  在前100名超级计算机中所占数量最多,达到44个,占44%;

  在全部361个集群系统中所占数量最多,达到171个,占47.3%;

  美国速度最快的计算机――Lawrence Livermore 国家实验室的 Blue Gene/L 系统;

  欧洲速度最快的计算机――巴塞罗那超级计算中心的 MareNostrum JS21集群。

另外,IBM 的4个全新 Blue Gene 系统也在这次全球超级计算机500强榜单上首次露面,其中一个系统安装在哈佛大学。

自2004 年11月 IBM 宣布以商业形式提供 IBM System Blue Gene 解决方案(该研究项目的商业版本)以来,全球超级计算机500强榜单上已经创纪录地出现了28个 Blue Gene 系统。基于 IBM Power 架构并经过专门优化的 IBM System Blue Gene 解决方案在提供处理大量数据所需的带宽、可扩展性和能力的同时,其功耗和占地空间仅相当于当今速度最快系统的一小部分。目前,IBM 与其合作伙伴正在开发一系列不断增长的高性能计算(HPC)应用,包括基于 Blue Gene 的生命科学、金融建模、流体力学、量子化学、分子力学,天文学、空间研究和气候建模等解决方案。

Speed up the programes

判断数组是否为空,几种方法的效率比较:

                          Total Elapsed Time   User+System Time
if($a[0])                           1                     1
if(exists($a[0]))                1.23                 1.22
if($#a)                             2.03                 2.02
if(@a)                              2.10                 2.09

System Watch & Management

uname -a    系统版本信息等
ps aux       当前进程
nice           进程优先级
renice        调整系统中已存在的进程优先级
fuser          使用某资源的进程
lsof            进程使用的资源
pidof          查看 PID
dmesg       核心启动信息
netstat       网络状态

Input method

使用中文输入法的经历:应该是从 智能ABC 开始(用了5、6年),全拼一开始就被我抛弃了,但是全拼输入法的字库比 ABC 全一点,有些字需要用全拼才能输入,所以电脑上一般都保留 智能ABC 和 全拼 两种输入法。在同事的推荐下改用 紫光拼音v6(大约用了两个月),又在杨经理的推荐下转到 搜狗拼音。刚用紫光的时候感觉比 ABC 强多了,现在又感觉 搜狗 比紫光强多了,呵呵。

不久前 Google 盗用 搜狗 输入法词库的事情炒得沸沸扬扬,我相信 Google 的技术做出更好的输入法应该不是难事,但就目前而言,似乎 搜狗输入法 更胜一筹。
安装程序大小 google 8.9M,搜狗 7.7M;皮肤:搜狗可换,google不可换;输入效率和组词的准确率据网上评论(我现在还没用过google输入法) google输入法也没有太大的优势,所以暂时观望,等待 google 中文输入法的下个版本。

Google search

谷歌搜索遥遥领先 成功背后的秘密
2007.06.04  from:新浪科技  马丁

搜索是重中之重

  随着企业规模不断扩大,谷歌开始向多个领域进军,包括网络地图、数字图书馆、视频共享以及桌面软件等等。但是,谷歌的重中之重仍然是搜索引擎。通过谷歌搜索引擎,用户可以在浩如烟海的大量信息中找到自己需要的内容。正因为有了出色的搜索引擎,谷歌才成为了访问量最大、利润最为丰厚、甚至最为强大的互联网公司。

  不过,搜索引擎给谷歌招致的抱怨也最多。每天都有数百万用户在使用谷歌搜索引擎之后感到失望,因为他们无法找到自己需要的旅馆、医药处方、或者人物背景。谷歌经常能帮助用户找到想要的东西,但并非总能做到这一点。基于这一原因,阿米特・辛格哈尔(Amit Singhal)和其它数百名工程师一直致力于改进谷歌搜索引擎,希望能缩小"经常"和"总是"之间的差距。

  互联网的生命之源

  辛格哈尔是谷歌搜索引擎排名算法的大师。这一算法主要用于确定哪些网页是用户问题的最佳答案,它是谷歌核心团队――搜索质量部门的重要组成部分。长期来来,该部门一直是个谜,谷歌很少允许团队成员抛头露面。谷歌对辛格哈尔及其团队的评价非常高,将他们视为公司最为根本的竞争优势。谷歌认为,要想抵御来自雅虎和微软的强势入侵,就必须降低让用户失望的频度。而在这一过程中,搜索质量部门发挥着不可替代的作用。

  Federated Media首席执行官约翰・巴特勒(John Battelle)表示:"谷歌创建的核心价值就是排名算法。"数据显示,网络商店有四分之一到二分之一的访问者来自于搜索引擎;很多用户都无视媒体网站的网页,而是通过谷歌直接访问所需的特定页面。他说:"从上述事实可以看出,谷歌已经成为了互联网的'生命之源',谁也离不开它。"

  用户无法看到搜索引擎背后的算法和艺术,但事实上,谷歌搜索质量团队每周都要对搜索引擎算法做数次改进。在他们的努力下,谷歌搜索引擎可以更加有效地理解用户的真实意图。例如,有些人搜索"苹果"是为了了解同水果相关的信息,有些人则在研究苹果公司的Mac或iPod。尽管搜索内容相同,但用户的意图却有着天壤之别。辛格哈尔表示:"过去几年里,搜索已经由'给我输入的东西'转变为'给我想要的东西'。"

  不为人知的内幕

  辛格哈尔今年39岁,是一名印度人,于2000年加盟谷歌。他目前是一名谷歌研究员,这是谷歌专门为精英工程师设立的职位。不久前,一名《纽约时报》的记者获准采访了辛格哈尔和其它搜索质量团队成员。尽管谷歌对很多问题都讳忌莫深,但这名记者仍然获得了很多以前不为人知的内幕。

  在谷歌不断改进搜索引擎的过程中,面临的最大挑战是日渐庞大的规模。目前,谷歌已经成为全球访问量最大的网站,支持112种语言,将数百亿个网页纳入索引,每天处理数亿次搜索请求。更为糟糕的是,很多网页创建的目的就是吸引眼球,里面充斥了大量的广告、色情内容和财务欺骗信息。因此,用户希望谷歌能在搜索结果中排除这些无用网页,帮助他们找到最相关的信息。

  谷歌搜索质量团队主管尤迪・马恩伯(Udi Manber)表示:"用户的期望值非常高。当我们刚刚推出搜索服务时,如果用户能通过搜索引擎找到想要的东西,就会感到是一个奇迹。现在的情况则完全不同,如果用户在前三个搜索结果页面中找不到想要的东西,就认为搜索引擎存在问题。"

  谷歌搜索业务充分展现了其打破常规的管理模式。谷歌拥有数百名工程师,其中包括来自学术机构的顶级搜索专家,这些人通常被松散地组织在一起,从事自己感兴趣的项目。但在搜索引擎方面,谷歌会仔细、严格地检查工程师的独立成果,以确保新的搜索算法带来的好处多于坏处。大多数情况下,改进和质量控制都涉及平衡的艺术。马恩伯表示:"改进总会同时带来正面和负面的效应,我们必须衡量哪一种影响更大。只有正面效果,没有负面效果的改进不存在。"

  搜索团队大揭秘

  谷歌搜索质量团队在谷歌办公园区的Building 43工作。由于公司联合创始人拉里・佩奇(Larry Page)向往太空旅行,一个与"太空船一号"同样大小的复制品占据了Building 43的休息室。这一复制品也随时提醒参观者,谷歌就像火箭一样迅速升起。辛格哈尔和其它三名顶级工程师的办公室就坐落于Building 43的顶层,在他办公桌附近的黑板上,到处涂满了图表、问题和数学公式,当然还有用户对谷歌引擎提出的各种意见。

  谷歌的所有员工都可以使用"Buganizer"系统报告搜索问题,而辛格哈尔正是负责解决问题的人。辛格哈尔的同事马特・卡兹(Matt Cutts)表示:"辛格哈尔收到他人提出的问题之后,总是视若珍宝,并努力通过修正算法解决问题。"有些时候,用户或其它谷歌员工提出的问题需要立即得到解决。例如,如果不久前通过谷歌搜索"法国大革命",就会出现大量与法国总统大选相关的信息,而不是打倒法国国王路易十六的那场革命。谷歌搜索质量团队很快改变了网页的权值,从而解决了这一问题。

  当然,有时会出现更为复杂的问题。2005年,谷歌产品经理比尔・布罗格(Bill Brougher)指出,当用户搜索"teak patio Palo Alto"时,并不会返回这家名叫"Teak Patio"的本地商店。辛格哈尔随即启动了一项名为"Debug"的内部计划,检查计算机系统对每一个查询和网页的评价。

  辛格哈尔最终发现,Theteakpatio.com之所以没有在搜索结果中显现,主要因为谷歌搜索算法并没有赋予来自Palo Alto的其它网站足够的权值。收到投诉后的两个月内,辛格哈尔及其团队改进了搜索算法,从而解决了相关问题。不过,辛格哈尔并不能匆忙地解决所有问题,因为搜索引擎的每一次调整都会影响到很多网站。因此,他将很多问题都记在黑板上,如果同样的问题再次出现,他就会调整其优先级。

  人才是成功根本

  为了提高搜索引擎的质量,谷歌一直致力于从研究实验室和大学招募人才。例如,辛格哈尔就来自于AT&T实验室;马恩伯最初曾经在亚利桑那大学担任计算机教员,随后加盟雅虎担任首席科学家,之后还曾运营过亚马逊搜索部门。他去年从亚马逊加盟谷歌,很快就发现谷歌搜索引擎遥遥领先于学术实验室和其它企业竞争对手。他回忆道:"加入谷歌后的前三个月里,我经常会说,'我有一个想法'。但他们总是告诉我,'已经有人提出过这个想法,它无法发挥作用'。"

  谷歌搜索质量团队的分工非常明确:辛格哈尔等工程师主要负责用户输入关键字后的系统处理;一部分人主要负责改进搜索结果,例如优化网站描述,让用户更容易了解一个网站的内容;以马恩伯为首的其它成员则主要负责维护庞大的网页索引。在早期阶段,谷歌每六到八周创建一个新索引,而现在该公司每隔几天就要重新核对很多网页。

  在编辑索引的过程中,谷歌主要考虑每一个网页的PageRank。PageRank是谷歌联合创始人佩奇和塞吉・布林(Sergey Brin)的重要发明,它主要用于标识其它网站链接到特定网页的次数。网页的PageRank越高,在搜索结果中的排名也就越高。辛格哈尔已经开发出一个更为精确的系统来为网页排名,它涉及了200多种信息,PageRank只是其中之一。

  要完全了解谷歌搜索引擎所采用的技术是一项不可能完成的任务,因为这是谷歌赖以成功的根本,同时也是其它竞争对手梦寐以求的东西。只从搜索结果来看,很多时候并不能看出谷歌搜索引擎与竞争对手的差异。但搜索专家丹尼・沙利文(Danny Sullivan)认为,谷歌仍然领先于竞争对手。巴特勒也表示:"人们仍然认为谷歌是搜索的黄金标准。"

Do many things, like pings

From redspid.blog.163.com
2007年 06月06日 19:42

Perl 多进程的例子,收藏先。

作 者:Randal L. Schwartz

As a Unix system administrator, I'm often faced with those little mundane tasks that seem so trivial to me but so important to the community I'm supporting. Little things like ``hey, is that host up and responding to pings?''. Such tasks generally have a very repetitive nature to them, and scripting them seems to be the only way to have time to concentrate on the tasks that really need my attention.

作为一个 Unix 系统管理员,我经常会面对一些单调乏味的任务,虽然这对我来说是小菜一碟,但是对于我所支持的社区来说却显得比较重要了(比如很简单的事情"嘿!那台主机在工作吗?回应我的 ping 请求吗?")。这类任务通常都具有重复性,所以为了让我们能把精力集中在该集中的地方,写个脚本搞定这些琐事似乎就是唯一的方法了。

Let's look at the specific task of pinging a number of hosts on a subnet. Now, there are tools to do this quickly (like nmap), and there are even Perl modules to perform the ping (as in Net::Ping), but I wanted to focus on something familar that can be launched from Perl as an external process, and the system ping command seems mighty appropriate for that.

让我们看看这个在子网内 ping 大量主机的典型任务。现在有一些工具(像 nmap)可以很快地完成这个任务,而且甚至还有 Perl 模块来实现 ping(比如 Net::Ping),但我还是想把目光集中在一些能在 Perl 中作为额外进程运行的我们所熟悉的工具上,这样看来,系统所带的 ping 命令似乎比较适合。

First, let's look at how to ping one host, on my BSD-ish system:

首先,让我们看看如何 ping 一台主机,在我的 BSD 类系统中:

  sub ping_a_host {

    my $host = shift;

    `ping -i 1 -c 1 $host 2>/dev/null` =~ /0 packets rec/ ? 0 : 1;

  }

Here, I'm firing up a subshell to execute the ping -i 1 -c 1 command, which on my system requests ping have a 1-second timeout, and selects (as Sean Connery's character said in The Hunt for Red October so eloquently) ``one ping only''. Your ping parameters may vary: check your manpage.

这里,我们创建了一个子进程来执行 ping -i 1 -c 1 命令,这个命令只会 ping 目标主机一次,而且设置了超时时间为1秒。并选择(像肖恩-康纳利在《追击红色十月》里演的那个角色一样非常意味深长地说)"只 ping 一次"。你系统上的 ping 所需的参数可能有不同,请查看你的 man 说明。

The output is scanned for the string 0 packets rec, which if absent means we got a good ping. So if the match is found, we return 0 (the ping was bad), otherwise we'll return 1. The ping command spits out some diagnostics on standard error, which we'll toss using Bourne-shell syntax.

程序会在命令执行完所得到的输出中搜索 "0 packets rec" 这个字串,如果没有找到这个字串,说明 ping 成功了(目标主机有回应)。所以,如果我们找到了这个字串,那么返回 0(ping 失败了),否则我们返回 1。由于 ping 命令会向标准错误端输出一些诊断信息,所以我们把这些信息丢到 /dev/null 中去。

Note that the value of $host is not checked here for sanity. We certainly wouldn't want to accept a random command-line parameter or (gasp) a web form value here without some serious validation. However, as we use this in our program, all of the values will be internally generated, so we've got some degree of safety.

注意,这里没有对 $host 的值进行正确性检查。我们可不想接收一些事先没有经过验证的任意命令行参数,或者是通过网络表单传递来的值。不过,程序里所有值我们都将在程序内部生成,所以这已经是一层安全保障了。

So to scan a particular subnet, looking for hosts that are alive, we would add to that subroutine something like:

为了 ping 一个特定的子网看看有哪些主机存活,我们可以为上面的子程序添加如下的代码:

  print "ping $_ is ", ping_a_host($_), "\n"

    for map "10.0.1.$_", 1..254;

Now, this routine completes very quickly for hosts that are alive, but is slow-as-molasses for hosts that aren't present, because the TCP protocol demands that the host have a chance to respond.

现在,当主机存活时, ping 这一步很快就会完成,但如果主机不在(或者没有回应),那这一步就会非常慢了(由于 TCP 协议要求主机可以有一定的响应延迟的原因)。

So how can we speed that up? This is not a CPU-intensive loop: practically the entire time is waiting for some remote host to respond. We'll leave the ping_a_host subroutine alone, because that's not where we have a problem: it's doing its job as fast as it can. What we need to do is to do more of them at a time.

那么我们如何让程序加速呢?这并不是一个占用 CPU 很厉害的循环:实际上整个时间都花费在等待远程主机的回应上了。我们不管这个 ping_a_host 子程序,因为这并不是问题的所在:他正全速工作呢。我们需要的是在同一时间能做更多这样的任务。

One first approach is to fork a separate process for each host we want to ping. We'll then sit back in a wait loop. As each child process completes, we'll note its exit status, and when there are no more kids, we'll spit out a report.

其中一个首要的途径是为我们想 ping 的每一个主机 fork 出一个独立的进程。然后我们将返回到一个等待的循环中。当所有的子进程都完成的时候,我们会留意他们的退出状态,并且当子进程都结束后,再给出一个结果报告。

So, first, we'll define the host list for the task:

那么,首先,我们得先定义所需的主机列表:

  my @hosts = map "10.0.1.$_", "001".."010";

The numbers here are padded to three digits so that they sort as strings in a numeric sequence, a cheap but effective trick. Note also that I'm only selecting the first 10 hosts this time. I'll explain that shortly.

这些主机的最后部分被填充成三位,这样就能让这组字符串按照数字顺序来排序,简单而有效的技巧。注意我只选了子网中的前10台主机,后面我会解释原因。

Next, we'll want a hash to keep track of the kids:

下一步,我们将利用一个散列(hash)来跟踪子进程:

  my %pid_to_host;

The keys of this hash will be the child process ID (PID), and the value will be the corresponding host that the child is processing. Next, we'll want to loop over the host list, firing up a child for each:

子进程的进程号(PID)将成为这个散列的关键字,而其键值就是该子进程正在处理的相对应的主机地址。下一步,我们将遍历整个主机列表,为其中的每一个主机创建一个子进程:

  for (@hosts) {

    if (my $pid = fork) {

    ## parent does...

    $pid_to_host{$pid} = $_;

    warn "$pid is processing $_\n";

    } else { # child does

    ## child does...

    exit !ping_a_host($_);

    }

As each host is placed into $_, we'll fork. The result of fork is a child process running in parallel with the parent process. These processes are distinguished only by the return value of fork, which is 0 in the child, but the child's PID in the parent. So, if we get back a non-zero value, we're the parent, and we'll store the PID into the hash, along with the host that particular child is processing. If we're the child, then we'll call the ping_a_host routine, and arrange for our exit status to be good (0) if that routine gives a thumbs up.

在上面的代码中,所有的主机都会在 for 循环中依次传递给变量 $_ ,然后我们将进行 fork。调用 fork 函数后,我们将得到一个和父进程并行运行的子进程。它们之间的区别仅仅在于 fork 的返回值(fork 会返回两个值),如果返回值为 0,那说明在子进程中,父进程中 fork 的返回值就是子进程的 PID(进程号)。所以,如果我们得到一个非零的返回值,那么我们就在父进程中,在该进程中我们将会把子进程的 PID 及与工作中的该进程相应的主机 ip 保存到散列中。假如我们在子进程中,那么我们将会调用 ping_a_host 程序,并且当这个程序正常退出的时候,我们把退出状态码置为 0 (表示工作正常的)。

The warn in the loop is merely for diagnostic purposes so that you can see what's happening. In a production program, I'd certainly remove that.

这个循环中的 warn 仅仅用来输出诊断信息,这样你就可以知道程序正在干什么。当程序作为成品的时候,我会把这行去掉。

At the end of this loop, we'll have a number of processes. Far too many, in fact. For each host to check, we'll have two processes running: the shell forked by the backquotes, and the ping process itself. Perl has to fork a shell because I needed that child to have its standard error output redirected. If I could have gotten the redirection out of those backquotes somehow, we'd have only one child process per host, not two.

在这次循环的最后,我们将会有很多个进程。事实上太多了。对于每个要检查的主机,我们将耗费两个进程:一个是反引号调用系统命令分出的 shell 进程,一个是 ping 这个进程本身。Perl 之所以得分出一个 shell 进程是因为我们需要把这个子进程的标准错误输出转向(不会在屏幕上显示出来)。假如我们能用某种方式避免使用反引号调用的输出转向,那么我们就能只分出一个进程而不是两个了。

Launching 20 processes to check 10 hosts will start pushing us up against the typical per-user process limit. And now you can see why I didn't do all 254 hosts at once!

创建20个进程去检查10台主机将使我们面临经典的每用户进程数限制的问题(校者注:unix 下可以通过 ulimit -u 命令查到这个进程限制)。现在你应该明白我为什么先前只选前10台而不是一次性把254台主机都放进来的原因(会产生 508 个子进程!)。

Now it's time to wait for the results. A simple ``wait'' loop will reap the children as fast as they complete their task. First, we'll declare a hash to hold the results:

现在是时候等待返回结果了。用一个简单的 "wait" 循环就能在子进程完成任务之后尽快地收割它们。首先,我们得声明一个散列来保存结果:

  my %host_result;

The key will be the host, and the value will be 1 if the child said it was pingable, otherwise 0.

主机地址将成为该散列的关键字,而其对应的键值将是 1(当子进程说那台主机可以 ping 到)或者 0(ping 不到)

  while (keys %pid_to_host) {

    my $pid = wait;

    last if $pid < 0;

    my $host = delete $pid_to_host{$pid}

    or warn("Why did I see $pid ($?)\n"), next;

    warn "reaping $pid for $host\n";

    $host_result{$host} = $? ? 0 : 1;

  }

As long as we've got kids (indicated by the ever decreasing size of the %pid_to_host hash), we'll wait for them. The child process ID comes back from wait, which we'll stick into $pid. At this point, the exit status of that particular child is in $?. If the return value of wait is negative, then we don't have any more kids. This is an unexpected result, which we could check later by noticing that %pid_to_host is not yet empty, or we could have simply died here.

当有子进程存在的时候(由大小递减的散列 %pid_to_host 所指示),我们将会等待它们直到它们完结。wait 函数会返回子进程的进程号,我们把它保存至 $pid。此时,指定的子进程的退出状态保存在特殊变量 $? 中。假如 wait 返回值是负数,那说明我们没有子进程了。这不是我们所期待的结果,我们可以通过检查散列 %pid_to_host 是否非空来确认,或者简单的就在此处结束。

Next, we'll use the %pid_to_host hash to map the PID into the host for which it was processing. Again, we might have accidentally reaped a completed child which wasn't one of ours, so defensive programming requires checking for that. This won't happen unless other parts of this program are also forking children somehow, but I'm a cautious programmer most of the time.

接下来,我们将利用散列 %pid_to_host 将进程号映射到正在处理的主机。也许我们会偶然地将一个已完成的不属于我们的子进程收割掉,所以我们要对其进行检查。当我们没有在这个程序的其他地方以某种方式分出子进程的时候,就不会产生这种情况,虽然我们这个程序满足这个要求,但大多数时候我是个谨慎的程序员(所以我在程序中加入了对这种情况进行检查的代码)。

Finally, we'll take the exit status in $?, and map it into the appropriate good/bad value for the result hash.

最后,我们将参照特殊变量 $? 中的退出状态码把 ping 结果的 好/坏 值保存至结果散列。

When this loop completes, we have no more kids performing tasks, and it's time to show the result:

当这个循环结束,就没有子进程在处理任务了,现在是时候显示结果了:

  for (sort keys %host_result) {

    print "$_ is ", ($host_result{$_} ? "good" : "bad"), "\n";

  }

For each key of the result table, we'll say whether the result was good or bad.

以上的代码打印出每台主机 ping 的结果。

Putting this all together makes a nice little demo of forking 20 kids to check 10 hosts, but it won't scale to 254 hosts, because that would require more process slots than we typically have (or want to use, actually). What we need to do is perform the forking gradually, so that we never have more than 20 kids at a time. One naive approach is to chunk the data into bite-size bits:

把上面所有的代码凑到一起就成了一个分出20个子进程来检查10台主机的漂亮的演示程序,但是它却不适合有254台主机的情况,还记得前面提到的每用户进程限制吗?那怎么办呢?我们可以循序渐进地分出子进程的嘛,这样我们就可以保证同时不会有超过20个子进程存在。一个笨办法就是把数据(这里指主机列表)分割成几个部分:

  my @all_hosts = ...;

  my %host_results;

  while (my @hosts = splice @all_hosts, 0, 10) {

    ... process @hosts, adding into %host_results ...

  }

  ... show results ...

Here, most of the code above gets wrapped into an outer loop which hands 10 hosts at a time to be processed, using splice to peel them off of the master list. While this strategy certainly solves the ``no more than 10 at a time'' condition, each batch of 10 has to wait for the slowest of the 10 to complete.

以上的代码在用 splice 函数将 @all_hosts 每次分成10份付给 @hosts,然后针对 @hosts 来进行多进程的处理,这样,用一个外层的 while 循环(相对于那个多进程处理的循环)来保证同时只处理主机总列表中的10台主机。这种策略的确能解决"同时不多于10台主机"的问题,但是实际上每一批 10台主机都要等前面的10台主机处理完后才能继续,这样显然太慢了。

A better way would be to fork until we hit the limit of active children, then wait for one child to finish before we need to fork again. First, we'll need to factor out ``waiting for a kid'' into a subroutine so we can call it in two different places: while forking a new task, and at the end to reap all the remaining children:

一种更好的方法就是如果正在运行的子进程数量没有达到设定的极限值,就继续 fork,否则就等待某个子进程完成然后再 fork。首先,我们需要把"等待某个子进程"写成一个子程序以方便我们在两个不同的地方调用:当为新任务创建子进程以及在最后收割所有仍然存在的子进程的时候。

  sub wait_for_a_kid {

    my $pid = wait;

    return 0 if $pid < 0;

    my $host = delete $pid_to_host{$pid}

    or warn("Why did I see $pid ($?)\n"), next;

    warn "reaping $pid for $host\n";

    $host_result{$host} = $? ? 0 : 1;

    1;

  }

Note that we're accessing %pid_to_host and %host_result directly here, so those variables must be in scope before the subroutine definition. The subroutine now returns 1 if a kid was reaped, and 0 otherwise. The final reap loop now becomes:

注意我们这里是直接的访问散列 %pid_to_host 和 %host_result 的。所以它们必须已经在这个子程序定义之前定义了。当一个子进程被顺利收割时,该子程序返回1,否则返回0。程序最后的收割循环(译者注:这个收割循环会持续到所有的子进程全部被收割为止,这样是为了避免僵进程导致进程泄漏,关于僵进程和进程泄漏的概念,请自行查找有关资料)现在变成了:

  ## final reap:

  1 while wait_for_a_kid();

At this point, the program functions identically to the prior one, except that I've refactored the kid reaping. The magic happens next. We'll put wait_for_a_kid in the middle of the forking loop as well, just before we're about to fork, conditionally if the number of kids is already at the maximum we chose:

到这步,除了我重新写的这个子进程收割程序,这个程序的功能就和先前的那个一样了。接下来将发生一些魔术般的事情,呵呵。我们将把 wait_for_a_kid 子程序放到创建子进程的那个循环中,调用 fork 之前,在子进程数达到设定的极限值时调用该子程序。

  for (@hosts) {

    wait_for_a_kid() if keys %pid_to_host >= 10;

    ...

Ahh. That does it. We can now crank @hosts back up to our 254 items. As we fire off the first 10, this new statement has no effect. But when it comes time for the 11th, we'll wait until at least one of the other 10 to complete first. So, at no time do we have more than 10 hosts active (using 20 child processes for reasons explained earlier). The entire program is given here in case you want to see it all in context:

啊哈!现在我们可以把 @hosts 中主机的数量增加到254台了。当在为前10台主机创建子进程的时候,这条新加的表达式并不起什么作用,但是,当为第11台主机创建子进程的时候,它就会一直等待直到至少有一台主机已经处理完毕才继续。这样,我们就不会在同一时间处理超过10台主机了(处理10台机会使用20个子进程,原因前面说过了)。下面就是完整的程序:

  sub ping_a_host {

    my $host = shift;

    `ping -i 1 -c 1 $host 2>/dev/null` =~ /0 packets rec/ ? 0 : 1;

  }

  my %pid_to_host;

  my %host_result;

  sub wait_for_a_kid {

    my $pid = wait;

    return 0 if $pid < 0;

    my $host = delete $pid_to_host{$pid}

    or warn("Why did I see $pid ($?)\n"), next;

    warn "reaping $pid for $host\n";

    $host_result{$host} = $? ? 0 : 1;

    1;

  }

  my @hosts = map "10.0.1.$_", "001".."254";

  for (@hosts) {

    wait_for_a_kid() if keys %pid_to_host > 10;

    if (my $pid = fork) {

    ## parent does...

    $pid_to_host{$pid} = $_;

    warn "$pid is processing $_\n";

    } else { # child does

    ## child does...

    exit !ping_a_host($_);

    }

  }

  ## final reap:

  1 while wait_for_a_kid();

  for (sort keys %host_result) {

    print "$_ is ", ($host_result{$_} ? "good" : "bad"), "\n";

  }

As a working program, this does pretty good, although it could be made a bit more robust, and is very specific to the particular ping program on my machine. If you don't want to write this pattern of code into each program that wants to do parallel things, look at Parallel::Fork Manager in the CPAN, which does pretty much the same thing with a friendly interface.

虽然这个程序还可以进一步的完善以使它更强健,但现在他工作得很好,比起单单用我系统上的 ping 命令,用这个程序来完成任务就显得有效多了。如果你不想每次一涉及并行处理的事情就套用上面的代码,那么可以试试 CPAN 上的 Parallel::Fork Manager 模块,它也能够漂亮的实现到相同的效果,不过更妙的是它拥有一个更友好的接口。

One improvement to this program might be to pre-fork and re-use the children, using some sort of IPC (pipes or sockets) to communicate additional tasks to perform as each task completes, but I've run out of space to talk about that here. Until next time, enjoy!

预创建进程以及子进程重用(在每个任务完成的时候利用一些进程间通信(IPC)的方式(管道或者套接字)来与接下来的任务进行通讯)可以作为该程序的一个改进,但是这已经超出了本文的范围。okay, 希望你能喜欢这篇文章,下次再见!

―――――――――――――-

在 Parallel::Fork Manager 模块文档里摘一个实例给懒惰的 Perl 程序员 :) 这个例子会创建 30 个子进程来并行下载不同的链接。这要比亲自动手调用 fork 简单多了。

use LWP::Simple;

use Parallel::ForkManager;

...

@links=(

  ["http://www.foo.bar/rulez.data","rulez_data.txt"],

  ["http://new.host/more_data.doc","more_data.doc"],

  ...

);

...

# 同时使用 30 个进程

my $pm = new Parallel::ForkManager(30);

foreach my $linkarray (@links) {

  $pm->start and next; # 开始 fork

  my ($link,$fn) = @$linkarray;

  warn "Cannot get $fn from $link"

    if getstore($link,$fn) != RC_OK;

  $pm->finish; # do the exit in the child process

}

$pm->wait_all_children;

First you need to instantiate the Fork Manager with the "new" constructor. You must specify the maximum number of processes to be created. If you specify 0, then NO fork will be done; this is good for debugging purposes.

首先通过 new 来初始化一个 Fork Manager 对象,同时必须标明最大进程数。如果使用 0 的话就可以避免 fork 来达到调试程序的作用。

Next, use $pm->start to do the fork. $pm returns 0 for the child process, and child pid for the parent process (see also "fork()" in perlfunc(1p)). The "and next" skips the internal loop in the parent process. NOTE: $pm->start dies if the fork fails.

然后使用 $pm->start 来开始 fork。 $pm 在子进程时返回 0 ,父进程时返回子进程的进程号(具体请参阅 Perl 的 fork 文档)。"and next" 用来跳过父进程。注意:如果 fork 失败的话, $pm->start 就提示错误,程序结束。

$pm->finish terminates the child process (assuming a fork was done in the "start").

$pm->finish 结束子程序(假设我们一开始使用了 start 来 fork)

NOTE: You cannot use $pm->start if you are already in the child process. If you want to manage another set of subprocesses in the child process, you must instantiate another Parallel::Fork Manager object!

注意:在子进程中不能使用 $pm->start。 如果你想在子进程中使用另外一组子进程,你必须再初始化一个 Parallel::Fork Manager 对象。

2007年6月13日星期三

Rich format blog

知道怎么通过 email 发布非纯文本格式的 blog 了,需要发送 html 格式的邮件。

我一直使用 GOOGLE 的搜索引擎,效果非常好,也就是搜索音频时才用百度。现在正式加入 GOOGLE fans 的行列 o(∩_∩)o... 。电子邮件用 Gmail,网络相册用 picasaweb ,网络日志用 blogger,包括自定义的 GOOGLE 页面 igoogle,GOOGLE 日历,功能确实强大。只是网络连接速度比国内网站要慢许多,这也难怪,中国的防火墙太厚了,连 blogger 都要通过 ftp 转发,想不通为什么要拦截 blogger。我想,这也是影响 GOOGLE 在中国业务发展的重要因素。但是国内几个所谓大网站提供的服务兼容性实在是太糟糕了,尤其是对非 windows 系统和非 ie 浏览器的兼容性。

中国的 Linux、Unix 用户太少了,目前国内的计算机应用大都处在超初级阶段,整天就是 word、excel、ppt,把计算机当成打字机、复印机来用,暴殄天物啊。专业计算机教育实践环节太少,程序不是读书读出来的,就像书法、美术一样,更重要的是写、练。学习算法仅仅把书本上的例子看懂了是没用的,把书收起来,自己写代码,一定要是可以运行的代码,让计算机给出最终的判断结果,这样才算是把这个算法掌握了。其实计算机科学(主要指软件方面)是理论与实践高度一致的科学,通过实际操作是理解、掌握理论知识的最佳途径。

Vim 7

与旧版本相比,在 Vim 7 中新增了多项重要的特性。

使用拼写检查功能:
Vim 7 内置了一项拼写检查功能,使用该功能可以检查出所拼写词语的错误。在默认情况下,这项功能是没有开启的。若是使用 GVim
的话,可通过"Tools -> Spelling -> Spell check on"菜单命令开启。Vim
一旦发现拼写错误的词语,则以红色的波浪线标记。而使用以下命令可以执行拼写检查功能的相关操作:

:set spell 开启拼写检查功能
:set nospell 关闭拼写检查功能
:]s 移到下一个拼写错误的单词
:[s 作用与上一命令类似,但它是从相反方向进行搜索
z= 显示一个有关拼写错误单词的列表,可从中选择
zg 告诉拼写检查器该单词是拼写正确的
zw 与上一命令相反,告诉拼写检查器该单词是拼写错误的

使用括弧高亮显示功能:
此特性在编码时非常具有帮助。对于如"{"、"}"之类的配对括弧,Vim 7 将高亮显示它们。如果不喜欢,可以使用":NoMatchParen"命令禁用该功能。

使用自动补完功能:
这是一个非常酷的特性。当你在写代码的时候,可以使用该功能帮助你自动完成标记、关键字等等。此功能支持 C、(X)HTML(包含
CSS)、JavaScript、PHP、Python、Ruby、SQL、XML 等语言。在插入模式中,连续按"[Ctrl+x]
[Ctrl+o]"组合键可以打开该功能。你可以从弹出的列表框中进行选择。

http://linuxhelp.blogspot.com/2006/09/visual-walk-through-of-couple-of-new.html

2007年6月12日星期二

Upgrade documents

From my.opera.com/redspider

尖括号(<>)的神奇特点:如果没有指定文件名,则其从标准输入流中自动打开和关闭一系列文件进行读入。但如果 $^I
中有字符串,这个字符串则会成为备份文件的扩展名。
(下面的代码通过给 @ARGV 赋值,模拟标准输入得到的文件名)


$^I = '.bak';# 备份文件后缀名
@ARGV = glob('*.txt');# 模拟命令行参数获得的文件名 :)

# 逐个打开从命令行获得的文件,更新内容
# 源文件以 $^I 定义的后缀名备份
while (<>) {
s/author/author: redspider/g;
print;# 默认输出自动被重定向至文件
}

# 删除备份文件
my @bakfiles = glob('*.bak');
for (@bakfiles) { unlink($_) }

RHCE note: shell scripts, configuration files

From redspid.blog.163.com
2007年 06月05日 00:55

常用 Shell script:
/etc/rc.sysinit 系统初始化脚本
/etc/rc.local 用户自定义启动脚本
/etc/profile bash shell 登录脚本之一

使用 useradd 增加账号的默认设定在 /etc/login.defs 中

系统日志:
/var/log/dmesg 核心启动日志,用 dmesg 命令查看
/var/log/messages 系统报错日志
/var/log/maillog 邮件系统日志
/var/log/xferlog FTP 服务用日志
/var/log/secure 安全信息,系统登录与网络连接信息
/var/log/wtmp 登录记录

2007年6月11日星期一

RHCE Note

From redspid.blog.163.com
2007年 06月03日 23:28

Opera Blog 还是登录不上,好多重要的笔记都在上面,备份确实很重要。能访问 Opera Blog 的时候要把东西都转过来。

六一还行哈,honey_jing 应该比较满意吧,嘿嘿...

是时候好好复习提高一下 Linux 了,准备 RHCE !

登录用的虚拟控制台可根据需要增减,配置文件为 /etc/inittab

file 指令从系统配置文件 /usr/share/magic 中读取相应的文件规范

ls 指令标识文件颜色的定义在文件 /etc/DIR_COLORS 中

umask 在 /etc/profile 中设置

主机名配置在文件 /etc/sysconfig/network 中

Bash 中常用快捷键:
Ctrl + s ,Ctrl +q 暂停/恢复屏幕输出
Ctrl + l 清屏,相当于 clear
Ctrl + a 光标移至行首
Ctrl + e 光标移至行尾
Ctrl + k 删除光标至行尾的内容
Ctrl + u 删除整行

New starting

这一篇沿用 163 blog 上的标题,因为意义特殊哈 :)
From redspid.blog.163.com

2007/05/25 一个新的开始哈 ^^

(25日 开始,26日 honey_jing说表现不错,但要继续努力 嘿嘿)。

这也是163上的第一篇 BLOG,http://my.opera.com/redspid 这几天不知道为什么不能登录。我需要重开一个稳定点的
BLOG,以前的也要备份一下,好多精典呢。

Honey jing:

When you're lost and the light is fading
the wind blows cold and you can't find your way back home
remember that the darkest hour is just before the dawn
Sometimes a leap of fauth is all it takes
cause only love can see the path to set you free
just close your eyes, look inside, and let your heart believe
there's been a force so strong beside you all alone
you'll know it when your dream comes true
there's something only love can do
in your quest for a new horizon
set your course find a star to light your way
although the task may seen sometimes to be more than you can bear
one thing you need to know you are not alone
If you believe in miracles then you can be the one
to shine you light and show the world
There's nothing love can't overcome
There's something only love can do

First blog on blogger

http://my.opera.com/redspider 有一个月登录不上去了,在 http://redspid.blog.163.com 上记了几篇笔记。才发现 Google 也有 Blog,嘿嘿,太好了,一会就把 163 上的转过来。
我还是比较信任美国的技术,事实不容置疑啊。 :)