行者无疆 始于足下 - 行走,思考,在路上

打造高效的工作环境(2): 高效的文件管理

1 为什么Windows的文件系统混乱、低效?

让众位久等了!上篇Why Windows Sucks的吐槽文中,我曾谈到,Windows文件系统几点令我非常不喜欢的地方:

  • 文件系统多盘拼,文件命名大小混
  • 权限控制小烦躁,命令终端很废柴

本篇我们稍微深入探讨一下这个话题,并由此引入我们接下来系列文章的主角,*nix。

上小学的时候我们就知道,Windows的第一个盘是C盘。如果你稍微研究下所谓“Windows提速优化”这类的教程,你就会知道C盘是所谓的系统盘,非常重要。如果你足够细心,并且有足够的耐力,那么你可能会学到:

  • 程序尽量不要装在C盘,影响系统运行速度
  • 可以用工具将C盘里的"My Documents"(中文名是“我的文档”)里面的东西转移到别的盘里,这样可以节省很多系统盘的空间,“有可能”使得系统运行更加畅快
  • 定期整理下磁盘碎片,清理下注册表,杀杀毒,可以提高系统运行速度

但是你有没有想过:

  • A盘和B盘哪里去了?
  • 为什么我的系统有C、D、E三个盘而别人的系统除了C、D、E还有F,甚至还有Z盘?
  • 为什么一个电脑的文件系统要分为多个盘呢?
  • 苹果系统需要整理磁盘碎片吗?
  • 注册表到底是干嘛用的?
  • ……

事实上这个世界上本不该有这么多个为什么,一切的一切,源于Windows蹩脚的设计:

  • Windows的文件系统是多根的,这导致你几乎没有办法控制你的移动硬盘的挂载点,几乎没有办法进行chroot高级实验,几乎没有办法制定规范化的类似于*nix下的FHS标准
  • Windows的文件系统目录结构是极其混乱而不统一的,我引用一张表格1来对比说明下*nix和Windows两种文件系统的目录结构,你可以看到,*nix系统目录的命名都非常简洁规律,便于脚本自动化处理,而Windows的文件命名和目录结构像是一层层的石头胡乱堆砌的
     
    Function Linux Microsoft
    Kernel root "WINNT" or "WINDOWS"another page on this site
      /boot  
    Executables /usr/bin "Program Files"
      /usr/lib  
      /usr/share  
      /usr/doc  
      /usr/apps  
    Drivers /dev Win…/System32
    hosts file /etc Win…/System32/Drivers/Etc
    One for each User /usr "Documents and Settings"
      /user  
    Log files /var -
    Temporary work files /tmp Temp
    Optimizing Utilities /opt -
  • Windows的系统文件命名非常混乱,不堪入目,正如“一千个读者心中就有一千个哈姆雷特”一样,一千个Windows C盘就有一千种的文件命名和目录结构,下面是我的正版Windows 7系统下的C盘目录:
    • Windows 7下的C盘:
      • autoexec.bat
      • b7e61efa43ef263f987f6b2dbfe5b362
      • Boot
      • bootmgr
      • BOOTSECT.BAK
      • bootsqm.dat
      • Config.Msi
      • config.sys
      • Documents
      • Download
      • found.000
      • Intel
      • IO.SYS
      • LLabs
      • mfg
      • MSDOS.SYS
      • PerfLogs
      • ppsvodcache
      • ProgramData
      • Program
      • QQDownload
      • $RECYCLE.BIN
      • RRbackups
      • swshare
      • System
      • Temp
      • Users
      • Windows
    • linux下的根目录:
      • bin
      • boot
      • dev
      • etc
      • home
      • lib
      • lib64
      • lost+found
      • media
      • mnt
      • opt
      • proc
      • root
      • run
      • sbin
      • srv
      • sys
      • tmp
      • usr
      • var
  • 合理的文件结构组织和文件命名,对于自动脚本处理是非常重要的,譬如,如果一个文件名称为"My Documents",那么在脚本处理中,如果不小心编码,这个文件就会被当成"My"和"Documents"两个文件处理。

1.1 历史原因

当然,这种混乱是有一定历史原因的。细细讲来倒是很有意思的一件事情。话说MS80年代初只是主打做Basic语言解释器小的软件公司,后来IBM需要发展PC机,最开始找的是DEC公司的人,但是DEC的老总据说是非常忙,而私人飞机好像出了问题,于是就错过了和IBM的谈判,让MS拣了个大大的便宜。而MS呢,手头是没有成型的操作系统的,就从一个不知名的小公司里面花了5万刀买来了一个系统,并重新命名为MS-DOS,联合Intel和IBM做起了合伙生意,只是IBM没有想到的是,你来我往,几番周折,两个小弟弟MS和Intel成长了起来,在90年代中期其风头甚至盖过了IBM自己。其实谈起计算机的水平和资历,全世界也没有几个敢和IBM叫板的公司,当年IBM 360系统的横空出世,不仅开创了软件工程中众多的“人月神话”,更让无数黑客在360系统的熏陶下成长起来。扯远了,话说回来,MS-DOS呢,是一个非常蹩脚的操作系统,甚至连美国大学里的学生都瞧不惯,说微软是做小儿科系统的公司2。你想一想,90年代的时候,Richard Stevens的APUE都出第一版了,而MS-DOS大概才刚刚摆脱8个字符以下长度文件名的限制。后来呢,苹果抄袭Xerox,搞出了漂亮的GUI,这样一来,微软压力甚大,因为系统底层比不过Unix,表面层GUI又被苹果占了先机,危矣。怎么办好呢?微软开始一面搞Windows,一面联合IBM搞OS/2,同时明修栈道、暗度陈仓,从老的DEC公司挖来一批人开始默默地搞NT(号称"New Technology"的操作系统)。这样一直多战线并存的搞到了Windows 2000的横空出世。话说Windows 2000之所以叫Windows 2000,一方面是因为它是在2000年推出的,另一方面恐怕是搞出Windows 2000确实动用了MS 2000个以上的人力(我猜的,不过几千人的人力是有的)。至此呢,Windows开始一心搞NT。其实这样也好,美中不足的是NT为了兼容以前蹩脚操作系统,背上了很多沉重的历史包袱,这也导致Windows系统更新换代的速度特别的慢。Ubuntu半年推出一个新版本,Mac OS自动X后,10年光景,已经到了X.7的版本,每个版本都有大的提升,而微软闭门造车耗时五年的Vista,还有新进推出的Win7,奋战了这么多年,还是没能将XP第一的宝座纳入囊中,我看MS的系统是江郎才尽,再难突破了3

而在微软系统的代代更新中,最苦命的算是一直追随MS的程序员了,掏着升级系统和硬件的银子不说,就连自己费尽力气学到的知识,从BASIC、到MS-DOS、到VC++、到MFC,到ASP,到ASP.NET,到C#,也随着微软系统的更新换代灰飞烟灭了……殊不知,*nix下的程序员,纵历风雨,我心永恒。靠着vi+gcc,我就能闯天下。

2 *nix文件系统的优势

相较Windows,*nix的文件系统相对要规范的多,究其根源,在于*nix有一条非常重要的设计哲学,那就是:Everything in Unix is a file:

  • linux的文件系统是单根的,具有一种逻辑意义上的美感。可能有人会问,如果我们新插入一个移动硬盘,我没有盘符,怎么访问?这就是Windows的惯性思维。在Linux中,我们可以随意创建一个目录,然后通过mount命令将起挂载在这个目录点上。事实上有一个叫做fuse4的东西,允许你mount你想得到想不到的很多东西:
    • 见过PB级别的文件系统吗?我见过,在百度,我们通过hadoop的一个fuse模块,将几千台机器组成的PB级的HDFS文件系统挂载到单机硬盘节点上,对外提供ftp服务5
    • 你可以通过SSH挂载远程机器的文件系统6
    • 你还可以挂载一个ftp到本地系统7
    • 你甚至可以将你的Gmail挂载过来,当本地磁盘用8
  • linux的文件命令和文件存放是很有规律的,稍微学习下,你就会知道/bin、/etc、/usr、/home目录的作用,并且,在所有的*nix环境下,都有这些统一规范的目录。
  • linux为每个用户建立一个单独的/home/user主目录,所有用户相关的配置都存放在这个目录下,结合linux下所有几乎所有配置文件都是纯文本这样的特点,带来的好处就是极其简单实用的用户数据迁移过程 ——当你系统崩溃重装的时候,只需要保留/home分区,不用做太多的配置,一切都在:
    • 原先的软件快捷键几乎保持不变
    • vim和emacs的配置不变
    • 甚至连桌面的壁纸都不会变
  • linux中大量采用纯文本的配置文件,相比较于中央集权的注册表方式管理的配置文件, 纯文本文件的好处在于通用性、直观性、可见性和易读性 。虽然文本配置格式多样,但是你已然可以使用你最擅长的工具(哪怕是OpenOffice也行)来查看甚至修改配置文件,并且可以根据个人需要讲这些配置文件放到诸如bitbucket这类SCM系统里面;而对于Windows的注册表,一旦损坏,除了少数几个专有的工具,你就只能双手一撒,重装系统,或者给微软打电话了。

3 一些个人的关于文件组织和管理的Tips

以上,都是关于Windows不好的吐槽以及*nix好的赞扬,没兴趣的看客可以直接忽略,因为下面的内容才是本篇文章的核心所在。

我曾经无数次在学校教室、宿舍和公司的办公桌上,看见各式人等电脑中,一个可怜单薄的桌面上,存放着从txt、doc、docx、ppt,到jpg、png,到rm、mkv,到rar,到"xxxx的快捷方式"等等五花八门的没有八十也有一百个之多的文件。那感觉就像是看到了五湖四海的人们睡到了一张星级宾馆的床上,令人心头一紧、后背发凉。我甚至可以感觉得到他们盯着屏幕、挪着鼠标、眯着双眼寻找某年某月某日的一份word文件的焦躁与辛苦。我甚至还能联想到,这样的人在生活中也多数是邋遢的,他们会随手丢弃东西,经常翻箱倒柜的去寻找某个久远的日子里的一个小物品。

不是这样的,正确高效的文件组织管理绝对不该是这样的。我相信,即便你没有洁癖,但是看着电脑桌面上那么一坨乱糟糟的东西,心情也会不好的。所以我的电脑桌面上向来都是清清爽爽,一个图标都不放。我个人总结了一些粗浅的文件组织管理的小技巧,经过两年多的实战,效果还是不错的:

3.1 规范同一的文件命名

  • 尽量使用小写的文件命名
  • 尽量使用英文单词命名(良好的英文水平是优秀Coder的必要条件)
  • 如果文件名是多个单词,用下划线_将多个单词连接起来,千万不要留有空格,对脚本化的文档处理非常不利

3.2 良好和谐的目录结构

  • documents:主要存放各种文档,包括但不限于各种工作简历啊、考试进度啊、学校通知啊,诸如此类,定期删除过期文档,将有学习价值的文件转移到study文件夹下
  • downloads:主要存放Firefox等Internet软件的下载资源,有价值的资源及时转移,没有价值的资源及早删除
  • media:主要存放各种多媒体资源,重点用户轻松娱乐,三个子文件夹:
    • musics: 存放喜欢的音乐,将这个文件夹导入Amarok或者你喜欢的播放器软件即可
    • pictures:主要存放个人照片和网上的一些有趣有意义的图片
    • videos:各种电影,我非常喜欢看电影哈,可惜电脑硬盘空间不够,加上我决定要逐步完善自己的版权意识,所以存量有限
  • mnt:用于临时挂载一些U盘的目录
  • programming:用于自己学习编程的目录,我现在用BitBucket管理自己的代码,每个bitbucket上的repository都对应于这个文件夹下的一个子目录
  • software:用于存放一些有用的软件,其实这个没啥必要,因为linux主流distribution的软件库一般都非常完善,只要有好的网络环境,想装什么软件(哪怕同时装几十个软件)只是一条命令或者一次鼠标点击的事情
  • study:存放自己有电脑以来收集到的各种学习资料和自己大学里的各种作业、ppt、文档等等,分门别类,定期整理删除
  • tmp:我自己的tmp目录,用于临时创建一些不重要的测试文件,常见场景是我需要测试一些C语言或者TeX或者Python里面的某个特性,因此临时创建一个小文件,编译运行下,看看效果
  • tools:用于存放自己写的一些系统管理的小工具,比如我自己写的SSH翻墙脚本、设定笔记本电池充电阀值的脚本等等

4 接下来

按照原本的写作计划,在本篇文章的基础之上,我将在接下来的三篇文章中谈到三个主题:

  • Just Find it: Findutils,介绍*nix的小工具,帮助你在文件的海洋中傲游穿梭,包括但不限于:
    • 如何迅速而准确的定位你想要的寻找的文件
    • 如何迅速而准确的在历史的目录树中进行切换穿梭
    • 如何仅仅借助Shell工具,在一个Open Source的代码库中,寻找一个变量的出现位置,并且能够找出到底是哪个文件包含了这个变量的使用
    • 如何删除某个目录下所有以.bak结尾并且修改时间在n天内的所有文件
  • 细谈文本配置,文本配置是"Everything in Unix is a file"的一个重要体现,对应于Windows的注册表,文本化的配置文件大大简化了*nix系统管理工作,这篇主要会介绍:
    • *nix系统中一些重要的配置文件
    • 以及相关的配置文件的配置格式
    • 配置文件跨系统的迁移和保存
    • 以XML/JSON/YAML为例介绍下常见的几种文件配置格式,有可能的话,初步介绍下Lisp中"Code is Data"的扩展概念
  • Shell之道,初步介绍下*nix Shell编程的一些入门要点,并直接转入Shell编程的精华——管道。可能的话,会在此基础上展开探讨下进程间通信的一些思考。

敬请期待!

--

Footnotes:

1 参考Operating Systems & Commands,这篇文章详细对比了*nix和Windows两种系统之间的差异。

2 参考《软件随想录》(阮一峰译),P65,《在耶鲁大学的演讲》。

3 以上言论,多有戏谑成分,众位看官一笑而过,切莫当真。

4 关于Linux中FUSE模块的设计思路,可以参考徐宥写的编程珠玑番外篇-K. Plan 9 的故事(修订版),徐宥写的这一系列文章水平很高,趣味盎然,强烈推荐。

5 参考MountableHDFS

6 参考sshfs

7 参考curlftpfs

8 参考GmailFS

 

闲谈MapReduce(1): Hadoop初探

1 缘起

MapReduce是这几年IT界很热的一个名词,从某种意义上讲,MapReduce引领了当代海量数据处理的趋势和潮流。与IT界的其他名词一样,MapReduce听起来也是个很玄乎的名词,MapReduce?Map?Reduce?如果你是一名初级Coder,那么你可能从某处知道,Map的翻译是映射,Reduce的翻译是归约。MapReduce就是映射归约,是一种数据并行处理的一种编程模型。如果很不幸,你不是一名光荣的Coder,只是中国网民大军中的五万万分之一1,那么没关系,MapReduce离你并不遥远,有一个名词你一定很熟悉,那就是——云计算。关于云计算,互联网上有一个经典笑话,“中国一留学生去美国打工的当过报童,不带计算器,习惯动作抬头望天时心算找零。顾客大为惊讶,纷纷掏出计算器验证,皆无误,也抬头望天,惊恐问:“云计算?”不过云计算的真正含义,用工程师的语言,准确地定义,应当是“超大规模的,可扩展的,低成本,但是高可靠性的服务器集群系统”2

从大的层面上来讲,云计算并不仅仅是MapReduce,MapReduce只是云计算的一个技术性开端,或者说,是互联网的发展需求推动技术的发展进步,最后由Google临门一脚创造出来的一种处理海量数据的并行编程模型。真正的云计算包含诸如IDC建设、海量存储、网络规划、商业模式、网络安全等等诸多技术的难题,还有很多被一些所谓的专家炒作起来的社会意义。不过本系列文章并不打算探讨这些过于宏大的主题,我本人也没有这样的水准和资格来说三到四。本系列文章的目的只有一个,那就是搞明白,MapReduce中的Map和Reduce,到底源自何处3

我第一次听说MapReduce这个名词,是在2010年9月,那时百度来浙大宣讲,顺带开了一个技术讲座,主讲人徐串曾是Google中国编程挑战赛冠军。当然,讲座内容我是听不懂的,随心记下来的几个技术名词,至今为止,还能记住的,只剩下MapReduce了。后来面试百度运维部,期间和面试官聊到我暑期实习在华数淘宝做的一个视频转码入库系统,面试官大概觉得这个系统有点分布式的意思,因此题目结束的时候给了我一个建议,就是让我学习下MapReduce。再后来,阴差阳错,我进入了百度的分布式运维小组学习Hadoop运维,学习MapReduce就成了一个身不由己的任务。

在百度的半年,我初步接触了大规模Hadoop集群(3000个节点的规模)的运维工作。但比较讽刺的是,运维Hadoop集群的我,自身并没有写过多少真正的MapReduce程序,对Hadoop的理解也浅尝辄止。而我也始终没有搞明白,好端端的一个程序,为什么要按照MapReduce这样别扭的模型重构运行?

大概是看了Paul Graham的《黑客与画家》后,我开始正式认真学习Lisp这门语言,至今已有小半年时间,这期间我利用业余时间,和最近一个月的休假时间,基本上看完了Paul Graham的《ANSI Common Lisp》《On Lisp》《SICP》太难,我穷尽脑力至今也只窥得前面三章,做了100道习题左右,不过即便如此,也令我受益匪浅4。半年Lisp的学习让我搞明白了MapReduce中,Map和Reduce的来龙去脉。这个问题我Google了很久,但是始终没有一个满意的答案,现如今,我自己找到了满意的答案。

2 抽象漏洞(兼谈数学和计算机工程)

在正式开始我们的探险之旅前,我们还面临这一个问题,那就是,这次探险的必要性在哪里?既然MapReduce已然为我们提供了成熟的理论编程模型,Hadoop生态圈也给我们提供了一整套成熟的工程实现,我们为什么还要纠缠这些学究般的历史问题?我的解答是, 一个学科的历史往往就是这个学科的本身 。无论是一门编程语言、编程范式、编程模型,或者IT业的任何一项新技术新名词,在学习的过程中,一定要搞明白:

  • 它解决了什么样的技术问题?当时的历史背景是什么?还有没有类似的(可能没有流行起来的)解决方案?
  • 它的引入带来了哪些新的问题?
  • 它的优点是什么?什么样的问题一定会手到禽来?
  • 它的不足是什么?什么样的问题是它解决不了的?

这就好比解一道很难数学题,如果光告诉你一个正确的数字,那么这个数字对你来说一点意义都没有;如果进一步,告诉你标准的解题过程,那么你可能会对这个题目有一个粗浅的认识;如果有那么一个白痴,不但告诉你正确的答案和解题过程,还把他的演算纸送给了你,并热切地给你讲解他在解题过程中碰到了哪些问题和陷阱,是怎样解决怎样解决问题怎样规规避这些陷阱的,那么你对这道题目的理解则会大大加深,日后再碰到同样类型的问题就会轻车熟路,手到拈来。 从某种意义上而言,一个完整的解题的探寻过程才是一个题目所具有的全部信息价值,扔掉这些而仅仅记住一个解题结果或者一个标准的解题证明,无疑是买椟还珠 5 。但是比较可悲的是,计算机是一个年轻的学科,所以专门讲述计算机历史的书籍并不像数学史书籍一般汗牛充栋。

从另一个角度上讲,计算机和数学的都是一座不断分层的抽象大厦。数学是从基本的整数,到数系的扩充,到微积分的诞生,到非欧几何等等宏大的诗篇;而计算机则是从最基本的与非门,到bit、byte、word,到汇编、c、高级语言,到设计模式、分布式等等现代工业的大厦和基础。“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决6”,不过很不幸, 计算机的抽象和数学的抽象有一个本质的不同,那就是计算机的抽象是有漏洞的 ,这就是抽象漏洞法则:All non-trivial abstractions, to some degree, are leaky。在数学领域,我们从来不用担心说某个定理“因为空调故障的原因宕机了,或者因为内存吃紧运行特别缓慢,似乎是发生内存泄漏了”,等等诸如此类的各种各样令人头疼的问题。这条法则深刻的影响了计算机软件和数学定理的生产过程——在计算机中,我们不可能找到一个能困惑世间智者358年的谜7;在数学领域,我们也不可能找到一个耗费人类5000万人年人力的定理8如果说,基于抽象的数学,考验的是人类大脑思考深度的极限,那么同样是基于抽象,并且脱胎于数学的计算机工程,挑战的就是人类大脑思考广度的极限 ——软件工程中瓶瓶罐罐的细节太多了,所以大凡软件开发,走的都是兵团作战的策略;而数学就不一样,“10个产妇无法在一个月内生出孩子9”,数学领域中辉煌定理的产出,往往依靠少数几个,甚至单个天才数学家的苦苦思索和灵感涌现。

3 Let's Go

以上,废话了这么多,所要强调的无非就是,了解MapReduce的来龙去脉,对于写出更好的MapReduce程序,甚至将来拨开层层抽象,解决MapReduce的底层问题,乃至改善MapReduce,都是大有裨益的。不过,在正式踏上我们的探险旅程之前,我们需要检查一下手头的“装备”是否合格,很简单:

  • 你需要一台*nix系统,最好是GNU Linux,苹果也行,如果实在不方便,Windows下装个Cygwin也还能凑合;
  • 你需要有一定的编程经验,包括但不仅限于C、Java、Bash、Python,如果再对Lisp或者Scheme有一定了解就更好了(别急,本系列文章对Lisp做一个简要的介绍);
  • 你需要了解一些常见的*nix软件开发工具,包括但不限于Vim的使用、Ant和Make构建工具、Git和SVN版本控制软件;
  • 你需要对POSIX系统标准有一定了解,包括但不限于*nix的文件系统结构、用户属组、文件权限、管道等等。

Now, Let's Go!

4 Hadoop

行文至此,相信众位读者已经知晓了云计算的一些基础概念,最起码知道了所谓Google技术的三驾马车是什么,如果能看过Hadoop代码中WordCount的例子并能看懂的话,那你简直是太天才了。为了保证我们的探险顺利进行,我们需要一套开源的MapReduce平台实现来验证我们的学习成果,Hadoop是不二选择。关于Hadoop本身有太多太多的资料,因此我在这里就不再劳心劳力的copy别人的劳动成果了。推荐以下三本书,作为Hadoop的入门:

我们所要做的,就是在本机的*nix系统下,搭建一个demo的伪分布式运行的Hadoop平台。我采用的Hadoop版本是Hadoop 0.20,这个版本比较稳定,最新的Hadoop 1.0添加了很多新的特性,这些特性对于我们的探险并没有特别的作用,而且我也不甚了解。当然,本文的重点并不是Hadoop,所以我并不会带你去分析HDFS的源代码,告诉你如何打Patch(我也不会,嘿嘿)。本文的重点在于MapReduce的来龙去脉。

  • 首先本机*nix上存在jdk和ssh,并找到相应的$JAVA_HOME
  • 首先是建立本机用户到自身的ssh信任关系,步骤大致如下:
➜  ~  ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/lox/.ssh/id_rsa): 
/home/lox/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/lox/.ssh/id_rsa.
Your public key has been saved in /home/lox/.ssh/id_rsa.pub.
The key fingerprint is:
19:3f:55:84:99:d2:1e:c6:42:d0:39:6f:3e:83:84:21 lox@lox-pad
The key's randomart image is:
+--[ RSA 2048]----+
|        .+.+ =o  |
|      E . * O.   |
|       ..o B..   |
|        .+..+    |
|        S.o+     |
|          ..+    |
|             o   |
+-----------------+
➜  ~  cp .ssh/id_rsa.pub .ssh/authorized_keys 
➜  ~  chmod 700 .ssh 
➜  ~  chmod 600 .ssh/authorized_keys 
➜  ~  ssh lox@localhost
  • 下载hadoop v0.20,解压缩到一个目录,我的目录结构如下,其中tmp/hadoop-data作为hdfs数据存放目录(包括伪分布式运行的namenode和datanode的数据),tmp/hadoop-v20作为$HADOOP_HOME
➜  ~  tree -L 1 tmp/hadoop-data tmp/hadoop-v20 
tmp/hadoop-data
tmp/hadoop-v20
├── bin
├── build.xml
├── CHANGES.txt
├── conf
├── conf.origin
├── conf.pseudo
├── conf.standalone
├── contrib
├── docs
├── hadoop-0.20.3-dev-ant.jar
├── hadoop-0.20.3-dev-core.jar
├── hadoop-0.20.3-dev-examples.jar
├── hadoop-0.20.3-dev-streaming.jar
├── hadoop-0.20.3-dev-test.jar
├── hadoop-0.20.3-dev-tools.jar
├── ivy
├── ivy.xml
├── lib
├── LICENSE.txt
├── logs
├── NOTICE.txt
├── README.txt
├── src
└── webapps
  • 修改hadoop的配置文件分别如下:
    • hadoop-env.sh,重点修改下$JAVA_HOME,指向SUN JDK或者OpenJDK的目录,Hadoop官方建议采用SUN(现在是Oracle啦)的JDK。
    • core-site.xml
    • hdfs-site.xml
    • mapred-site.xml
hadoop-env.sh

...
...

# The java implementation to use.  Required.
# export JAVA_HOME=/opt/java
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk

...
...
core-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>fs.default.name</name>
        <value>hdfs://localhost:9000</value>
    </property>
    <property>
        <name>fs.trash.interval</name>
        <value>1440</value>
    </property>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/lox/tmp/hadoop-data/tmp</value>
    </property>
</configuratione>
hdfs-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.name.dir</name>
        <value>/home/lox/tmp/hadoop-data/name</value>
        <final>true</final>
    </property>
    <property>
        <name>dfs.data.dir</name>
        <value>/home/lox/tmp/hadoop-data/data</value>
        <final>true</final>
    </property>
</configuration>

mapred-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>mapred.job.tracker</name>
        <value>localhost:9001</value>
    </property>
    <property>
        <name>mapred.tasktracker.map.tasks.maximum</name>
        <value>5</value>
    </property>
    <property>
        <name>mapred.tasktracker.reduce.tasks.maximum</name>
        <value>5</value>
    </property>
    <property>
        <name>mapred.child.java.opts</name>
        <value>-Xmx512m</value>
    </property>
</configuration>
  • 启动hadoop,如果能用Hadoop FS Shell做一些常规的mkdir和ls操作,Hadoop搭建就算大功告成了:
➜  ~  hadoop namenode -format 
12/02/15 00:07:23 INFO namenode.NameNode: STARTUP_MSG: 
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = lox-pad/127.0.0.1
STARTUP_MSG:   args = [-format]
STARTUP_MSG:   version = 0.20.3-dev
STARTUP_MSG:   build = http://svn.apache.org/repos/asf/hadoop/common/tags/release-0.20.2 -r 916569; compiled by 'lox' on Wed Nov  9 23:40:01 CST 2011
************************************************************/
Re-format filesystem in /home/lox/tmp/hadoop-data/name ? (Y or N) y
Format aborted in /home/lox/tmp/hadoop-data/name
12/02/15 00:07:25 INFO namenode.NameNode: SHUTDOWN_MSG: 
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at lox-pad/127.0.0.1
************************************************************/
➜  ~  start-all.sh 
starting namenode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-namenode-lox-pad.out
localhost: starting datanode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-datanode-lox-pad.out
localhost: starting secondarynamenode, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-secondarynamenode-lox-pad.out
starting jobtracker, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-jobtracker-lox-pad.out
localhost: starting tasktracker, logging to /home/lox/tmp/hadoop-v20/bin/../logs/hadoop-lox-tasktracker-lox-pad.out
➜  ~  jps   
21061 JobTracker
20852 DataNode
21255 Jps
20977 SecondaryNameNode
20764 NameNode
21156 TaskTracker
➜  ~  hadoop fs -mkdir /tmp/this-is-a-test-dir
➜  ~  hadoop fs -ls /tmp
Found 1 items
drwxr-xr-x   - lox supergroup          0 2012-02-15 00:08 /tmp/this-is-a-test-dir
➜  ~  

好了。基础工作已经准备好,在接下来的旅程中,我会初步讲解一下Hadoop的基本概念和使用方法,进而转入Lisp(Scheme)函数式编程的美妙世界,带你逐本溯源,领略一下原生态的Map和Reduce到底是什么模样,并且会顺带谈到一些我在Lisp学习过程中领略到的别样风景,包括但不限于Java的反射、序列化等一些高级特性,XML、JSON的数据语言的特性特点等等。敬请期待!

--

Footnotes:

1 第29次中国互联网络发展状况统计报告显示,2012年初,中国网民共计5.13亿。

2 关于这个定义的出处可以参考弯曲评论上一篇非常好的关于云计算的科普文章“云里雾里云计算”,本文不打算探讨云计算的社会意义、产业变革、安全等过于宏大的主题(其实我对这些一点都不了解)。

3 MapReduce的第一篇论文"MapReduce: Simplified Data Processing on Large Clusters"曾写到:"Our abstraction is inspired by the map and reduce primitives present in Lisp and many other functional languages."可见,MapReduce的思想来自于古老的Lisp语言。

4 广告一下,在我有限的阅读经历中,《SICP》是我读过的计算机书籍中最棒的一本,没有之一。如果能认真做完这本书里面的356道题目,绝对会让你对编程本质的理解有一个脱胎换骨般的提高。这里有我个人的部分习题解答代码和学习笔记。

5 关于这一点,刘未鹏的《知其所以然》系列文章里有更好的解读,我就不再重复了。

6 参考程序员的自我修养

7 参考费马大定理 : 一个困惑了世间智者358年的谜

8《Unix编程艺术》的序言里的脚注:“从1969年到2003年,35年世间并不短。以这期间众多Unix站点数量的历史曲线来估算,人们在Unix系统的开发方面投入了约5000万人年”。

9 这原本是Brooks's Law的一种观点。

 

打造高效的工作环境(1):Why Windows Sucks

1 缘起

这两天我的ArchLinux系统碰到了一个十分诡异的问题,就是电脑无法待机、关机,也无法重启,更令人拍案叫绝的是,电脑在关机重启的过程中,当硬盘停止转动后,整个系统就Hang住了,而屏幕终端还在,只是不再响应任何请求。解决这个问题的唯一办法就是强制关机,但是这种方法实在有失水准,有伤大雅。在尝试了增删内核模块、更新驱动的等多种方法后,我终于在ArchLinux BBS上找到了解决方案

Google了几个来回,再看一些关于操作系统IT历史的八卦,半个下午就耗掉了,从某种意义上来说,这是在浪费时间。而事实上,如果不算辞掉工作更换电脑被迫地系统调优的那次,我已经至少半年没有进行过OS和软件层面的Tweak工作了。这其中的缘由,大概是由于电脑折腾久了,就会折腾出一套适合自己口味的解决方案,这套解决方案,就是接下来一系列文章的主题——打造高效的工作环境。

打造高效的工作环境,Wow,多么宏大的一个主题啊,不过我见识有限,就这个话题,我只能谈谈电脑相关的知识,和我个人的理解,我不会讲到:

  • 桌上要放几盆草
  • 要不要听轻音乐
  • 开放式的办公空间

等与电脑毫不相关的话题。除此之外,还有一个前提,那就是我的文章主要针对Linux和Mac用户,对Windows用户的参考价值不大。

Why Not Windows?Why Linux?Why Mac?

我100%地相信,在中国,100%的人是通过Windows系统进入电脑的世界的,我也是。但是我也100%地相信,如果你是一个程序员Geek,用Linux或者Mac,会让你的生活变得更美好;如果你只是一个普通的电脑使用者,用Mac或者Linux,至少不会让你的生活变得更差。

说到这里,很多人会跳出来争辩,多数论调是:

  • Linux的驱动如何如何不好
  • Linux的桌面如何如何烂
  • Linux下的软件如何如何不完善
  • Linux下的游戏如何如何匮乏

我的回应是,对于一件事情,对于一件事情,我认为,人的认知有四种状态,分别是:

  • You know you know.
  • You Know you don't know.
  • You don't know you know.
  • You don't know you don't know.

"You know you know"说的是类似于1+1=2这类的常识,首先是你知道"1+1=2"这个知识点,进一步讲,你知道"1+1=2"这个知识点是一个认知事实,而你自己对于这个认知事实也是知晓的,所以归结下来是"You know you know",说的通俗点,就是“你是知道‘你本人是大学文化,所以会算1+1=2’这个事实的”。

"You know you don't know"说的是我这样的Coder,知道自己水平不够,功力尚浅,不懂得AI,不懂得数据库,不会算法,但好在还有自知之明,所为“吾生而有涯,而知也无涯”,"You know you don't know",学吧,学到白头学到老。

"You don't know you know"的情况很少见,这种情况常见于某些天赋异禀而不自知的人,就好比练成了九阳神功的张无忌,明明已经武功盖世,却不自知,见到阿猫阿狗也会心底害怕。

"You don't know you don't know",这句话用来形容那些狂妄自大目中无人之辈真是再合适不过。不过对于常人,我们能否从这句话中得到一些启示呢?当然可以。 事实上,小到一个生活常识,大到一门学科领域,如果你对它不甚了解,甚至完全不知,那么这种"You don't know"有很大的概率是"You don't know you don't know",而不是"You know you don't know"。仔细想想,这句话揭露了一个可怕的事实,那就是,随着知识爆炸的进行,人类在自己探索创建的辉煌文明成果面前,变得越来越无知;另一方面,人类的的知识再以指数级别的速度增长,但是培养人才的方式却没有本质的进步,这也就意味着现代人才的培养会越来越难1

扯远了,说了这么多,就一个意思,在你对一个领域、一个知识有充分的调研学习之前,审行慎言。这也是“为什么上帝给了我们两只耳朵却只给了一张嘴巴2”。我个人曾经有过3年的用Linux做主力桌面的经验,其中有50%的时间是整个电脑上只有一个Linux系统,其余双系统并用的时间,98%的时间也是在Linux上,所以对于Linux桌面的情况,我还算有些发言权:

  • Linux的驱动确实是一个软肋,不过情况较2000年左右Redhat 9.0横行的年代已经改善了很多,在这方面,Ubuntu绝对是一个集大成者,现在已经很少找到装上Ubuntu驱动不能用的电脑了,其余的发行版,经过简单配置,也完全可以搞定驱动问题。
  • Linux的桌面已经非常完善了,Linux 并不是只有一个黑黑的令人敬畏的终端。KDE 4.8的设计和整合已经非常完美,各种软件的集成性比Mac有过之而无不及。
  • Linux下的软件如果不比Windows多,至少不会比Windows少。很多优秀的软件诸如Amarok、Digikam、Emacs等等,都是以Linux为首要支持平台的,甚至有的软件只支持Linux,很多工业级别的软件,诸如Hadoop、MySQL、Apache等等,无一不是以Linux为最佳运行平台。
  • Linux下的游戏比较匮乏,这点是不争的事实。

So,说了这么多,信也好,不信也罢,接下来谈谈:

2 Why Not Windows?

作为一个Coder,每次用Windows,我都有一种想要砸掉电脑的冲动。所以毕业设计时,在Windows上运行VMware里面跑着Mac OS X,启动Xcode写Win32 Style风格的程序,那可真是痛不欲生、终身难忘的事前黑暗时代。我搞了首打油诗:

  • 文件系统多盘拼,文件命名大小混 :Windows是多根文件系统,每个根称作一个盘,而*nix的系统是单根文件系统,新来磁盘只需要在文件系统树上新增个挂载点即可;Windows文件的命名和组织从来没有任何规律,而*nix的文件系统则有一个统一的FHS标准,并且,在Linux下,几乎所有的文件名都是小写字母,并且不含有空格,这对脚本批处理是一个大大的方便之处。
  • 权限控制小烦躁,命令终端很废柴 :Windows下的文件权限很困惑,我从来没搞明白,好像获得一个文件的某种特殊权限,还要去点击属性窗口;用户权限就更加混乱了,一个Administrator,后来Vista和7又加入了貌似“家长模式”等等,太乱了;*nix下的权限控制则非常简单明了,三条命令如chmod, chgrp, sudo就可以全部搞清楚;Windows下的传统cmd.exe简直废柴的不能再废柴了, 谁能告诉我为什么cmd窗口无法最大化? 真不明白这到底是哪门子的设计。
  • 弹出窗口满天飞,后台进程到处藏 :在Windows下还有一点非常让我难受,就是无论是搜狗输入法、迅雷下载,还是QQ、360等,这些软件无一例外,都有一个爱好,就是首先把自己加入系统的启动项,然后呢,在你写代码看片练葵花宝典乾坤大挪移到了关口的时刻,“啪!”的一下给你整几个弹出窗口,放几条八卦新闻……还有那废柴的任务管理器,从来都是杀不掉进程,自己倒先莫名其妙地卡死了,哪里像*nix上的killall -9,手起刀落,快刀展乱麻,痛快痛快。
  • 一家独大搞垄断,格式兼容已败北 :在格式兼容方面,从来都是*nix下的软件想尽办法兼容Windows的软件,但是Windows一家独大,对于兼容别的系统的软件,从来不屑一顾,举例?OpenOffice,ntfs-3g,数不胜数啊。
  • 病毒木马禁不止,杀毒软件赚钱忙 :每次我去帮别人修理Windows系统,别人的第一想法都是让我先替他们杀杀毒,可见,病毒和Windows故障一样,在人们的心中难解难分。
  • 硬盘整理除碎片,系统臃肿找管家 :Windows系统有一个特点,那就是任何系统装好后,都需要“深度优化”,然后才能用得比较舒畅,其中的优化包括但不限于硬盘碎片整理、软件增删、装机必备等等,这也是 为什么各种优化大师、超级兔子、碎片整理等软件“屡禁不止”的原因吧。
  • 万年IE不升级,银行网商耍流氓 :IE 7.0+新增加了多标签的特性,但是呢,这个多标签特性默认情况下是只启动20%的——除非手工指定,否则点开的链接依然是在新窗口中。退一步讲,就算是手工新开个标签页,但是这个空白标签页的打开简直比乌龟还慢,至少要5秒钟,正是让人“屎可忍,而尿不可忍啊”。至于万年不变的IE6,已经国内众网商网银流氓们的ActiceX插件,我已经无力吐槽了,历史会证明,一个不支持跨平台浏览器的银行网商,绝对会是软件史上的一个笑话,或者说,这是中国银行业的奇耻大辱。
  • 多情自古空余恨,聪明反被聪明误 :Windows下的很多软件都喜欢自作聪明,典型例子就是Microsoft Word。且不说各种软硬回车,最简单的一个列表,回车之后默认又是一个列表项,但是如果我想新开段落呢?很多人就不知道怎么办了,于是就各种暴力手段地搞排版,排出来的东西,可想而知。我只能说,这种自作聪明,有时候不是真的聪明,是蛮横的自作主张,是对用户意志赤裸裸的强奸啊。

个人吐槽到此结束,详情请进一步参考:

3 Save your life

在接下来的系列文章里面,我会分门别类地介绍我在Linux桌面使用上的一些日常经验,分享自己的一些心得。这些经验之谈对于刚刚踏入Linux大门的同志,以及对于初级Mac用户,甚至部分喜爱折腾的Windows用户,都有很大的参考价值。我觉得,在信息时代,电脑将伴随着我们的一生,高效地使用电脑,就能够在更短的时间内处理更复杂的事情,从而为自己节省出宝贵的时间,去做更有意义的事情,这是一种正向循环;而如果每天纠结于杀毒、木马、弹出窗口、软件破解,则会使你的思维受阻、降低你的工作效率,这是一种负向循环。

这一系列的读者群将以Linux用户为主(重点是Coder),高级Mac用户可以作为参考,对于Windows用户,理解起来可能会有些困难。不过话又说回来,“不经一番寒彻骨,哪得梅花扑鼻香”。我给自己定下如下两个目标:

  • 在键盘上舞蹈
  • 思维不会受阻

至于主题,我初步想了分为如下几个

  • 高效的文件管理
  • Just Find it:Findutils
  • 细谈文本配置
  • Shell之魂:管道
  • Screen:it not a screen
  • Zsh:终极Shell
  • VIM:键盘上跳舞
  • CLI Tools:把玩终端
  • 时光机:版本控制
  • 抛弃Office:LaTeX
  • KDE系列:
    • Kwin
    • Dolphin & Konqueror
    • Konsole & Yakuake
    • Krunner

敬请期待!

Footnotes:

1 阮一峰博客:什么是博士

2 这是西方的一句谚语,寓意在于告诫人们要多聆听,少说话

 

再见,2011

还有两个小时就要踏上去往哈尔滨的旅程。回首2011,颇多感慨。这一年我23周岁,从16岁离家求学至今,这是第七个年头。这一年的标志性事件就是我开始正式从学校走向社会,实现经济独立。其余的一切,基本上都是围绕着这条主线在转。

1 学业

2011年上半年的主题就是学业了。具体说来,就是我为了所谓一个学位的虚名, 每天殚精竭虑,为了最后的几门考试和毕业设计奔命不息。3月1日回校,7月5日拿到毕业证,6日离杭。这期间混过10+门课,外加一门毕业设计。至此对中国的学术体系彻底失望,再也不想回头。

临毕业之际,许多人邀我参加各种活动,除了少数不得不去的几个,诸如旅行者毕业散伙饭,其余则一律回绝。有些人散去之后,终究不会再见,索性随缘,何必再添一场饭局、游戏,徒增无趣?

2 工作

2011年下半年的主题是工作。我所在的小组负责百度Hadoop集群的运维工作。面对着15000+的机器资源,如何更合理的利用、管理这庞大的资源,对于我们是一个巨大的挑战。

其实纵观业界,开源的Hadoop生态圈已成,各种周边工具诸如chukwa、ganglia、 nagios等已经比较成熟,但是如运维这些成套的系统,每个公司却有每个公司 的不同做法了,这也是一个IT公司安身立命、独立于世的重要资本。

开始的时候,由于新人入职,学习培训,加上组内的照顾,自觉工作十分有趣。 到10月份,在真正接手集群的时候,事情陡然增多,各种会议沟通、预算报表让 我十分疲惫,加上部门人员变动,新来的老大和我脾气并不对味,因此让我萌生了要走的念头。

Anyway,在百度,我见识到了巨型公司运营的基本流程,接触到了浩瀚如海的机器资源以及相伴而来的各种故障,并有幸和牛人们一起并肩战斗(虽然我是为他们提供底层服务的……),这一切的一切,让我受益匪浅。

两年内,从我正式开始认真学习计算机开始,我从一个小破烂的实验室,到淘宝的实习,再到百度的分布式运维小组,平台越来越大。只不过,随着平台的扩大, 其所带来的沟通成本也会倍增。在百度,我平均每天发十五封邮件,每天花3-5个小时在聊天工具上,每周至少开3个会,每周至少写两份文档(包括周报), 这一切的一切大大得压缩了我学习底层技术、编写代码的时间。所以我决定离开,嗯,在年后。

3 经济

2011年的一个重要人生里程碑是我第一次实现了经济独立,并且在年底12月份初的时候成了一个所谓的“万元户”。如果说,学生时代,是有钱没时间,那么, 工作时代,就是有时间没钱。我希望,在下一个七年,等到我三十岁的时候,能够实现一种高层次的财务自由。

说到底,我依旧是个俗人,逃脱不了俗世的纷纷扰扰。所谓自由,有的时候,不是自己想干什么就可以干什么,而是自己不想干什么的时候,就可以不干什么。

4 专业

2011年,我在专业技能的提升方面并没有达到我的预期,但是已经做到尽心尽力。

2011年下半年的专业关键词是Lisp。在8-12月4个多月的时间里,除了工作上的需要,偶尔分神去学习下Java和Hadoop的相关知识,剩余的大部分精力都放在了Lisp的学习上。

学习Lisp让我发现了编程语言的另一个世界,正如学习Linux让我发现了操作系统的另一个世界。我在Lisp身上找到了很多以前我学习的编程语言不曾体会到的东西,诸如交互式的编程环境、简单和谐的S-expression、强大的macro,等等等等。我觉得,通过lisp的学习,我开始逐渐登堂入室,窥得计算机科学的本质。 我开始理解了很多以前不曾理解、似是而非的概念,诸如code is data、序列化、 xml与ant,我现在能以lisp的观点重新审视MapReduce编程模型,而SICP的前两 章内容,更让我领略到了combination和abstraction的绝妙组合。

2012,我希望我在Lisp学习上的道路上更进一步,完成所有sicp的习题,完成 《On Lisp》的阅读和《PAIP》,并且深入学习计算机领域的另外一本经典书籍——《深入理解计算机系统》。我觉的SICP和CSAPP代表了计算机科学的两个方向,前者讲的是计算的本质,也就是编程语言和数学,后者讲的是计算机,也就是编程语言的底层支撑。

5 阅读

2011年我依旧保持着优秀的阅读习惯和进度,即便是在百度繁忙的工作之余,我 也会保持每周20-30个小时的独自阅读时间,我以此为荣,并以此作为我以后安身立命、闯荡江湖的资本。我非常享受这闲暇的时光,再也不用为了考试、分数去阅读,我可以递归的去阅读自己感兴趣的任何资料,从scheme,到lisp,到 emacs,到ai,所读无穷、所识无尽,所乐无限。

6 观影

2011年我的观影活动极其频繁,整整一年,我大概看了不下170部电影和电视剧, 还不包括重温以前的一些经典片诸如《暗算》、《亮剑》等等。

重点推荐:

  • 吴晓波《激荡三十年》
  • 俞敏洪《创业传记》
  • 《迁徙的鸟》
  • 《猫咪物语》
  • 《谍影重重》

7 旅行

2011年我并没有大的旅行动作和计划。而事实上,除了08年那次杭州到拉萨45天疯狂的旅程,旅行之于我,随着年月的逝去,从一个压抑很久的梦想,逐渐的演变成一种北大教室内静静读书的安详。

我不希望做一个旅游暴发户。所以对于《背包十年》,一笑而过。我觉得,旅行者没有必要把旅行说的那么高尚,这个世界需要一往无前的行者,也需要在各个岗位上日复一日的工人。《背包十年》的作者说白领的工作是“每分每秒都很精 致,但每分每秒都是无聊”,未免太过偏激,对自己的生活太过傲娇,我想,他这辈子大概也不会体会到数学和计算理论的和谐之美了。

8 社交

2011年并没有重量级的良师益友在我的生命中留下印记。一方面是由于我个人逐渐收敛自己的社交圈,将自己有限的时间精力放在一些更值得我去思考、去做的事情上,另一方面也许是年岁增长,并步入职场的缘故。

人生苦短,诱惑太多。我们生命中90%的人,到头来大家不过是一场过客。随遇而安,随缘而乐对于人际关系,该说不的饭局就说不,省下的宝贵时间,留给自己,即便是空虚寂寞,也会让自己更加明了自己不喜欢什么,这就有希望能够找到自己更喜欢的东西。

找到自己喜欢的东西,人生的一切快乐皆来源于此。

9 展望

总的来说,2011年至于我,说不上丰富,却多了一份安定与安详。我想明白了很多道理,也开始明白,生活不仅仅是要做加法,必要的时候,也要做一些减法。 在人生60多年的旅程中,背负太多的东西,只会让你走的更慢。

想下海游泳,就要脱掉身上的衣服;想登高而呼,就要卸下身上的重担。2012, 我来了。

 

Learning SICP: (sqrt 2.0)

接触计算机也算四年有余,对自己的所学所知却毫无信心。回头看了看以前写过的很多文章,诸如配置IDE环境啦、配置Linux操作系统啦、零零散散的小程序啦,等等诸如此类,不成体系,都是在小打小闹。因此我决定,在可以预见的几年内,一方面做好百度份内的工作,赚一点养家糊口的钱;另一方面也要从基础做起,一点一点地夯实自己的技术实力。技术是基础,无论是以后创业,还是继续在程序员的行业里面模爬滚打,扎实的技术都是一个必备的条件。Google的创始人曾经说过,要成为一个企业家,需要“Be an expert in all aspects”,而一个公司赖以生存的基础,除了良好的营销、管理,最最基本的还是需要有能拿的出手的产品,而产品的基础就是技术。所以我从来不赞成“码农没有前途”等等诸如此类的说法,这样说的人,多半自己不是一个合格的码农,又或是对IT互联网本身就没有深刻的理解,信口雌黄罢了。

人类生存于世的一大乐趣就是自己制造工具,能否制造工具也是人类之所以成为万物之灵的根本。而学计算机的一大好处就是可以方便地、随心所欲地制造自己想要的工具,没有想不到,只有做不到,工具的级别取决于程序员的技术能力。譬如Fabrice Bellard就用JavaScript写了一个PC模拟器,可以在浏览器里面跑Linux,而此君的其他作品,诸如ffmpeg、qemu、tinycc,在开源社区几乎是无人不知无人不晓。

学计算机的一大好处就是经典教材诸如SICPCSAPPTAOCP、龙书、虎书等等数不胜数,思忖再三,决定还是以MIT经典的那本SICP开始。关于SICP的具体内容我不再多言,Wikipedia一查便知。让我沉思的两点是,这本书是MIT大一新生学习计算机的第一门课,也就是计算机的导论课程,而这样一门大一新生的导论课程,在两百多页的教材中,确涉及到了图灵机理论、递归算法、lambda算子等等诸多关于编程本质的知识,不得不感叹MIT课程的高质量,同样作为国内高校翘楚的浙江大学,大一新生恐怕还都在背诵C语言各种符号的优先级,还在古老的Turbo C 2.0上写着古老的graphics.h程序呢;第二,这本书长盛不衰几十年,被数百所大学选为计算机系的教材,并且对计算机教育产生了深远的影响,国内有那本教材能够达到这样的境界?谭浩强的?严尉敏的?都不是。除了教材本身,作者的态度,还有配套的相关资料,以及由此推动的深入挖掘和研究才是最重要的。SICP的作者Gerald J. Sussman同时也是Scheme语言的发明人之一。

利用晚上和周末空余的时间,断断续续地看完了SICP第一章的大半部分,还有前面的几段讲义和视频。讲义中的有一个求方根的程序:

#!/usr/bin/guile -s
!#

(define square
  (lambda (x)
    (* x x)))

(define average 
  (lambda (x y)
    (* (+ x y) 0.5)))

(define close-enuf?
  (lambda (guess x)
    (< (abs (- (square guess) x)) 0.001)))

(define improve
  (lambda (guess x)
    (average guess (/ x guess))))

(define sqrt-loop 
  (lambda (G X)
    (if (close-enuf? G X)
      G
      (sqrt-loop (improve G X) X))))

(define sqrt
  (lambda (x)
    (sqrt-loop 1.0 x)))

;;(display (sqrt 2))
;;(newline)

短短几行,几乎涵盖了二分法的精髓。程序就是数据,函数本身可以当数据来操作,本身就蕴涵着深刻的和谐统一的数学美。

其实学习这个东西就像武侠小说里的武功,公式技巧编程语言都是花拳秀腿,对整个学科体系的理解、数学的功底才是精深的内功,是一切上乘武功的根基。由此我又想到一个人的工作的价值。私以为,一个人的价值(也可以说是薪水),是以这个人的不可替代性来衡量的。如果你现在走掉,而你的老板随随便便就能找一个人来顶替你的岗位,那么你做的工作是可替代性非常高的工作,自然薪水也不会太高;反之亦然。

ps:写博客写到一半的时候is-programmer忽然挂掉,所以出现了半截文章。看来我也该考虑考虑租一个独立的虚拟主机或者VPS了。




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee