20121129

Linux shell脚本,Linux下的西红柿时间管理法 III

Linux shell脚本,Linux下的西红柿时间管理法 III

8. 需要的支持技术

我们说到希望从atq指令的输出中,自动计算出还剩多长时间休息,而不是靠用户自己计算。atq的输出是这样的:

1 3444 Tue Nov 27 18:47:00 2012 r young
2 3445 Tue Nov 27 18:48:00 2012 r young

第1行是提醒的任务,第2行是锁屏的任务。这里已经包含了执行任务的时间,即Tue Nov 27 18:47:00
2012,我们要做的是把这段数据抽出来,跟当前时间做减法。

单纯这么一说,似乎任务很简单,但事实要更复杂一些,一会儿你会看到。在看到任务的时候就确定有哪些支持技术,是非常困难的。难到就像,你还没有迈出第一步,就确定以后的路上会遇到哪些大河要跨过,哪些高山要翻越。不知道以后会有什么困难就无从准备,而那些没有做好准备就遇到的困难,正是扼杀成功的原因。怎么办呢?无他,或者,如果我们有经验,走过一次,那就已经知道了;又或者,有个向导带着我们走,他已经走过一次;又或者,干脆现在走一次,然后就知道了。

在没走之前先猜测一下会怎么样,在走的每一步记录,这正是工程师的基本素养:估算和度量。

9. 探索的过程

我们准备写一个shell脚本,运行的时候显示出当前时刻距离atq中的第二行任务还剩多长时间

9.1 解析数据

要从

1 3444 Tue Nov 27 18:47:00 2012 r young
2 3445 Tue Nov 27 18:48:00 2012 r young

中把"Tue Nov 27 18:48:00
2012"单独取出来,是按约定的语法或格式处理字符串,在编译原理里叫作做解析。解析简单的数据的手段很多,比如sed,比如cut。

我这样实现的:
atq -q r | cut -f2 | cut -d' ' -f 1,2,3,4,5 | sort | sed -n 2p

这是由一组管理连起来的进程组成。"|"就是管道,表示前一个进程的输出作为后一个进程的输入。我们一步一步看。这些进程,包括cut,sort,sed,都是字符串处理常用工具,具体的用法和参数我也记不住,常要看手册或者google。

第一步,atq -q r,表示只列出队列r中的任务。执行效果是:

~ $ atq -q r
3502 Thu Nov 29 19:33:00 2012 r young
3503 Thu Nov 29 19:34:00 2012 r young

第二步,cut -f2,表示取出第二个字段。效果相当于下面这两行:

~ $ atq -q r | cut -f2
Thu Nov 29 19:33:00 2012 r young
Thu Nov 29 19:34:00 2012 r young

只去除了3501和3502两个序号。不要小巧这点工作,这是一个很好的开始,并且表明我们能够操作字符串了。

第三步,cut -d' ' -f
1,2,3,4,5,表示取第1、2、3、4、5字段,并且以空格作为分隔符划分字段,效果如下,切掉了后面的队列名和用户名,离目标更近了:

~ $ atq -q r | cut -f2 | cut -d' ' -f 1,2,3,4,5
Thu Nov 29 19:33:00 2012
Thu Nov 29 19:34:00 2012

第四步,sort,排序,默认是由小到大,效果如下:

~ $ atq -q r | cut -f2 | cut -d' ' -f 1,2,3,4,5 | sort
Thu Nov 29 19:33:00 2012
Thu Nov 29 19:34:00 2012

这是为了下一步有确定的输入,以便挑出正确那行。

第五步,sed -n 2p,选择输出第二行,效果如下:

~ $ atq -q r | cut -f2 | cut -d' ' -f 1,2,3,4,5 | sort | sed -n 2p
Thu Nov 29 19:34:00 2012

小结,我们由atq输出的任务

3502 Thu Nov 29 19:33:00 2012 r young
3503 Thu Nov 29 19:34:00 2012 r young

得到了将会锁屏的时间:

Thu Nov 29 19:34:00 2012

这一时间,将用于下一步的做差计算。慢着,任务的时间和当前时间做差,当前时间是什么?

当前时间可以用date获得,效果如下:

~ $ date
Thu Nov 29 19:18:20 2012

9.2 计算时间差

求时间点 Thu Nov 29 19:18:20 2012 和时间点 Thu Nov 29 19:34:00 2012
的差,当然不能把它们直接相减了事。有的同学可能想到了,可以按上面的方法解析出日期、小时、分钟、秒,然后再做减法。这也能解决,不过由于时间相减是个工程中可以想见的常用的功能,所以,应该有现成的解决方案。这也是个原则,凡是常用的功能,一定有常用的方案或者函数。至于什么是"常用的"功能,你常做小项目,就会知道。

去做,就会明白。就像,怎么成为好人,你希望别人如何对你,别人如何做你会感动,按照那个要求去做,那就是好人了,至少会被别人评价为"好人"。

时间相减这个功能的常用方案,我这样实现:

1 task=$(date -d "$task" +%s)
2 now=$(date -d "$(date)" +%s)
3 diff=$(($task-$now))

第一行中,执行了一个指令"date -d <什么东西>
+%s",这代表把<什么东西>里的时间转化为自1970年1月1日起到<什么东西>这个时间,相差了多少秒。为什么是1970年1月1日而不是1949年呢,因为大家可能还记得C语言和UNIX操作系统诞生于1969-1970年。那个<什么东西>就是"Thu
Nov 29 19:18:20 2012"这样的东西。

执行效果是这样的:

~$ date -d "Thu Nov 29 19:18:20 2012" +%s
1354187900

到底多少秒,我们也并不需要关心,一会儿能用来求差就行了。

"task=$(date -d "$task" +%s)"中代替了<什么东西>的,不是固定的时间,像"Thu Nov 29 19:18:20
2012",而是"$task",它表示一个变量,名字叫做task。这个task是这么来的:

task=$(atq -q r | cut -f2 | cut -d' ' -f 1,2,3,4,5 | sort | sed -n 2p
)

这就像在上面三行代码里,也有个变量赋值给task:

task=$(date -d "$task" +%s)

在等号右边的task的值是"Thu Nov 29 19:18:20 2012",在等号左边的task的值是上面的那个秒数 1354187900。

第2行为now赋值为"此刻"date的秒数。
2 now=$(date -d "$(date)" +%s)

第3行求差得到diff,锁屏时刻的秒数 (距1970年元旦 )和此刻的秒数 (距1970
年元量) 的差:

3 diff=$(($task-$now))

这样,我们就得到了,还有多少秒到锁屏时间,虽不够友好,但是离目标又近了一步。

9.3 格式调整

我不希望这样的结果,还剩778秒到休息锁屏时间,虽然这和12分钟58秒没什么本质区别。我希望它这样提示 12:58。

9.3.1 换算

这个好办,对60做除法,商就是分钟数,余数就是秒数。既然这么显然,那shell一定提供了这样的支持技术,果然一goolge就有。其实上面这些,有不少我忘记了或者记不清的,我也都去google了。关键在于,你得知道那东西存在,才能google。

这里[http://www.computing.net/answers/unix/remainder-operator/6820.html]有一段

: Use the % operator. Check below
: --
: 1. expr 5 / 2 gives 2 as Quotient.
: 2. expr 5 % 2 gives 1 as Remainder.

所以,我这样实现:

minute=$((diff/60))
sec=$((diff%60))

又是变量赋值。

9.3.2 条件判断

但是,还有些别的可能,比如只剩下12分5秒的时候,我不希望显示成

还剩12:5

而是希望得到:

还剩12:05

这需要条件判断。查到shell中的条件判断的语法:

if [cond]; then
fi

当然,前提还是,你得确信知道条件判断这种东西是存在的。

我这样实现:

1 if [ "$sec" -lt "10" ]; then
2 sec=0$sec
3 else
4 sec=$sec
5 fi

9.3.3 连接字符串

上面的代码中,第2行中的"0$sec",把常量字符串与变量相连接,就是直接接起来写,这个我也试了一下,如下:

$ a='hello'
$ b='world'
$ c=$a$b
$ echo $c
helloworld

9.3.4 判断空行

还有另一个可能。如果还有不到一分钟就休息了,atq的输出将只有一行,因为提醒音的那个任务已经执行完了。

我们需要判断输出有几行,或者说,我们需要判断空行。goolge得到:

[http://stackoverflow.com/questions/3061036/how-to-find-variable-is-empty-or-in-shell-script]

: In bash at least: if [[ -z "$var" ]]
:
: the command line "man test" is your friend.

最后一行对应的UNIX谚语是:男人是最好的,原文 "man is the
best"。这里的man,不是男人,而是manual的缩写,unix下的一个指令
man,用来查手册的。尽管大家都心知肚名man不是男人的意思,还是有不少unix/linux发行版中的man指令有个等同的指令,名字叫做woman。恩,而且woman和man不仅平等,而且完全一样。

我这样判断空行:

1 if [ -z "$task" ]; then
2 echo "No more than 1 minute left to have a break."
3 exit 0
4 fi

10 bug修正和功能增加

人生总是只有开始,才知道原来后面有这么多苦难;程序总是开跑才发现,原来总有bug存在。王子和公主从此以后过上无忧无虑的幸福生活,这种事只有在童话里才有。

没啥,逢山开路,遇水搭桥,碰到bug就杀掉。

10.1 排序

atq输出的时候,输出我也不知道是怎么个顺序,所以有了上面的sort指令。最初的版本中是没有的。

10.2 只加入指定的队列

虽然还没有出现这样的情况,但是在其他的时候,或者其他的程序,可能也要使用at任务的队列。所以,我改成只选其中一个队列使用。

atq -q r,只显示队列r中的任务。

at ... -q r,向队列r中添加任务。


11. 秘密

表面上看,上面是演示如何实现西红柿时间管理。没错,西红柿时间管理确实很有效,我常用。但是,正如钢琴老师教你弹的那些小曲子也确实挺好听的,但是她教你弹曲子的目的绝对不仅是欣赏这些曲子本身,而是更注重练习曲目时所得到的能力提升。这个小项目也是一样。

以上这些步骤看起来很流畅,先这样,再那样,然后又如何,最后问题解决了。等到你实践的时候可能略有不同。这种差异的来源是因为:我其实不是盲目地探索的,因为学习过其他的语言、做过其他的小项目,所以能够猜到应该有这样的那样的解决方案存在,所以我是有意去寻找每一步的技术和有计划地逼近终点的。换句话说,我经常地猜到了那里应该有这样的技术存在,然后才去google。而google并不能告诉你你不知道的东西。

如同《怎样解题:数学思维的新方法》[http://book.douban.com/subject/2124114/]这本书所说的,教师解题的过程,并不是盲目的,而是假设或计划将会如何,然后朝着那个方向推理和努力。我们作为学生需要体会的,是在观摩教师解题过程中的那些节点和方向。然后可能还要思考,他是怎么知道到这里就会有这个技术了呢?就像故事里讲的,孩子问雕塑师,你先前怎么知道石头里有个女人的呢。

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

20121127

Linux shell脚本,Linux下的西红柿时间管理法 II

Linux shell脚本,Linux下的西红柿时间管理法 II

4. 架框及已有的技术

我原来的代码非常简单,里面包含了大致的框架和已经利用的技术,如下。

1 #!/bin/bash
2 at now + 20 minutes 2>/dev/null <<EOF
3 aplay -q /usr/lib/openoffice/basis3.2/share/gallery/sounds/horse.wav &
4 EOF
5
6 atq | tail -n 1

以上是计时20分钟的,计时5分钟的基本相同,唯上面的20改为5。

第1行,表示将使用bash作为shell解释执行。

第2行,at指令表示增加一个作业,在某个时间执行,具体的时间是20分钟以后。"2>/dev/null"是错误重定向,即如果有错误信息,输出到null设备,也就是忽略它们。这是为了避免有错误的时候出提示信息。我希望程序出错的时候就死掉。

从第2行的"<<EOF"到第4行的"EOF"之间,是当20分钟到了的时候,计算机应该干点啥。第3行,也就是播放那声巨难听的马叫。

以上,就是主要的框架,手动运行脚本时增加一个at作业,然后到时间的时候放点声什么的提醒我。但是仅仅有音乐不足以打断我,所以向eyefoo学习,我准备让计算机到时间的时候把屏幕锁住。

这就涉及到下一个问题,我需要一些新的技术支持我。这也是做不熟悉的小项目的一个重要技巧:不是按需求-分析-设计-实现这样的瀑布或其变形,而是在做完需求和基本框架以后,要做技术原型测试需要的新技术。

5. 需要的支持技术

需要的支持技术包括:锁屏幕,解除屏幕的锁定,放音乐,算还剩多少时间休息。之所以新技术里需要
放音乐,是因为我发现马叫声太难听了,而eyefoo的那几段mid不错,准备拿来用。

算还剩多少时间这个比较麻烦,后面我们再单独谈,先看其他的。

5.1 锁屏幕和解锁屏幕

google了一下,得到以下结果。

[http://stackoverflow.com/questions/8681662/lock-ubuntu-from-shell-script]
Lock
ssh -X user@server "export DISPLAY=:0; gnome-screensaver;
gnome-screensaver-command -l;
UnLock
ssh -X user@server "export DISPLAY=:0; gnome-screensaver;
gnome-screensaver-command -d

然后我手动试了一下,好使。这里想再补充两点。第一,google不是万能的,使用它的前提是你得知道自己要找什么。所以从需求到分析、能找到需要的技术都很重要,它们帮助你知道要找什么。第二,找到以后试一下很重要。不试你不知道它好使,仅仅网友宣称甚至手册宣称都是没用的。亚里士多德还宣称两个铁球不同时落地呢。你得先试一下。此外,试的时候不要在你正准备做的项目里试,另做一个小的项目,专门试这个技术的。一次只解决一个问题,保持最小系统,都是符合14条原则的。

5.2 放音乐

5.2.1 音乐文件

eyefoo的mid在我的Linux机器上放不出声来,因为我的机器里没有这种乐器库。这个说起来就复杂了,跟mid的原理有关,此处略过。总之,你可以有两种方法做出个新的mid来。一种方法是,找个听音牛的,让她告诉你那个曲子的谱,然后你用lilypond或者cakewalk或者Siblius之类的软件按谱做个mid出来。嘴哼哼也行,在旋律上这没什么差别,所不同者,嘴哼哼的不能用mid格式。另一种方法是,用rosegarden打开这个mid文件,编辑一下,换个乐器试试,我换了三角钢琴。

5.2.2 播放

timidity break2.mid

timidity是个Linux下的midi播放软件,命令行的,可以在shell脚本下调用。这就是为什么那些命令行工具会长久存在的原因,它们为shell脚本提供服务。而GUI编脚本就困难多了。等你看了我后面贴的脚本代码,再对比.net之类写的工具,就会发现脚本真是简单了。

当然,这个也得试一下技术原型。

5.2.3 音量

我发现原有的曲子音量有点小,有的时候预告时间快到了那几声听不到,所以查了一下timidity的参数,-A 是调音量的。

当然,这个也得试一下技术原型。下略。

6. 代码

根据需求、既定的框架、新试完的技术,就有了以下代码:

1 #!/bin/bash
2 tomato_path="~/tools/tomato"
3
4 at now + 24 minutes -q r 2>/dev/null <<EOF
5 timidity -A 800 $tomato_path/prebreak2.mid &
6 EOF
7
8 at now + 25 minutes -q r 2>/dev/null <<EOF
9 timidity -A 800 $tomato_path/break2.mid &
10 gnome-screensaver-command -l
11 sleep 300
12 timidity $tomato_path/unlock.mid &
13 gnome-screensaver-command -d
14 20.sh
15 EOF
16

第2行,定义一个变量名字叫 tomato_path,后面在第5行、第9行、第12行分别引用了一次。

第5行,到24分钟的时候,预报时间快到了;第9行,放声音,下课啦;然后在第11行休息300秒,即5分钟;第12行,播上课铃声。

第10行,到时间了,锁屏幕。输入密码的时间通常足够阻止我继续工作的冲动。

第13行,休息结束,开启屏幕。

第14行,自动地再次运行这个脚本,即开始计时25分钟。

这段代码也可以在 [https://github.com/younggift/tomato.git] 找到。

7. 更多需求

这基本就够用了,但是还有不足。指令atq可以列出任务在什么时间将被执行,像这样:

$ atq
3444 Tue Nov 27 18:47:00 2012 r young
3445 Tue Nov 27 18:48:00 2012 r young

但是,我更想直接快速知道还有多少分钟可以工作,而不是根据当前时间和任务时间计算。所以,我们还希望能用脚本解决这个问是。

未完待续

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

Linux shell脚本,Linux下的西红柿时间管理法 I

Linux shell脚本,Linux下的西红柿时间管理法 I

1. 西红柿时间管理法是什么

西红柿是一种时间管理方法,用于帮助我们集中注意力的。大致的思路是,集中注意力工作25分钟,在这个期间,拒绝电话、上网、计划外的讨论--一般而言,即使对方是你的老板,告诉他25分钟以后去找他,这样的态度他也容易接受。25分钟以后休息5分钟,无论工作得有多么high,工作有多么重要。花了多少时间不重要,集中注意力才是生产力,因为人的脑力创造性的效果并不与时间成正比。重复以上步骤4次,休息一个较长的时间。

为什么这个时间管理法叫做西红柿呢,因为人们最初使用西方厨房里煮鸡蛋计时器来倒计时25分钟和5分钟。咱们煮蛋的时候一般都是用手表,隔一会看一眼表,差不多到时间了捞出来。这个表面上合理的方法违背了计算机程序设计中的一个比较基础的原则:中断比轮询对CPU的占用率低。不过咱们似乎一向对工作和对生活按两种不同的态度。

西红柿的详细介绍可以参见[http://article.yeeyan.org/view/204108/169539],参考书是[http://book.douban.com/subject/5916234/]。

2. 我为什么要在Linux下写西红柿时间管理工具呢

最初,我写了个非常简单的脚本。大概能实现这样的功能:手动运行一个脚本,到25分钟的时候,机器叫一声,是一声巨难听的马叫,提醒我该休息了;然后手动跑另一个脚本,到5分钟的时候再叫一声。

然后,我遇到了问题。到25分钟的时候,如前所述,我可能干活正high,当时听到马叫的反应就是"啊,时间到了,马上就停",这个"马上",有一次持续达4个小时。我遇到的另一个问题是,开始工作的时候,有时忘记手动运行这个25分钟计时,直到累得不行的时候才想起来,"20分钟怎么这么长啊。"

后来,张和郑两位同学群发了个工具,就是eyefoo[http://eyefoo.com]了。这是个windows下的程序,我需要windows的时候就用它。感觉不错,对比我前面在Linux下遇到的问题,就看出了原来简陋脚本的差距了。

3. 功能需求

第一,我的脚本在25分钟结束的时候提示的"声音还不够大"。需要更强有力的事件阻止我继续工作。这并非你的意志薄弱,而是动物性使然。心理学告诉我们,当我们产生情绪冲动的时候,理智那块的大脑还没来得及得出结论。所以,心理学家又告诉我们,这个时候,延迟和打断就很有效果。你如果特想买某个东西,把它放到购物篮,间隔一段时间,等到付钱的时候,想买的冲动可能已经消失了。基本上,愤怒、想砍人什么的,都可以用这种方式化解。足够强有力的打断,然后一小段延迟。

这种强有力的打断虽然来自我自己,仍然令人不爽。所以,eyefoo做得很好,它提前一会儿告诉你,"快到点了啊。"这人性化多了。

第二,我希望25分钟结束以后,自动计时5分钟,休息5分钟结束以后,自动计时下一轮的25分钟。

第三,我仍然希望它工作在Linux下,而且还用shell来写。

未完待续

--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

20121112

男人都应该这样死去

男人都应该这样死去

如何死去,这并非一个所谓"讨巧"的话题。当今之世,大家都在讨论真正牛的富二代如何娶了年轻貌美的女子,或者嘲笑如何适度地在会议上哽咽才能获得权利从而得到女子,又或者你是不是会弹大提琴或者煮得一手好咖啡从而讨好芳心进而得到女子。总之,如何享受生活。但是,这些都是给那些已经拥有享受生活的资本的人考虑的。还有一些人,需要考虑的是如何离开女子,或者,如何去死。

我前天看了一部新片子《边境风云》,里面就有这样一个男人。他沉默,即使要被活埋的时候也没有吭一声,甚至没有动一动;他明知必死,以死赴之,把未来的生活留给女人。

有人会说,那故事都是电影里的。所以,在现实中,我们看到了另一些故事。

某高校举行运动会,取消了长跑项目,这包括男子5000米。一看到5000这个数字,很多人可能就一哆嗦。因为我们都跑过1000米或者女子800,挺累的。与此相比,5000米更是一个能让人把肺子翻转出来的项目。取消这个项目的原因,是因为怕学生受伤,学生们的态度则是"没意思""时间太长了"。

这样极少有人喜欢这样的项目,我只参加过两次,并且一点也不期待会有下一次。我参加的两次,一次是初中越野,也不知道有多远,反正跑完的时候我呕吐加抽筋;另一次是高中五千或者一万,上场的原因是只要参加并跑完全程,班级就有加分。高中那次,我被很多人扣了圈,这些人里甚至可能还包括倒数第二名。有人可能会问,你这么差劲为什么还要上场呢,答案很简单,因为我们班没有别人乐意上场。每班出场2人,另一位是我们班体委,他跑到第某圈的时候抽筋或岔气退赛了。没有人敢于参加长跑,在我看来整个班都很丢脸,所以上场这种事,只好我来做。虽然成绩糟烂,但是总比弃权来得男人一点,当年我这样想。

今天,讨论这个已经不合时宜,毕竟大家都理解刘翔跟健抻断在伦敦退赛了。但是,学校运动会这种比赛既不会要了你的命,也不会影响你作为终生的体育事业。

取消长跑,已经不再只是身体素质的问题了。5000米,训练和体现男人的坚忍。尤其是在一群玩儿鼠标乐器篮球足球诗歌的男生当中,绕操场跑上十多圈。现在,我们太注重被喝彩,被关注,太期待实时的反应和成绩。如果体验成绩的感觉推迟到明天,就会有一大票人放弃无论那是多么重要的活动。如果结果再有那么一点不确定,离开的人就会更多。

但是,非实时的活动,包括计划、估算、度量,这些正是人类不同于动物之处。正是追求未来的快乐,阻止我们今天做某些事。随心所欲地挥霍,要么,你是非常富有这种东西,要么,你根本就不在乎。或者,你太年轻,还没有学会在乎。

暴雪,从来不是那种在一两分钟甚至一两个小时下一米深雪的天气现象,而是就像现在的外面,持续的一直不停地降雪几天几夜。这可以让吉林省部分学校停课,让黑龙江省在这样寒冷的天气停电。自然的伟力,并不在于突发,而在于积累。我们也需要持久的知识结构的更新,不是以月日作为单位,而是穷尽一生。如果你感到舒服了,看的书做的项目里都是你清楚了解透彻明白的,那么,就是你已经停下来开始腐烂了。成长,从来都是持续地痛苦的过程,成长的停止,不是成熟,而是腐烂。

与持续地学习不同,还有人特别欣赏灵机一动、聪明、灵活,尤其是为自己是这样的人而窃喜。我接下来要讲的故事想说明,所有这些都是没有用的。

我跟赵老师和偶像去唐山的时候,是为了一个钢厂的项目。对方提出一个需求,希望在断电的时候也能记录天车的动作,以便在恢复供电的时候再读出来。大家词穷的时候,我提出一个方案,加一个机械结构,像发条那种东西,停电的时候天车一边走,就一边结发条上弦加劲,等恢复供电,读发条的状态。

方案优秀吧,得意吧?故事没有结束。

赵老师解释说,这种技术早就存在,并且有了名字,叫做机械补偿。能想到这种方案固然说明我灵活、灵机一动、聪明,可是这之后呢,如果不知道机械补偿这个名字,难道要重新从头设计整个这个领域的成果吗?

一位王老师曾经教导我说,优秀的方案有两种。一种是你灵机一动想出来的,一告诉别人别人就会了的那种,那种你千万不能告诉别人;另一种是你即使告诉别人,别人也听不明白。这后一种,他当时举的例子是付里叶变换的某种应用。这一类的应用,往往需要学习你的人也有相同的基本功,这意味着同样长时间的努力。

和这些人类积累很多年的成果相比,那些聪明、灵机一动、灵活,基本都不堪一击。苹果教主乔布斯也不是单凭灵感做出漂亮的工业设计,他甚专门上过字体这门课程。

长期积累,一朝可以使用;甚至,看不到确切的结果,永远也没有直接地应用。忍受这些,拒绝实时的和情绪的反应,使人类从动物中分离出来。所以,我们需要坚忍,无论是过去艰难的时候,还是现在大家都在享受的时候。

长跑不仅需要坚忍,还需要持久。

大家不喜欢长跑的一年原因,是因为乒乓球、篮球、足球、羽毛球还可以交朋友,鲜有听说长跑中上气不接下气的还能发展友谊。我们真的那么渴望友谊,那么需要来自他人的肯定吗。就像很多家长训练孩子的体育运动,除了上述这些,再就是跆拳道、游泳、拉丁舞和国标。还训练孩子声乐、乐器,各种以后会在高档的人群中用到的……他们渴望的不是友谊和美,甚至不是技能,而是人脉。

那么,耐力和心肺功能呢?这些对你生存和长期工作都最重要的部分呢。我们需要阅读很多年,在将来的岁月里。但是,我们并不是把那么多个小时在一天里耗尽,那是不可能的,一天只有24个小时而已。我们只能把一生的阅读分解成很多段,每天几个小时。这需要耐力的训练,而且长期的工作也需要心肺功能。

我曾跟黄同学有一段对话。他和同学比赛做俯卧撑的时候,感觉头几个并不吃力,后面就渐渐不行了。我有做俯卧撑的经验,有一段时间每天100个,一下子就能猜到他的问题。我问,"你做的时候呼吸么?"他说,"得憋着气啊。"

这其实就是问题所在。你在做三五个俯卧撑的时候可以屏息,而在做几十个的时候,你不得不呼吸,而且呼吸,而不是胸肌才是这其中最重要的部分。短跑百米,优秀的运动员可以不呼吸,全靠无氧跑完全程,没有听说哪位可以一口气跑完马拉松的。

我们为什么需要持久?因为大部分结果都需要持久地努力。而不是一时的兴奋。"可以十年不将军,不能一天不拱卒。"你每天拱卒的好处,只有在五年十年以后才逐渐地显现出来。

所以,不计一时得失运筹帷幄的将军才比啊啊地冲上去的莽夫更男人。

其实,我们仍然生活在原始社会,这周围仍然是部落和部落的猎场。有的部落可能一直以来坐山靠水的物产丰富,但是这些都不会永恒,没有什么能够保有他们现在所拥有的。

我们仍然需要每天奔跑十几公里追逐猎物。我们的猎物与我们祖先的似乎不同,但是对于坚忍和持久的要求从来也没有改变。

当我们奔跑时,无聊、枯噪,我们应该如何处理。不知道专业的运动员或者长跑大牛们是如何做的,我每一次在俯卧撑到50个以后的时候,唯一想到的事情就是放弃。为了防止我突然停下来,我保持呼吸,在保持呼吸的同时,注意自己的动作,每一个都仔细观察评估,下一个努力做得更加标准有效。

生活本身,也是这样持久的训练。又不是童话书和过生日,每天哪有那么多的惊喜。不外乎观察评估,希望明天做得更好,也避免当惊喜到来的时候,没有心脏或者能力去承受。

长跑取消的后续里说,"即便如此,在剩下的1500米长跑项目中,不少选手已经体力不支,被同学"架着"离开了跑道。"

这让我又想起,上次承办ACM比赛的时候,有同学说这桌子摆齐工作量太大了。我说了一大顿令人厌恶的话,后来我说,"连桌子都摆不齐,咱们再跟日本人打,还会输。"

不是总有人在期待下一次战争,或者报怨不够硬气么。光嘴上硬气是没有用的,除非你认定自己有资格不需要亲自动手。我希望在下一次战争中,没有一个男人因为无法忍受劳累、饥饿、寒冷、恐惧而投降。我刚刚提到的原因,不是劳累、饥饿、寒冷、恐惧本身,而是不能忍受它们。这种承受的能力,需要长久的训练,而无法凭借一时的热血和激情完成。

男人应该如何死去?

不是在鲁莽的突袭中,而是一直跋涉,沉默、坚忍、持久地,最后死在这样的成长的道路上。


--------------------

博客会手工同步到以下地址:

[http://giftdotyoung.blogspot.com]

[http://blog.csdn.net/younggift]

20121107

我们注视的,是相同的世界吗

我们注视的,是相同的世界吗

我经常对于CSDN里的博客如何分类颇感踌躇。比如昨天,我先是在图书馆跟ZHUAMO调了约4个小时代码,然后又跟ZHUMAO去大哥那里做服务器负载均衡的咨询。两个故障在我看来原因是相同的,那么,应该归到系统维护类呢,还是编程类?

先是一大早,跟ZHUMAO通电话,问我一大早感觉如何。我说,当然不好,本来正睡觉,被打断几次,只好起床吃饭。ZHUMAO说,那你还是来吧,不然我还得再打断你几次。

吃了上午饭,我想想,还是去到ZHUMAO现场,与其远程被打断几次,不如现场讨论来得迅速。更何况ZHUMAO为我这样的半残人士准备了可以拖到眼前的那种"臂"式的显示器架,我和他结对编程的环境很是不错。

故事1 程序设计 或者 web

11点,我们开始调代码。故事1开始。

故事1。ZHUMAO打算做一个web程序,包括上传乱糟各种东西的功能。此前几经评估,准备借助 plupload 实现上传。plupload是个支持 flash/html5 等诸多客户端平台的解决方案,我们最需要的特色是 客户端部分可以把一个大的待上传文件拆成若干个小块,在服务端再组装起来,避免通常的大文件上传方案要在服务端分配与文件相同大小内存的问题。plupload 把大文件分成的小块称为 chunk。

我们选定plupload方案以后,我和zhumao,sunqc做了一些准备工作,部署了示例程序,改了一些配置,改了目录权限,以支持 web server 写操作。然后我们传了大文件,小文件,测试成功。昨天之前,zhumao&sunqc两位同学又做了一些工作,把界面改得华丽了很多,测试了传特定格式的文件。

然后,问题来了。

我昨天去的时候,ZHUMAO描述说:plupload有个毛病,上传图片的时候,会把图片大小自动修改了,改成比较小的、质量较低的。

我说:啊。

这几年来,zhumao已经熟悉我的嘴脸了。说有什么毛病,第一件事,我肯定是要看毛病到底啥样。你光说,我是啥也不信。基本上,如果你说吃了砒霜会死,我十有八九会要求你死给我看。这一条,可以参考14条原则里不要相信客户或者任何人那一条。

其实我心里还在想些别的。我在想,这哪是毛病,这明明是特点啊。上传图片一般都是为了在web站点上展示,不需要高质量,而图片压缩以后大大减小上传的文件尺寸,多好啊。就像声学钢琴,特指非三角的那种,正常按键的时候声音比较大;电钢琴如果把音量调小,你正常按键的时候,声音会比较小--某同学,这不是毛病,这是特点,因为声学钢琴不具备这种功能。如果你把电钢琴的声音调到正常,再正常按键,那至少,刚刚提到正常按键声音比较小的问题就消失了。

不过,ZHUMAO是用户及上帝,他的要求都是合理的,而且我确实能够理解,保留完美质量照片的重要性。所以我说:这特性应该能禁用吧,这个就挺像,参数resize。

ZHUMAO说,试了,不好使。删除这个特性,就传不上去照片了。

我说:啊?

于是ZHUMAO又演示一遍。果然,客户端报IO错误多少多少号,服务端没有接收到文件。

我说:哎呀?

后来还有很多技术路线的小插曲,我们还试了一些没用的。再后来,我猜测:不是啥类型的大文件都传不上去了吧?

ZHUMAO说:没有,我们测过。

我说:啊。

于是ZHUMAO开始演示。这一次,失败了。某个图片类型以外的文件,上传也失败了。然后我们又确认,上传小的图片文件时--由于不需要chunk--可以上传成功,上传大的图片文件时--由于需要chunk--上传失败。分界线正在是否大到需要chunk。

所以,这个时候发生了一个重要的变化:1.并不是改了resize参数以后上传图片失败,2.而是目前无论什么类型的文件只要chunk,上传都失败。

同样的现象:改resize上传文件失败,现在变成了不同的原因:不仅是图片,任何文件,甚至不改resize,上传也会失败。此前之所以会误会为改了resize上传就失败,是因为改了resize参数以后,测试的恰好是需要chunk的文件。

批判性思维告诉我们,要注意,如果A与B同时或先后发生,那么,我们不能简单得出A与B的因果关系,除了回归分析,还至少需要考虑到:A是导致B的唯一原因么,A是导致B的全部原因么。甚至,在上述案例中,A根本不是导致B的原因。resize修改,只是暴露出了问题,并非导致问题。

据说西域某小城,国王喜欢杀掉报凶信的人,他显然不能区分暴露问题和导致问题是两回事。我们的文化中讨厌乌鸦,大致也是这个路子。我们甚至讨厌预测不良后果的人。

然后,我跟ZHUMAO开始着手解决为什么不能上传需要chunk的大文件这一问题。所以,以前老师总是教导我们,知道问题是什么,远比知道如何解决重要。是不是还有人记得政治课上的那些题,明明我们背得一大堆好答案,考试的时候唯独不知道问的那道题和哪个答案对应。确定了问题以后,解决起来只是体力活了,我俩拆腾了4个小时里剩下的时间,解决了。resize可以通过把quality改为100保证上传的文件大小不变,甚至还可以把resize参数删除,图片就不在客户端做任何处理。

最初和后来,我们看到的是相同的故障,但是,我们心中所想的已经非常不同。先前是图片,后来是chunk。我们先前与后来,观察的是同一个世界么?

故事2 系统维护

下午15:10,跟ZHUMAO去大哥那里做咨询,故事2开始。

大哥以前想办个乐队来着,这是他的理想。我大一的时候,在迎新晚会上看他和陈师兄弹吉他,唱《青春》。他俩是谁向谁单膝跪下来着,我眼神不好没看清。不过他们不是好基友,那是因为电吉他的拾音器线不够长,跪着的那位直接拿迈克对着吉他。大哥的乐队一直也没办成,成为了IT团队的领袖。我当初也有理想来着。我跟大哥说,等我有了房子,一定要在天花板上装几个啤酒桶,下面接上水龙头,想喝的时候,哗。真过瘾啊。我的理想也没有实现,成了今天的这个样子。

我们,各自先去做谋生的或者让我们能生存下去的事了。那些伟大的理想,让更精于此道的兄弟们去实现吧。有一些人,他们应该能靠乐队活下去,有一些人...真的会有人能靠喝酒活下去么?

昨天下午去拜访的,就是这位大哥了。咨询中间的时候,大哥在电话里说,他还需要来么。我说,当然,你得来,你难道就不想来看看我么,如此难得地见到我的机会。

大哥来的时候,某台服务器正重新启动,后来的解决路线就非常清晰了。我们从头说。我和ZHUMAO没去的时候,故障现象的描述是:当访问量上升,负载增加的时候,服务器会崩溃。

我俩分别在听到这句话的时候问了同一个问题,"什么是崩溃。"

所以,到现场以后,画了整体部署的框图,我们就要求:崩溃一个给我们看看呗。

答复是:不确定什么时候能崩溃。

那崩溃时候的日志呢?

答复是:日志有,不知道什么时候崩溃的。

有位兄弟想起个时间。我们通过他们电话的时间,及ZHUMAO查了其他的一些日志,确定了崩溃时间。再查那个时间的日志--没有任何异常。

ZHUMAO说,我用AB做一个压力测试吧,先给你整"崩溃"一下。开始同学们不同意,后来从了。压力测试几次的结果是,当时服务器似乎死了,但是无一例外地,压力一消除,服务器就能从"崩溃"中自动恢复正常。

而同学们描述的"崩溃",是无法恢复,只能reset各个服务才能解决问题。我断言不是由于压力导致的,不然,压力持续下,reset以后,服务器会不停地在 崩溃-reset-正常-崩溃 之间震荡。而同学们说现象不是这样的。

最难诊断的,就是病人告诉医生,我疼,但是我也不知道哪疼。

这个时候救星来了,有一台服务器登录不上去了,怀疑被黑了。重启,用光盘重置登录密码,重启服务器。这时,大哥进门,好戏来了--网站无法访问了。

以前每次重启服务器或服务以后,据说,网站就恢复了。同学们说,从来也没有这样过,重启服务器也没用。

此处省略半个多小时的分析和实验。我们最后得出结论,至少这一次故障与负载压力之类毫不相关,怀疑此前的那些故障也都与服务器性能无关。这台同时有电信、网通、教育网IP的服务器上面还跑了一个DNS server,它域管理服务器架在网通IP上,而www服务架设在教育网IP上。而且,ZHUMAO说,网通线路不怎么稳定,并用实验证实了。

所以,当某个不幸的家伙要访问www.xxx.net的时候,他先问他的DNS服务器"www.xxx.net的IP是什么啊"。他的DNS服务器不知道,向.net根域服务器提出递归解析请求,.net根域服务器又去问--对了,就是在网通线路上的上述域管理服务器。然后,没问到,因为网通线路质量不好。

所以,全世界都访问www.xxx.net困难。这可以用通过IP而不是域名访问验证,当然,我们也这样做了。

问题清晰以后,解决就方便多了。我们把域管理服务器移到了教育网线路上。说到这里有个插曲。其实这些同学虽然也遇到一些困难,但是还真是挺有专业精神的。我要求修改域管理服务器的地址,那同学问我"不会带来其他的问题吗?"我心想,好问题,这谁能保证啊,然后说,"不能保证。"他越发犹豫,我故意说,"哎呀,就试试呗。"恶作剧的感觉,我都快笑出声了。结果,这位同学转头去看大哥,得到同意以后才操作。就本科生这样的年龄来说,非常专业。

还是说,问题清晰以后,解决本身就方便多了。解决,只是问题诊断的小小延续而已。

先前大哥的同学们猜测系统性能、应该做负载均衡,我和ZHUMAO看到的是DNS解析。大家一起看到故障现象,为什么会定义出不同的问题呢。因为,正如柯南道尔通过福尔摩斯说:"因为我们只看到我们想看到的。"

你所看到的现象,不一定是事实,我所看到的现象,也不一定是。包师兄当年在友谊商场到校医校的路上,问我,"我们如何确定观察的是同一个世界呢。"我当时毫无畏惧地说,"唯物主义者这样证实,我们修改这个世界,你也看到了这个修改,那么这是同一个世界。"后来一些年,我开始动摇。在目录A下建立文件,目录B里这些文件也出现了,你就能保证那是两个相同的目录么。如果有个程序监听目录A,然后复制所有的操作到B呢,而且,将来某一刻,这个监听程序不工作了,这还是两个相同的目录么。或者更简单的,如果换个用户登录,发现A和B不相同呢?包师兄后来去美国继续研究康德的《纯粹理性批判》去了,他本科是物理专业的。我本科是电子的,还在这里,一步没动。

你的世界与我的世界的同一问题,与此类似的,又如何确保我说的正是你所听到的。你点头微笑,示意听懂,我又如何确认你不是在表演,而事实可能是,你用"不想听"过滤了全部内容。

人生不相见,动如参与商。

--------------------

博客会手工同步到以下地址: