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

万方学位论文pdf合并脚本v0.1

古人云:天下文章一大抄。整个三月,浙江大学CS开题报告热火朝天,其中各种纠结与不解、各种困惑与混乱、各种word/tex模版纷争,不再详述。23号提交论文,但时至此刻,我刚刚Google Translate了一片水文搞定了外文翻译,修改了学院bug百出的latex模版,搞定了开题报告的格式,至于剩下的3500字,尚无着落,痛苦不堪,心慌也。

废话少说,今天晚上去万方数据库校内镜像下载学位论文,岂知万方这个财主极其抠门猥琐,不但很多有价值的学术论文无法下载,可以下载的论文也是一个zip压缩包,然后里面几十到上百个pdf不等……看一篇完整的学位论文要打开几十个pdf,莫说是我,就是我的x201i,也该累死了……

一个典型的万方学位论文zip压缩包目录结构如下:

lox >>> tree IPTV机顶盒GUI子系统的研究与实现 
IPTV机顶盒GUI子系统的研究与实现
├── default.htm
├── Images
│   ├── ball.gif
lox >>> tree -L 3 -p -N | grep '\[d' 
└── [drwxrwxr-x]  wanfang
    ├── [drwxrwxr-x]  IPTV机顶盒GUI子系统的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   └── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  Tools设计与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于QtEmbedded的图形用户界面移植
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于嵌入式Linux智能手机GUI平台的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于消息通信机制嵌入式GUI的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式Linux图形用户界面的研究与开发
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式uGUI的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式系统轻量化GUI框架的设计与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    └── [drwxrwxr-x]  面向数字家电产品的GUI框架的设计与实现
        ├── [drwxrwxr-x]  Images
        ├── [drwxrwxr-x]  Paper
│   ├── bg.gif
│   ├── folder.gif
│   ├── H.gif
│   ├── I.gif
│   ├── L.gif
│   ├── nfolder.gif
│   ├── ofolder.gif
lox >>> tree IPTV机顶盒GUI子系统的研究与实现 
IPTV机顶盒GUI子系统的研究与实现
├── default.htm
├── Images
│   ├── ball.gif
│   ├── bg.gif
│   ├── folder.gif
│   ├── H.gif
│   ├── I.gif
│   ├── L.gif
│   ├── nfolder.gif
│   ├── ofolder.gif
│   └── T.gif
└── Paper
    └── pdf
        ├── d0447950001.pdf
        ├── d0447950002.pdf
        ├── d0447950003.pdf
        ├── d0447950004.pdf
        ├── d0447950005.pdf
        ├── d0447950006.pdf
        ├── d0447950007.pdf
        ├── d0447950008.pdf
        ├── d0447950009.pdf
        ├── d044795wz.pdf
        ├── d044795zye.pdf
        ├── fm.htm
        ├── index.htm
        ├── iptv.pdf
        ├── left.htm
        ├── ml.htm
        └── single_merged_pdf.pdf

3 directories, 28 files

所有的pdf文档在./Paper/pdf目录下,并且必有一个xxxxwz.pdf和一个xxxxzye.pdf文件,剩下的pdf文件基本上内容顺序和编号顺序一致,但是不排除有页码重叠的状况。

想到的办法就是找CLI工具,将这些pdf合并成一份完整的论文。Archlinux下:pacman -Ss pdf,结合Google,得到几个相关的pdf工具:

  • pdfedit
  • ghostscript
  • pdftk
  • poppler

pdfedit是图形化的pdf edit(编辑)工具,显然不符合CLI自动化处理的要求。而且看界面是基于QT3.x的,编辑功能应该是很强大的。具体可以看pdfedit的Screenshots。不过这与本文无关了。

ghostscript is an interpreter for the PostScript language。linuxtoy给出了一种合并pdf方法,我尝试了一下,但是万方本身的pdf是加密的,直接转换会出现莫名其妙的错误,所以这种方法最终失败。

pdftk是一个十分强大的pdf工具,按照官方的说法,pdftk可以用来:

  • Merge PDF Documents
  • Split PDF Pages into a New Document
  • Rotate PDF Pages or Documents
  • Decrypt Input as Necessary (Password Required)
  • Encrypt Output as Desired
  • Fill PDF Forms with FDF Data or XFDF Data and/or Flatten Forms
  • Apply a Background Watermark or a Foreground Stamp
  • Report on PDF Metrics such as Metadata, Bookmarks, and Page Labels
  • Update PDF Metadata
  • Attach Files to PDF Pages or the PDF Document
  • Unpack PDF Attachments
  • Burst a PDF Document into Single Pages
  • Uncompress and Re-Compress Page Streams
  • Repair Corrupted PDF (Where Possible)

可以用pdftk 1.pdf 2.pdf 3.pdf cat output 123.pdf的方式来合并pdf,但是由于万方pdf的特殊加密,用pdftk合并时,会出现"OWNER PASSWORD REQUIRED"的失败提示。所以成功合并pdf的最关键问题就是去掉万方pdf加密。

幸运的是,我在townx找到了解决方法,感谢万能的Google。剩下的任务,就是Shell Script的天地了。

至于Shell Script,已经好久没有摆弄,很多写法已经生疏,好在半年前在华数淘宝写的脚本还在,打开浏览了下,照葫芦画瓢,倒也没有遇到太大困难。完整的脚本如下:

#!/usr/bin/env bash

################################################################################
# Purpose:  Merge pdf file downloaded from Wanfang dissertation database
#               (http://g.wanfangdata.com.cn/)
# Author:   Xiao Hanyu(xiaohanyu1988@gmail.com)
# Depends:
#       pdftk:              merge multiple pdf files, pdftk is also a useful pdf 
#                               manipulation tools
#       ps2pdf/pdftops:     pdf --> ps then ps --> pdf to remove encryption 
################################################################################

function usage
{
    cat << EOF
`basename $0`: A utility to merge encryted pdf files into one single pdf

Usage:      `basename $0` [Options]
Example:    
            `basename $0` -f "file1.pdf file2.pdf" -o merged.pdf
            `basename $0` -d input_pdf_dir -o merged.pdf
            `basename $0` -d input_pdf_dir
Options:
    -f:     set the input pdf file list
    -d:     set the input pdf directory
    -o:     set the output pdf filename
    -h:     show this help
EOF
}

function merge_pdfs
{
    echo "######## Convert begin!! ########"
    for pdf in $pdf_list
    do
        ## do not use pdf_name = `basename $pdf .pdf` 
        ## since basename will remove the directory prefix of $pdf
        pdf_name=`echo $pdf | sed -e "s/\.pdf//"`

        ## add some animation ^_^
        echo -n "$pdf_name.pdf ---->> $pdf_name.ps "
        pdftops $pdf_name.pdf $pdf_name.ps

        echo "---->> $pdf_name.pdf"
        ps2pdf $pdf_name.ps $pdf_name.pdf
        rm -rf $pdf_name.ps
    done
    echo "######## Convert end!! ########"

    echo "######## Merge begin!! ########"
    pdftk $pdf_list cat output $pdf_merge
    echo "######## Merge success, open $pdf_merge to see the result. Bye!! ########"
}

while getopts "d:f:o:h" arg
do 
    case $arg in
        d)
            pdf_dir=$OPTARG
            pdf_list=`ls $pdf_dir/*pdf`
            ;;
        f) 
            pdf_list=$OPTARG
            ;;
        o) 
            pdf_merge=$OPTARG
            ;;
        h)  
            usage
            exit 0
            ;;
        ?)
            echo "!!Wrong command options"
            usage
            exit 1
            ;;
    esac
done

# if pdf_dir is not set yet, then it's set to default(that is, current directory)
pdf_dir=${pdf_dir:-"."}

# set default output pdf filename, plus $pdf_dir prefix
pdf_merge="${pdf_dir}/${pdf_merge:-"single_merged_pdf.pdf"}"
merge_pdfs

脚本结构还是很简单的:

  • 参数解析采用bash内置的getopts,暂时只支持短选项;
  • 有一个帮助说明函数function usage{};
  • 关键函数是function merge_pdfs{},尤其需要注意目录名和文件名的处理;

调用方法如function usage{}里面所示:

  • ./wanfang_pdf_merge.sh -d pdf_dir
  • ./wanfang_pdf_merge.sh -d . -o merged_pdf.pdf
  • ./wanfang_pdf_merge.sh -f "dir1/pdf1.pdf dir2/pdf2.pdf" -o output/merged_pdf.pdf

测试:

wanfang_pdf_merge_test1

在这个基础脚本上进一步封装下,比如,对于如下的目录结构:

lox >>> tree -L 3 -p -N | grep '\[d' 
└── [drwxrwxr-x]  wanfang
    ├── [drwxrwxr-x]  IPTV机顶盒GUI子系统的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   └── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  Tools设计与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于QtEmbedded的图形用户界面移植
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于嵌入式Linux智能手机GUI平台的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  基于消息通信机制嵌入式GUI的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式Linux图形用户界面的研究与开发
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式uGUI的研究与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    ├── [drwxrwxr-x]  嵌入式系统轻量化GUI框架的设计与实现
    │   ├── [drwxrwxr-x]  Images
    │   ├── [drwxrwxr-x]  Paper
    └── [drwxrwxr-x]  面向数字家电产品的GUI框架的设计与实现
        ├── [drwxrwxr-x]  Images
        ├── [drwxrwxr-x]  Paper

我们的封装脚本命令如下:

for pdf_dir in `tree wanfang -ipNf | grep '\[d' | grep 'pdf' | awk '{print $2}'`
do              
    ~/tools/wanfang_pdf_merge.sh -d $pdf_dir
done

接下来喝咖啡!!!

wanfang_pdf_merge_test2

咖啡喝完后,我们来看一下结果:

lox >>> tree -ipNf  | grep 'single'
[-rw-rw-r--]  ./wanfang/IPTV机顶盒GUI子系统的研究与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/Tools设计与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/Tools设计与实现/Paper/pdf/single_merged_pdf.ps
[-rw-rw-r--]  ./wanfang/基于QtEmbedded的图形用户界面移植/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/基于嵌入式Linux智能手机GUI平台的研究与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/基于消息通信机制嵌入式GUI的研究与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/嵌入式Linux图形用户界面的研究与开发/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/嵌入式uGUI的研究与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/嵌入式系统轻量化GUI框架的设计与实现/Paper/pdf/single_merged_pdf.pdf
[-rw-rw-r--]  ./wanfang/面向数字家电产品的GUI框架的设计与实现/Paper/pdf/single_merged_pdf.pdf

大功告成!!!

接下来的任务是:

    写论文!!!!!!!!!!

Mac OS X遭遇记

3月1号回到玉泉,处理了许多杂事,找导师沟通了下毕业设计的问题。沟通的最终结果就是我又被发配到了手机客户端组,继续做GUI控件。事实上我最开始选的题目是《海量空间数据的高性能引擎研究》,我还是挺喜欢这个方向的,而且与我在Baidu的实习以及日后的工作都有很大的关联性。但是导师一句“题目较难,时间不够”就把我噎了回来,紧接着来一句“我还是希望你能够做一些连续性的工作”——就是去年四月份实验室做的Windows Mobile控件开发了。其实我是非常不喜欢这个项目的。对于一个崇尚自由、分享的Open Source Programmer来说,用着盗版的Windows+VS,盗用Open Source的成果来开发闭源软件,实实在在是一件不怎么惬意的事情——老实说我也算不上合格的Open Source Programmer,因为我至今也没有自己的Open Source软件。其次是我越来越讨厌关于Windows的一切,无论是作为一个User还是Programmer。我最近正计划着写一系列的Windows吐嘈文,构思良久,即将面世。

只不过这次不同,我所面对的不再是Windows Mobile,而是——iOS。

How?这是我脑子里最先冒出的想法——How to write an Win32-Styled GUI program under Windows(or maybe Linux) platform for iOS?我战战兢兢地问了下学长“实验室有苹果机吗?”,答曰“没有,用虚拟机”。

Oh,my god。在Windows平台上运行着虚拟机,在虚拟机里面运行着Mac OS X,在Mac OS X里面运行Xcode,在Xcode写Win32-Styled Program,然后将这个Win32-Styled的Program Load到虚拟机里面的Mac OS X里面的Xcode IDE里面的iOS模拟器上,调试!!!

What a Joke!

不过,吐槽归吐槽,活儿还是要干。鉴于前两次Hacintosh的惨痛经历,所以这才在也不敢在自己精心调制好的ThinkPad x201i上为所欲为,还是乖乖的虚拟机的好。幸好前两天买了根三星金条,武装到了4G内存,否则还真不敢想象在虚拟机里面玩Leopard。

高级的虚拟机咱不懂,所以诸如KVMXen就不在考虑之列了。剩下的,最开始接触电脑时玩的Microsoft Virtual PC,不知道现在活的怎么样。VMware,大概是三年前用过,印象就是臃肿,慢。VirtualBox,我的最爱,开源、免费、跨平台、轻量快捷。所以VirtualBox是试验的首选环境。

不过Mac平台的封闭性带来一个众人皆知的事实,那就是Hacintosh的成功性与人品——也无关,我的意思是说,Hacintosh的成功与否完全是莫名其妙的事情,无论是虚拟机还是实体机,能否Hacintosh,要看上帝的心情。

Hacintosh的版本有很多,比如东皇、iATKOS、iDeneb、OSXPCBETA等等,boot loader也有若干种方案,比如变色龙、EFI Emulation等等,个中详细可以参考OSx86。而由这些基本“元件”排列组合出来的网上作为“PC变Mac”的方案更是五花八门,让人目不暇接。照理说,对各种硬件的良好支持是一个OS安身立命的最基本条件,至于Mac如何在违背这个基本原则下打拼出自己的逍遥天地,容我另外一篇文章再做分析。

好了,回到正题,继续我的Mac OS X遭遇记。我按照老赵点滴上的指示在我的ArchLinux+VirtualBox 4.0上做实验,前面都是很顺利的,也出现了下面的Kernel panic情况:

mac in virtualbox: kernel panic

按照教程,重启之后就可以进入期盼的Leopard,可是我却陷入了无限的灰色风火轮等待中。重整多番,调整了多组参数,均以失败告终。

于是转投VMware,我按照VMware的要求,下载了300+M的VMware7.1的bundle,按照ArchWiki上的步骤,成功装上了VMware,但是确始终启动不起来。无奈,转投Windows吧。之所以坚持Linux,是因为我需要LaTeX,我需要Emacs+Auctex+cdlatex+outline-mode来完成我的毕业论文啊。

好在Windows下的VMware还算正常,安装过程也算顺利,我就不在细说了。具体过程可以参考《VMWare下安装MAC OS X Snow Leopard 10.6》,需要注意的主要是:

  • 安装之前用securAble检测下CPU是否支持虚拟化;
  • 内存至少1G,最好主机配上4G内存,而VMware配上2G内存,否则慢起来很要命,如果搞开发,硬盘最好20G以上;
  • 注意修改VMware目录下的.vmx下的guestOS由guestOS = "freebsd-64"改为guestOS = "darwin10";
  • 启动时始终需要darwin.iso来引导;
  • 成功安装系统后安装darwin.iso里面的vmtools,获得更好地使用体验;

放张图吧:

vmware mac os x

顺便感叹下,VMware的虚拟化技术还真是强大,2G虚拟内存跑Mac OS X,速度还真是不赖,界面效果也都能跑的出来。如果再弄个分屏软件,再插上一个LCD的液晶屏,就真是两个系统了。

至于Xcode和iOS SDK的安装就简单很多了,可能需要做一次系统升级。至于iOS上如何写Win32-Style的GUI程序,我现在也是丈二的和尚。至于额外的Macintosh吐槽文,还是等以后心情不错的时候再写吧。

兔年伊始

一月初处理完家中的事,回到百度补了三天班,请了两周的假,马不停蹄回到杭州,参加学校的几门考试。当然,这期间顺便去了趟上海看了看妞——也顺便看了看新版水浒传。陪妞的几天搞定了C#大作业,到杭州已经是一月中旬的事情。到宿舍的第一件事是发现了桌子上的奖学金证书,上面还写着自己的名字,没错,就是我。学业优秀三等奖学金,我仔细看着这几个烫金大字,脸上一阵苦笑——要知道,大三一年我还挂了三门课。不过心里却还是挺高兴的,虽然我根本不太在乎这个东西。给母亲打了个电话,让她高兴高兴;给妞也发了条短信,妞回“你的大学生活完满了”——我呢,会心一笑,盘算着这几百大洋能给妞买个什么东西呢。

一月的杭州总是那么阴霾,又赶上难得的大雪给太阳公公放了长假,不多的好心情也在湿冷的空气中散发殆尽。考试还是很无聊的,更无聊的是你在准备无聊的考试,别人却在旁边无聊地玩着无聊的游戏。所谓“大四不考研,天天像过年”,我是个例外,因为大四的最后半年我还有七门考试——都是重修。其实每个学期初自己都雄心勃勃的——工作要好,项目要做好,课程也要尽量做好,但是往往最终结果是工作好,项目好,课程却一塌糊涂。大四上我选了六门课,华数淘宝实习到十月中旬,然后用了不到两周的时间就拿下了Baidu的Offer,照理说,剩下的时间应该好好补补课业,搞一搞毕业设计,结果我却依然非常偏执地申请了Baidu的实习,不断地给自己“没事找事”,不懂得“享受时光”。结果是,整个一个学期六门课,我就去上过两次。学期末的考试自然难免焦头烂额。好在结果还行,我通过了本该预科时学的《线性代数》,两门选修课,C# 80+,软件体系结构也低空飘过。电路原理就去打了个酱油,计算机组成再度弃考,数字电子技术……真是纠结。

在杭州的几日还去参加了两次同学会,最大的发现是,CKC的同学们还是很牛的——有拿到MIT某某比赛金牌的、有在MSRA实习的、有拿了ACM中国赛区金牌+HKUST Offer+MSRA实习的、有保送到ZJU CAD/CG实验室读PHD的、有ibus-cloud-pinyin的作者和ibus-sunpinyin的作者、有主修CS辅修商科最后拿了Monitor咨询Offer的强悍女生,等等。我发现自己似乎有个小毛病,就是太过认可自己的生活方式,总以为别人的生活方式怎样怎样,偶尔会带着一丝鄙夷的眼光来看待一些事情。回头看看自己写的两篇《找工作总结》,霸道之气溢于言表,对自己挂课这件事情不以为耻,反而吹嘘地如同传奇一般。这或许是一种自恋吧。想想还是那句话,“人生不是平行的向量,没有可比性”。每个人都应该有自己的精彩,嗯。

23日回到北京,继续Baidu的实习。由于我元旦、春节等各种假期,导致我在Baidu的时间很分散,因此导师安排我去做一个项目调研性的工作。我选择的是x-trace,一个patch-based、cross-layer的网络监控工具。做的调研工作就是如何在Hadoop中集成x-trace,从而全面了解MapReduce任务的运行细节,如下图:

在Baidu一直奋战到最后一天,还参加了整个运维部的年夜饭。2月2号早晨起床迟了,便转道赶往六里桥客运站。好在运气不错,赶上了家乡的一辆Passat正在吆喝人,简单询问了下就上了车。司机彪悍无比,用一对春联盖上前后的车牌,几百公里的高速公路愣是没有交一分钱。就这样,大年三十、下午两点,我总算有惊无险地回到了家中。家中几日无非就是那么几件事情——看春晚、包饺子、走亲戚、喝大酒。我不喜欢喝酒,虽然我有那么点酒量。我觉得多数情况下,酒杯里盛的不是酒,而是虚伪。觥筹交错的背后往往是尔虞我诈。酒品如人品,都是一种心境,对高人而言,即便是白水一杯,亦可品出人间百态。

8号返京。我和父亲开车,带上弟弟,捎上去廊坊工作的表兄表嫂。带弟弟来主要是让他来参观下,长长见识,按照父亲的说法——“给他施加点压力”。中午到火车站,在北京的立交桥上绕了若干圈后终于到达了北5.4环我的住处。下午去百度大厦参观,节假日,保安无论如何也不给我这个面子,就是不让父亲和弟弟进。无奈之下只能带着他们绕着大厦走了一圈。时间尚早,就临时改变了计划,去清华北大参观下。如此又让我想到了高二那年来北大蹭课的青涩岁月。那时自己一门心思沉浸在竞赛中,数学竞赛惨败后就转战了化学,跟着“师傅”来到了北大,跟老师说是来买些书,顺便来听次课。其实暗地里倒是主要为了逃避一次月考。来到北大,漫步在未名湖畔,仰望博雅塔,清风徐徐,心情自不必说——仿佛自己已经考上北大,成了天之骄子。漫步进入一个小书店,就如那刘姥姥进了大观园,直把这里当成了理工科的天堂。买了各种各样的书,热学的,分析化学的,有机的,不知道有多开心了。次日去化学系蹭了节裴伟伟的有机化学课,讲的是什么已然忘记,印象深刻的,第一点就是很多人上课迟到,或者偷偷吃东西,让我觉得非常不可思议;第二点就是“师傅”wp去索要裴教授的签名,裴问了我们是哪个学校的,“师傅”说是唐山一中高二的……北大蹭完课,晚上又去清华逛了逛,也记不得是从哪个门进去的,只是记得wp总在那里提醒说“清华比北大还大,小心走丢”,还有就是我们逛着逛着到了一个路灯下,杆子上有一个按钮,我就要伸手去摁。然后wp一下子把我从背后抱住。事后我才知道那个可能是报警按钮,不能乱摁。哎,当时实在是太嫩了。

胡乱开车到了清华西门,时间已是下午两点多。在清华只走了两个小时,父亲就直嚷嚷着大腿疼。我也终于明白,父亲的时代已经过去。我们,已经成了时代的主人。清华出来后又拉着俩人去未名湖走了一圈,顺便感慨下即将逝去的大学生涯。晚上带着俩人去看了场3D电影——周杰伦的《青蜂侠》。父亲是一点本事没有了,而他也确实十多年没有看过电影了,像个小孩子似的,跟在我的后边,拿票,换3D眼镜。看了一半他还睡着了……弟弟倒是看得津津有味。

次日早晨,父亲和弟弟回家,我去上班。走之前帮他们设置好了导航仪,一路顺风,中午到家。我回到公司,继续调研我的x-trace。直到现在,项目依然没有本质的进展,主要原因是我对这个项目的难度评估不足,其次是我个人能力不够。x-trace是Berkeley RAD Lab几个博士生的博士论文项目,整个项目涉及到众多领域如对TCP/IP协议栈的深刻理解、Java/Ruby/Perl的纯熟使用等等。除此之外还有一些基础性工具的使用,如svn/git、ant/maven/scons、jetty、graphviz,GNU diff/patch等等,而要结合Hadoop与x-trace,更是需要对Hadoop的内部通讯机制有着深刻的了解。而这一切的一切,让我在调研的过程中举步维艰。

好在导师并没有给我施加太大的压力,项目也没有特别紧要的milestone,所以我还是有时间来巩固下基础,看一些书籍。部分重读了Java之父James Gosling的《The Java Programming Language》,了解了Annotation、Reflection、Serialization,让我对Java语言有了更进一步的认识。不过不得不说,初学者想要靠这本书入门还是太难了。学习了下Ant的使用,简单浏览了下Ant权威指南,主要是了解下主要思想和基本概念,没有太过深究。Hadoop: The Definitive Guide读到了第十章,还在本机上搞了个伪分布式Hadoop集群,但是缺乏实践,对Hadoop内部机制还是似懂非懂,多写写Java程序吧。另外,Pragmatic系列的几本小书都很不错:

  • 《Pragmatic Version Control Using Subversion》,svn基础使用入门,有Linux环境的话动手实践一下,两三天就可以上手了。
  • 《Pragmatic Unit Testing in Java with JUnit》,基于JUnit 3.x版本的,比较老了,但是单元测试的概念是相通的。
  • 《Pragmatic Project Automation》,讲的是软件的自动化构建、测试、安装、发布等等。

技术之外,我还看了一些电影短片和Blog,简单做下推荐:

  • 《天使爱美丽》:特别喜欢影片的色调、喜欢那个傻傻的矮个子、玻璃老头,当然,还有爱美丽的微笑。
  • 《黑天鹅》:一部心理剧,展示了人在巨大压力下心理的变化过程。但是我看不太懂。
  • 姜文《太阳照常升起》、《阳光灿烂的日子》,不知道是姜文的电影太过晦涩,还是我比较幼稚,总是看不太懂,包括《让子弹飞》。当然,字里行间外露的姜文的霸气,我还是能感受得到的。
  • 筷子兄弟《老男孩》,也许我还没有长大,不够成熟,但是这个片子让我来评,歌曲占80%,片子占20%。“青春如同奔流的江河,一去不回来不及道别”,叶蓓《白衣飘飘的年代》也是很不错的。
  • 旭日阳刚《春天里》、西单女孩《天使的翅膀》:总是有那么一些人,能够不时的带给我们一些温暖和感动,坚持的力量。
  • 刘伟《You Are Beautiful》
    • “我的人生中只有两条路,要么赶紧死,要么精彩地活着”
    • “生命里有三样东西不可以少,空气 水 音乐”
  • 《搭车去柏林》,这个记录片看得我躁动不已。我跟妞说“我们辞职吧,用一生的时间去度一个蜜月”。每一刻都是崭新的,我所向往的生活。
  • 《背包十年》,号称是中国第一位职业旅行家,确是不一样的人生。但是作者认为“白领的生活精确到每分每秒,但每分每秒都是无聊”,我认为颇为偏激。社会需要进步,而单单靠环游世界是无法推动社会进步的。所以环游世界是我的梦想,但也只是梦想之一。
  • 身边总有这么一些人:净干些随意妄为的事,一副既不在乎自己也不在乎别人的样子,其实心底里藏着比任何人都要柔和而耀跟的光芒。还就是这么些人,时不时地让你感到:活着真他妈带劲。follow your heart!!

忙里偷闲还去体验了下Archlinux下WordPress的本机安装,琢磨着有空了去搞一个独立域名的Blog。我最近一直想写一些东西,比如Hadoop的本机安装啊,WordPress的入门使用啊,Subversion使用小记啊,等等,诸如此类。但是转念一想,这些东西在网上都有足够多的资料,也不需要我在多此一举,给互联网上再增添点垃圾信息——国内的很多网站论坛基本上就是Copy来Copy去,而且Copy过来都不懂得排版一下就贴上去,恶心。我更希望有一些深刻独特的东西,所以最近一直在思考,却很少提笔了。如刘未鹏所说,“书写是为了更好的思考”,坚持写了一年多的Blog,确实让我受益很多。一点一滴,看到了自己的成长过程,结交了一些朋友,也开始学着将知识串成网络,展现出来。

3月返校,暂时结束Baidu实习生涯,全力以赴搞定毕业大计。看看能否抽出时间,架上单车,再出去“干上一票”,漂泊的梦想,压抑好久,已经膨胀的不行。

Issues of Eclipse Helios with Hadoop

最近在搞Hadoop MapReduce,在本机配置了个Hadoop Pseudo环境,就琢磨着写两个Java小程序练练手。而Java程序开发的初始配置一向以麻烦著称,记得大二时开始学习Java时对那个CLASSPATH环境变量晕了好久。所以这个时候选一款顺手的IDE就是很重要的了。

另一方面,对于长期生活在K.I.S.S环境的geek来说,对IDE通常是不感冒的。他们更喜欢a+b+c+d+Emacs或者Vim+w+x+y+z的组合。但是Java就不同了。Emacs虽然有JDEE,但是Emacs没有好用的jsp-mode,好像也没有自动打包发布部署的功能,或者即使有,也需要极其麻烦的配置。而且Emacs的代码不全功能一向很麻烦也不太好用,对于Java巨大的类库和超长的类名就更头大了。所以在血淋淋的事实面前,我还是屈服了。好在还有个Eclipse。

为什么是Eclipse而不是NetBeans?其实没啥特别的原因,就是Eclipse的界面更加和谐一点,对Java Swing的丑陋效果和蜗牛般的速度实在是心有余悸。Eclipse确实也是非常优秀的软件,跨平台,多语言,丰富的插件和和谐统一的插件安装系统,良好的社区支持。Emacs也是。

好了,废话少说,说说今天纠结的Eclipse Hadoop之旅吧。我用的软件版本是Eclipse 3.6,安装的时候顺便将eclipse-cdt也装上了:

pacman -S eclipse eclipse-cdt

启动Eclipse一切正常,试着建立一个Project却发现无论如何也找不到C++的项目,照理说不应该,不过不打紧,C++和今天的主题无关。继续。

Eclipse开发Hadoop MapReduce程序需要安装一个hadoop eclipse plugin,而根据Eclipse和Hadoop版本不同,所需选择的插件也不一样,有官方hadoop contrib里的jar包,有google code上的,还有打过patch的山寨jar包。而eclipse安装插件的方法也有很多,比如:

而我排列组合搞了一个下午后,Eclipse 3.6的Hadoop插件还是没有装上。无奈在AUR上安装了Eclipse 3.5:

yaourt -S eclipse-classic-galileo

然后将eclipse-hadoop-plugin放到plugins目录下,终于看到了可爱的小象。究竟是怎么回事呢?

定位好久,还是没有任何头绪。首先是eclipse没有Linux Manual,输入eclipse --help也没有任何信息,所以我不知道eclipse CLI有没有什么可用的参数;其次是我不知道eclipse有没有自己的log,或者有我也不知道在什么位置,无法发现启动过程中的蛛丝马迹。

此时已经有些心灰意冷,寻思着要不就用Eclipse 3.5得了。无意中在网上发现了Hadoop的另一个插件,Karmasphere,看了下介绍还是蛮强大的,而且有community和professional两个版本,前者是免费的,只是下载的时候需要简单注册下。最重要的是,这个插件有Eclipse和NetBeans两个版本,真实太令人激动了。照着教程配只好NetBeans 6.9的开发环境,可以用,很强大。于是心情大好,继续配置Eclipse 3.6版本,这下Eclipse 3.6无法安装插件的问题终于露出了狐狸尾巴:

"Cannot complete the install because one or more required items could not be found. Software currently installed: Shared profile 1.0.0.1284044641500 (SharedProfile_SDKProfile 1.0.0.1284044641500) Missing requirement: Shared profile 1.0.0.1284044641500 (SharedProfile_SDKProfile 1.0.0.1284044641500) requires 'org.eclipse.swt.gtk.linux.x86_64.source [3.6.1.v3655c]' but it could not be found"

!!!

重点是"requires 'org.eclipse.swt.gtk.linux.x86_64.source [3.6.1.v3655c]' but it could not be found"。赶紧定位下org.eclipse.swt.gtk.linux.x86_64:

% sudo updatedb && locate org.eclipse.swt.gtk.linux.x86_64
/usr/share/eclipse/plugins/org.eclipse.swt.gtk.linux.x86_64.source_3.6.1.v3655c.jar
/usr/share/eclipse/plugins/org.eclipse.swt.gtk.linux.x86_64_3.6.1.v3655c.jar

可以肯定的推断,这个东东在系统中是存在的,虽然命名方式可能不太一样。接下来的问题就好办了很多。我怀疑是/usr/share/eclipse目录的读写权限问题。在这里我的想法得到了佐证。于是立马改了/usr/share/eclipse的读写权限:

sudo chown -R lox:users /usr/share/eclipse

重启Eclipse 3.6,果不其然,CDT复活了。于是又安装了Eclipse-hadoop-plugin和karmasphere的plugin,总算大功告成。

最后放一张图吧:

eclipse_hadoop

x86-64 Arch Linux on ThinkPad x201i

前两天自用的Arch Linux系统出了点小问题,索性重新搞了一下,由i686迁移到x86-64平台。原先一直以为64位系统是高不可攀的贵族产品,后来才知道原来64位处理器最早是由AMD 1999年设计,几年前的Intel Core Duo早已经支持64位系统,只是软件产品和内存还跟不上,所以多数应用还是32位为主。

OS版本用的是Arch Linux 2010.05,在mirrors.sohu.com上下载支持 32 位及 64 位架构的 Dual 映像,用UltraISO刻录硬盘镜像到U盘上。基本的安装过程不再赘述,ArchWiki Beginner's Guide讲的明明白白。唯一注意的是分区格式化的时候需要格外注意,不要把自己原先的系统搞丢——我曾经有过惨痛的教训,不过幸好那次做了数据备份。不过100G的东西备份还原也是件耗时耗力的工作啊^)^。

基本系统装好后,装个Desktop Environment,然后再做一下系统美化和针对小黑的特殊配置。过程还是挺繁琐的,因此写下来做个备忘。先上张图,KDE4.6——我承认我越来越浮云了……

最新的Xorg已经变得十分人性化,再也不需要手工配置恼人的xorg.conf,最新的Linux内核驱动也能自动识别鼠标和键盘,不会再出现进入图形界面却无法使用鼠标键盘的窘境——至少两年前是这样的。有个东西叫做HAL,最近又出来个evdev。总体而言Linux的驱动程序还是比较混乱的,hal、evdev、mesa、xorg、xf86、wayland、alsa、oss、pulseaudio等等,令人头大。

字体用的是AUR里面打过ubuntu补丁的cairo-ubuntu、libxft-cairo、freetyp2-ubuntu以及WenQuanYi Micro Hei,加上次像素优化,效果还是不错,上图就是最好的说明。

网络客户端抛弃了废柴的KDE的networkmanager,采用了wicd,可以根据地点自动链接不同的无线网,而且非常稳定,从不崩溃。安装过程可以参考ArchWiki Wicd。关于蓝牙的配置,我用的是bluez和bluedevel,具体可以参考这里

剩下的都是小黑的特别配置。这方面的Wiki配置零零总总,并没有统一的解决方案。ThinkWiki是一个很好的去处,基本可以找到ThinkPad各个型号再主流Linux发行版上的安装配置。不过由此也看出开源软件的弊端——顶级的ThinkPad支持尚且如此繁琐,可见Linux真正要普及还有很长的路要走。废话少说,还是回到x201i上的设置吧。ThinkPad的设置主要有以下几处:

  • 电池电源控制
  • trackpoint小红点
  • Active Protection System,硬盘保护系统
  • 风扇控制

电池的电源控制主要是用来延长电池寿命的。电池的充电次数是有限的,因此减少电池的冲放电次数是演唱电池寿命的关键。tp_smapi是针对ThinkPad的一组内核模块,可以通过AUR(yaourt -S tp_smapi)安装。对电源的保护主要是设置电源的冲放电阀值。比如我们设置[start_charge=40, end_charge=90],意思就是当电池的电量低于40%的时候才开始充电,而一旦电量到达90%的时候就停止充电。举例说明,当我们野外需要频繁的野外工作时,如果不设置电池的充放电阀值[start_charge, end_charge],那么我们的电量可能是这样的:95(battery, discharge)-->80(AC power, charge)-->100(battery, discharge)-->70(AC power, charge)-->93(battery, discharge)-->70,而设置[start_charge=40, end_charge=90]后我们的电量变化就是这样的:95(battery, discharge)-->80(AC power, but not charge)-->80(battery, discharge)-->50(AC power, but still not charge since 50 >= 40)-->50(battery, discharge)-->27(If AC power now, charge, since 27 >= 40, charge until battery = 90)。看明白了吗?估计没有。反正我也有点晕。ArchWiki上提供了一个封装的脚本set_bat_thresh:

#!/bin/bash
#
# Bash script for setting the battery thresholds on ThinkPads using the tp_smapi interface.
# Written by Ignas Anikevicius (20/03/2010)

#HELP TEXT
if [ "x$1" == "x--help" -o "x$1" == "x-h" ]
then
  echo -e "
  WARNING!!! This script needs to be run as root in order to have effect!!!

  Possible options are:
    set_bat_thresh [BAT_N] [[LOWER] [UPPER]][--reset][-r] 
 
    [BAT_N] number of the battery (can be either 0 or 1). 

    LOWER - lower threshold.
    UPPER - upper threshold .
    [--reset] or [-r] sets the default thresholds. 

  execute to see this text:
    set_bat_thresh [--help][-h]
"
  exit 0
fi 

if [ ! -d /sys/devices/platform/smapi ]; then
  echo -e "\nSMAPI interface is NOT installed.\nPlease load the module.\n"
  exit 0; fi

#SETTING THRESHOLD VALUES
if [ "x$2" == "x--reset" -o "x$2" == "x-r" ]
then
  LOWER=96
  UPPER=100
else
  LOWER=$2
  UPPER=$3
fi

#VALUE TESTING
if [ ${LOWER} -ge ${UPPER} ]; then
  echo -e "\n  Please provide proper thresholds!!!  \n"
  exit 0
fi

#BATTERY NUMBER
BAT_N=$1
LOWER_F="/sys/devices/platform/smapi/BAT${BAT_N}/start_charge_thresh"
UPPER_F="/sys/devices/platform/smapi/BAT${BAT_N}/stop_charge_thresh"

#SETTING THE THRESHOLDS
echo ${LOWER} > ${LOWER_F}
echo ${UPPER} > ${UPPER_F} 

#ECHOING THE STUFF
echo -e "\nSetting battery thresholds for Battery ${BAT_N}:
  Threshold for charging to start: ${LOWER} 
  Threshold for charging to stop: ${UPPER} 
"
exit 0;

执行用:

set_bat_thresh 0 start_charge end_charge

至于trackpoint小红点,AUR里面有一个trackpoint脚本,用yaourt -S trackpoint安装,安装完毕将trackpoint加到/etc/rc.conf的DAEMONS里面。/etc/conf.d/trackpoint里面可以更改一些设置如:

  • SPEED: 小红点光标移动速度。
  • SENSITIVITY: 小红点敏感度。
  • PRESS_TO_SELECT: 小红点单击功能。

中键模拟用如下的脚本设置下(我也忘了是从哪里找到的了):

xinput set-int-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation" 8 1
xinput set-int-prop "TPPS/2 IBM TrackPoint" "Evdev Wheel Emulation Button" 8 2

硬盘保护(Active Protection System)用的是AUR里面的HDAPS,参看ArchWiki,Applet用的是thinkhdaps,根据需要改下/etc/conf.d/hdapsd里面的设置,效果还不错,抱着笔记本在床上看电影的时候视频会一卡一卡的。

风扇控制貌似不太不要,而且设置不好会影响散热效果,降低笔记本的寿命。这个功能主要目的貌似是使笔记本更安静些。用的软件包是AUR里面的tpfand和tpfan-admin,tpfand.conf是copy来的,参考这里。用了之后好像也没啥特别的效果。

最后show下/etc/rc.conf里面的设置,日后重装的时候也好有个参考:

#
# /etc/rc.conf - Main Configuration for Arch Linux
#

# -----------------------------------------------------------------------
# LOCALIZATION
# -----------------------------------------------------------------------
#
# LOCALE: available languages can be listed with the 'locale -a' command
# HARDWARECLOCK: set to "UTC" or "localtime", any other value will result
#   in the hardware clock being left untouched (useful for virtualization)
# TIMEZONE: timezones are found in /usr/share/zoneinfo
# KEYMAP: keymaps are found in /usr/share/kbd/keymaps
# CONSOLEFONT: found in /usr/share/kbd/consolefonts (only needed for non-US)
# CONSOLEMAP: found in /usr/share/kbd/consoletrans
# USECOLOR: use ANSI color sequences in startup messages
#
LOCALE="en_US.UTF-8"
HARDWARECLOCK="localtime"
TIMEZONE="Asia/Shanghai"
KEYMAP="us"
CONSOLEFONT=
CONSOLEMAP=
USECOLOR="yes"

# -----------------------------------------------------------------------
# HARDWARE
# -----------------------------------------------------------------------
#
# MOD_AUTOLOAD: Allow autoloading of modules at boot and when needed
# MOD_BLACKLIST: Prevent udev from loading these modules
# MODULES: Modules to load at boot-up. Prefix with a ! to blacklist.
#
# NOTE: Use of 'MOD_BLACKLIST' is deprecated. Please use ! in the MODULES array.
#
MOD_AUTOLOAD="yes"
#MOD_BLACKLIST=() #deprecated
MODULES=(uinput tp_smapi thinkpad_acpi thinkpad_ec vboxdrv)

# Scan for LVM volume groups at startup, required if you use LVM
USELVM="no"

# -----------------------------------------------------------------------
# NETWORKING
# -----------------------------------------------------------------------
#
# HOSTNAME: Hostname of machine. Should also be put in /etc/hosts
#
HOSTNAME="lox-pad"

# Use 'ifconfig -a' or 'ls /sys/class/net/' to see all available interfaces.
#
# Interfaces to start at boot-up (in this order)
# Declare each interface then list in INTERFACES
#   - prefix an entry in INTERFACES with a ! to disable it
#   - no hyphens in your interface names - Bash doesn't like it
# 
# DHCP:     Set your interface to "dhcp" (eth0="dhcp")
# Wireless: See network profiles below
#

#Static IP example
#eth0="eth0 192.168.0.2 netmask 255.255.255.0 broadcast 192.168.0.255"
eth0="dhcp"
INTERFACES=(!eth0)

# Routes to start at boot-up (in this order)
# Declare each route then list in ROUTES
#   - prefix an entry in ROUTES with a ! to disable it
#
gateway="default gw 192.168.0.1"
ROUTES=(!gateway)
 
# Enable these network profiles at boot-up.  These are only useful
# if you happen to need multiple network configurations (ie, laptop users)
#   - set to 'menu' to present a menu during boot-up (dialog package required)
#   - prefix an entry with a ! to disable it
#
# Network profiles are found in /etc/network.d
#
# This now requires the netcfg package
#
#NETWORKS=(main)

# -----------------------------------------------------------------------
# DAEMONS
# -----------------------------------------------------------------------
#
# Daemons to start at boot-up (in this order)
#   - prefix a daemon with a ! to disable it
#   - prefix a daemon with a @ to start it up in the background
#
DAEMONS=(@syslog-ng @dbus !hal !network !netfs @acpid @tpfand @crond @hdapsd @laptop-mode @wicd @kdm bluetooth @trackpoint)

大概就这么多吧。都是些琐碎的东西,能用就好了。想想Linux的东西变动如此之快,有些东西是真的不必深究的。比如关于中键模拟有上面的方案,也有改xorg.conf的方案。比如hal这个东西,再比如X Window和未来的Wayland,比如ext4和btrfs。想想自己走的也有些偏了,过于追求工具化的东西,倒是忽略了最本质的知识,如体系结构,算法等等。这就比如户外旅行,总是想方设法装一辆拉风的自行车,却很少去骑车领略旅行的真谛。四年,四年前的我还只会开机关机,四年后的我折腾系统小打小闹颇有一套,最本质的计算机基础却一塌糊涂。希望自己的折腾之旅到此位置吧。接下来的关键词是,lisp、tcp/ip,hadoop。




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