播客和其它

每隔一段时间,我都会到 Google Analytics 里面检查我博客的引入链接,主要关注那些个人网站,经常会发现一些有趣的人和事。今天逛到的博客提到了 Linux 下的 podcast 客户端,我忽然感了兴趣,然后就开始找一些有趣的 podcast 资源。

就客户端来讲,尝试了几个,发现 Windows 下的 podcast 客户端中,iTunes 还是最好的一个。当然,我的标准中有一条“支持代理服务器”,就刷掉了很多软件。而中文的稳定更新的 podcast 更没有多少,现在听的几个主要来自我爱 Podcast阅微堂的两篇文章。

让我比较不习惯的一个,是锵锵三人行的 podcast。这个 podcast 是由毛豆工作室 制作的,他们为 podcast 设置了下载密码。只有捐款了的会员,才能有固定的下载密码;未捐款用户则只能使用10分钟左右变更一次的guest密码下载。更绝的是,guest 密码的获取方式非常奇特,你必须准确点击到在一个 Google 图片广告上迅速移动的链接,才能看到图片形式的密码;稍有不慎,就只是点开了 Google 的广告,而得不到密码。

虽然我认为费力制作并租用服务器发布 podcast,收费提供也无可厚非,但是使用如此之戏弄用户的把戏提供 guest 密码让我无法认同。破解这种把戏其实也很简单,找出图片的链接,然后请求图片时在 header 中加上到原页面的 referer,就可以直接 GET 到图片了。当然,为了方便,可以将提取图片的 php 脚本扔到自己的服务器上,用浏览器刷新就可以直接得到密码了。

关于 podcast,我还有一个想法:有没有人将安装系统或者使用软件的教程做成 podcast?我想这样做应该很有趣,比如我们要安装 Ubuntu,只需要挂着个 mp3,按照里面声音一步一步走:“哦,现在把光驱打开,把光盘放进去,按 F12 进入启动选择界面,……”。

除了捣鼓 podcast 之外,我前几天还把 WordPress 升级到了 2.9.2。之前 2.7.1 用习惯了,尝试升级了几次都出问题,于是就一直停在了 2.7 版本。这次升级主要是考虑到安全问题,毕竟软件的时间越久越容易被人发现漏洞。升级仍然出现了一些小问题,主要的原因是 WP 运行时占用的内存超过了默认的 32M,在 wp-config.php 中加大内存就没事了。

在博客侧栏增加了来自阿里妈妈的广告,原因无它,只是为了尝试一下阿里妈妈的用户体验,钱估计是赚不到的。

上周五睡觉时,小腿脚踝上方不知不觉地被暖手宝烫出了一个滴溜溜圆的蚕豆状水泡。不能穿高帮的鞋子,只好两只脚穿不同的鞋。目前已经到医院上了三次药,在好转中。

宿舍原来空调风机功率太小,一直不暖和,2月下旬回来给敲掉了。期间下了两三场雪,供暖都快结束了,今天才装上新风机。只要开机就一股暖气片漆的味道,于是干脆放那不开它了,冷点儿也比吸化学毒气强。

我的 Facebook 帐号十几天前被关闭了,我发了封信申诉,一直没消息。昨天早上照常地清空了一下垃圾箱,在删除那一瞬间看见了 Facebook 的回信,真郁闷。不过虽然没看到回复,Facebook 是可以登录了,这是好事儿。

又薅移动的羊毛了,充 300 送 140 的公交卡。正好有张非学生卡,毕业了总是要用的,干脆充上得了。上个月是 50M 的流量,结果只用了不到 30M,这个月关了 5块 30M 的套餐,结果发现 20M 貌似又有点儿不够用了。

在 Twitter 上无意中发现一对可爱的恋人,经常连载一些类似博客的有趣的事,于是 fo 了,刚才发现那男孩儿把我 block 了,大概是不想被人关注吧。天晓得我怎么找到的这种 follower 和 following 都是 1 的用户。另外,看别人在 Twitter 上谈情说爱和吵架都是顶好玩的事情!

An IPv6 Enabled NTP Client for Windows in Python

Python NTP library (ntplib) offers a simple interface to query NTP servers from Python. But it does not support IPv6 NTP servers. I wrote a patch for ntplib to support IPv6 connections. You can download the patch file here and the patched library here.

The code bellow is a simple IPv6 enabled NTP client (ntpdate.py) in Python for Windows, using the patched ntplib. It doesn't (and won't) support Linux because the official NTP release offers IPv6 support on that platform.

#!/usr/bin/env python
# ntpdate.py - set the date and time via NTP
# An IPv6 enabled ntp client, for Windows ONLY.

import ntplib, time
from os import system
from sys import argv

def usage():
  print '''Usage: ntpdate.py  [-qh] server
Example:
  ntpdate.py 210.72.145.44      # IPv4
  ntpdate.py ntp6.remco.org     # IPv6
Options:

  -q     Query only - don't set the clock.
  -h     Print this message.

IPv6 NTP Server List:
  ntp6.remco.org               [2001:888:1031::2]
  ntp6.space.net               [2001:608:0:dff::2]
  time.buptnet.edu.cn          [2001:da8:202:10::60]
  time.join.uni-muenster.de    [2001:638:500:717:2e0:4bff:fe04:bc5f]
  ntp.sixxs.net                [2001:1291:2::b]
  ntp.eu.sixxs.net             [2001:808::66]
  ntp.us.sixxs.net             [2001:1291:2::b]
  ntp.rhrk.uni-kl.de           [2001:638:208:9::116]
  ntp.ipv6.uni-leipzig.de      [2001:638:902:1::10]
  ntp.hexago.com               [2001:5c0:0:2::25]
  ntp1.bit.nl                  [2001:7b8:3:2c::123]

Report bugs to http://solrex.org.'''
  sys.exit()

def main():
  ntp_svr = ''
  query = False

  for a in argv[1:]:
    if a == '-q':
      query = True
    elif a == '-h':
      usage()
    else:
      ntp_svr = a
  if ntp_svr == '':
    usage()

  c = ntplib.NTPClient()
  res = c.request(ntp_svr, version=3)
  t_epoch = res.offset + res.delay + time.time()
  t = time.localtime(t_epoch)
  centi_sec = t_epoch%1 * 100
  time_str = time.strftime('%H:%M:%S', t)
  if not query:
    system('time %s.%2.0f' % (time_str, centi_sec))
    date_str = time.strftime('%Y-%m-%d', t)
    system('date %s' % date_str)
  if query:
    print 'server %s, stratum %d, offset %f, delay %f' % (
           ntp_svr, res.stratum, res.offset, res.delay)
  print '%s %s ntpdate.py: time server %s offset %f sec' % (
         time.strftime('%d %b', t), time_str, ntp_svr, res.offset)

if __name__ == '__main__':
  main()

一个 Windows 对时小工具

由于在 CERNET 内,我经常需要用代理上网,没办法直连到 NTP 服务器,因此不能使用 Windows 时间服务对时。偶尔维修电脑或者不小心调整错时间,再加上电脑时钟本身就有一定的漂移,对时就变成了件麻烦的事情。

手动调时也没个参照,误差往往比较大。IPv6 网络上存在一些 NTP 服务器,Linux 下有 ntpdate 是支持 IPv6 NTP 服务器的,但是我搜索了半天,才在一篇文章上看到有人评论说 Windows 下只有一款 NTP 客户端支持 IPv6,还是收费软件——可他也没给出名字。

无奈之下想到 Python 的 httplib 是支持 IPv6 连接的,于是我就仿照 htpdate 写了一个利用 Google 的 IPv6 Web 服务器进行对时的 Python 小工具 htpdate.py。虽然误差比 NTP 大不少,但是还是在可接受范围内(不到 1 秒),而且比较方便,连日期也一块更新了。下面是代码,比较粗糙。

#!/usr/bin/env python
import httplib, time
from os import system

def main():
  conn = httplib.HTTPConnection('google.com')
  time.clock()
  conn.request('HEAD', '')
  t_rtt = time.clock()
  res_time = conn.getresponse().getheader('date')
  t = time.localtime(time.mktime(time.strptime(res_time,
                                 '%a, %d %b %Y %H:%M:%S %Z')) - time.timezone)
  time_str = time.strftime('%H:%M:%S', t)
  local_time = time.asctime()
  t_exe = time.clock()
  centi_sec = (t_exe - t_rtt/2)*100
  if centi_sec > 99:
    centi_sec = 99
  system('time %s.%2.0f' % (time_str, centi_sec))
  date_str = time.strftime('%Y-%m-%d', t)
  system('date %s' % date_str)
  print 'LOCAL  TIME: ' + local_time
  print 'SERVER TIME: ' + time.asctime(t)
  print 'LOCAL  TIME: ' + time.asctime()
  if (t_exe - t_rtt/2) >= 1:
    print 'Round trip time is too long. Time error might be larger than 1 sec.'

if __name__ == '__main__':
  main()

又是一年元宵时

今天早上,我做了个梦,梦见我爸爸躺在床上,瘦得皮包骨头。在我印象里,他这是从远方治病回来了。我走上前去,摸摸他萎缩的两腿,问他:“爸,你到底去哪儿了?怎么走那么久也不给我打个电话?我想你了。”他说:“是想给你打的,几次都没打成。”我给爸说:“爸,你儿子现在出息了,研究生都要毕业了,还找了份不错的工作。”我爸笑着说:“好啊,比我强。”我又问他:“你这次回来还走吗?”还没等他回答,梦就醒了。

起来后我给我妈打了个电话,给她说了这个梦。我妈立刻泣不成声,说昨天下雪,没去我爸坟上送灯,他这是想我们了,所以会托梦给我。安慰完我妈,挂了电话,我也没忍住,大哭了一场。

8 年了,其实我梦见爸爸的次数并不多。年年春节回老家,我都会到我爸坟前拜祭一下。今年初四,只有我一个人和姑姑家一起回老家走了走亲戚,没有去看我爸。我妈说怪她,其实我觉得该怪我。常年在外,清明也不回去、七月十五也不回去,本来只有过年的机会能看到我,结果今年也没有往坟上走一走,我爸这是怨我了。

我爸曾经是我小学四年级的语文老师,奶奶走的那天,该他上课,他什么都没讲出来,坐在讲台上哭了一节课。我爸刚走时,我没有很难过,总觉得他还在身边似的。但年龄越大,越能体会到那种子欲养而亲不在的悲伤。小时候我爸总为我的学习成绩而骄傲,说我特为他挣面子,每当考试又得高分,我都会赶快告诉我爸。可惜现在我取得一点儿小成绩,总想着要是我爸能活着看见就好了。

今年清明,我得回家一趟,去拜拜我爸。

使用 Sikuli 实现同时登录两个 Dropbox 帐户

来自 MIT 的用图片编程的 Sikuli 语言最近着实火了一把,看着对岸的程序员 Vgod 开发出如此酷的软件着实令人羡慕。但除了 Demo 之外,能不能拿 Sikuli 来 engineer a better life 呢?显然是可以的,就如 Vgod 这篇文章所说,Sikuli 有无穷的潜力,那我们就来玩儿一把,展示一下 Sikuli 的一个现实应用。

1. Dropbox

Dropbox 是一个在线文件存储系统,可以用来存储和在不同电脑间共享文件,但是一个 Dropbox 用户只有 2G 的存储空间,当我们文件多的时候,就受到限制了。而一般情况下 Dropbox 只能运行一个例程,使用多个用户貌似不可行。但是到底可能吗?

当然可能,只是我们需要多个 Windows 帐户。也就是说,每个 Windows 帐户可以运行一个 Dropbox,如果你系统里有多个帐户,就可以运行多个 Dropbox。注意,受到安全策略的限制,这些帐户必须设置密码。比如我们新建一个"dropbox"帐户,密码也是"dropbox"。

2. 笨的方法

一般情况下使用其它帐户运行程序的方式为:在程序或者快捷方式上点右键,选择“运行方式”,然后选择“下列用户”,输入你期望的用户和密码(dropbox:dropbox)来执行该程序。

3. 聪明的方法

但是这样做太麻烦了,我们可以用批处理脚本做这件事情:

start D:\Program\Dropbox\Dropbox.exe
runas /user:dropbox D:\Program\Dropbox\Dropbox.exe

但这样还要手工输入密码,有很多种方法可以避免手工输入 runas 密码,但很遗憾它们大多在 Windows XP Home Edition 上不可用。

用 Home Edition 的同志还是得交互式的输入密码。能不能不手工输呢?可以,比如 expect 就是专门处理交互的语言。不过,学起来太麻烦了吧,要不来看看 Sikuli 怎么做?

4. 使用 Sikuli

下面这个图就是完成启动两个 Dropbox 的 Sikuli 程序:

使用 Sikuli 同时启动两个 Dropbox

首先switchApp("cmd")启动 Windows 的命令行,然后wait等待那个提示符出现,然后 type() 键入一行 runas 命令,wait 等待提示输入密码,type 输入密码 dropbox 加回车 \n,bingo,出来一个 dropbox 了,最后再 type 一行启动非 runas 的 dropbox,又出来一个 dropbox。

上述程序运行结果如下图所示:

两个 Dropbox 在运行

好玩吧!Sikuli 程序就是那么简单,我从下载 Sikuli 到完成这个程序大约花了四十分钟的时间,这可比去学 expect 快多了。这下 expact 之类的交互语言在简单的场景下可以无视了。

你可以将 Sikuli 程序导出成一个 .skl 文件,据说可以双击运行,不过我尝试未成功,这是一个遗憾,希望后续版本可以解决这个问题。

5. 注册 Dropbox

您如果对 Dropbox 感兴趣的话,可以点击下面我的两个邀请链接注册,这样咱们的空间都可以增加 250M。本人将非常感谢您的支持。(如果您打算再注册一个的话,最好不要用自己的邀请链接,因为同一台电脑上激活的用户不会奖励空间。)

https://www.dropbox.com/referrals/NTE2NjMyMTU5

升级黑莓 8700 系统到 4.5.0.182

好多事情都是不做时觉得很难,做了才知道,哦,原来这么简单!给黑莓刷系统也是如此。

本来我的 8700 系统是 4.2.x 版本的,有很多主题和软件不能用,我当时怕升级麻烦,也就忍了。但是当我前两天才憧憬过的 UCWEB 黑莓版今天发布时,而我的 4.2 系统无法支持它,只好下狠心升级一把。

之前我曾经看过无数帖子,评论 4.5 的系统如何如何,也看过不少教程,该如何如何升级系统,总之一个感觉,就是非常麻烦。众说纷纭以至于连该用什么固件都不知道。但是经过几次尝试之后,我才发现了升级黑莓系统是怎么回事,根本没有我想象的那么复杂。下面给出我对整个过程的理解。

1. 到哪里下载固件?

要想刷系统,首先得有固件,到哪里下载就成了一个问题。网上乱七八糟的,众说纷纭,但是我认为本应该只有一个答案:黑莓官网。不过到官网下载固件需要国外代理,因为它禁掉了中国 IP,所以不懂翻墙的人就在其它网站找吧。

2. 下载什么样的固件?

在黑莓官网上,黑莓也不像一般的手机网站一样把一堆系统软件列出来。黑莓官网的固件是按照运营商管理的,很遗憾我们找不到中国移动和中国联通。要找支持中文固件,一般来说我们可以找香港的运营商。但是不同运营商提供的固件版本并不一样,香港的运营商固件可能并不新,这时候美国的 AT&T 反而是一个好的选择。如果需要中文支持的话,一般应该选择括号中注释为 EastAsia 和 Chinese 的固件(据我理解 MultiLanguage 并不包含中文支持)。选择版本的原则我觉得应该版本越高越好,但是不排除偏好某个稳定的版本。

3. 中文支持是不是必须的?

我之前以为必须下载的固件支持中文,装上之后才能使用中文。后来发现也不是那么回事,其实你完全可以下载一个高版本的不支持中文的固件装上,然后找一个相近版本的支持中文的固件,把里面中文支持部分的 .cod 文件找出来,然后用 JavaLoader 装到手机里,这个系统就可以支持中文了。简而言之,中文支持仅仅相当于应用软件而已,可以单独装的,只是需要用特别的方法装。

4. 如何安装固件?

这个就不用我说了,网上一堆一堆的教程。简单的流程就是先将固件安装到 Desktop Manager 里(其实是放到某个目录下),DM 识别了,然后装到手机里。我注意到的一点是:安装固件时最好不要联网,不然黑莓的 Desktop Manager 会老在那找软件更新,增加本来就很长的安装时间。

5. 安装固件时需要不需要备份?会不会对数据有影响?

不需要备份,安装时会自动备份和恢复。对黑莓自身应用,比如短信、通讯录等不会有影响,但是对第三方应用的数据会有影响,比如 Gmail、Mobipocket Reader 等。这也是没办法的事,第三方的应用数据本身也备份不出来。但很奇怪的是手动添加的 Service Book 和 TCP 的 APN 也会消失,只能重新修改。

6. 高版本的系统会不会很慢?

我曾经在网上看过一个耸人听闻的说法是 8700 4.5 的系统需要半个多小时才能启动,让我非常吃惊和迟疑,不敢升级系统。实践证明他大概说的是固件安装过程中的第一次启动需要那么长时间,之后的启动时间和 4.2 系统也没什么明显区别。至于内存占用啦、程序运行速度啦、网速啦,在使用中没有明显感觉。

我觉得将系统从 4.2 升级到 4.5 的优势是:可用的应用和主题更多了、系统和字体更漂亮了;劣势可能是占用的存储空间多了点儿、少了个拼音输入法。除此之外没有其它明显区别,我自己认为值得升级。

我喜欢的黑莓应用

上次手机丢了之后,为图便宜,我换了一个黑莓 8700,黑莓大概是我能负担起的最便宜的智能手机系列。虽然和原来的手机相比,8700 不带照相和扩展卡功能,但各种应用让我觉得比传统手机好玩多了。自从开始玩黑莓的这些有趣应用后,我渐渐觉得以后什么手机应用多,才能占到市场先机。以 Google Android 的开放平台以后肯定有不错的表现。

折腾了一段时间后,下面是一些我喜欢的黑莓应用:

1. Opera Mini 浏览器

如果没有网络,智能手机至少会少了一半的乐趣,现在很多网站都支持手机浏览了,包括我的这个博客,所以一个好用的网络浏览器非常重要。其实 Opera Mini 算不上很好用,但至少比黑莓自带浏览器好用多了,主要是在网页格式化方面。我比较看好的浏览器是 UCWEB,因为它支持标签功能,在 GPRS/EDGE 的低速网络下可以后台打开标签以节省时间。UCWEB 黑莓版已经在内测,希望能尽快推出。

2. Google Maps

通过黑莓上的 Google Maps 我才第一次知道原来没有 GPS 也可以定位。Google Maps 使用基站定位的标称误差大约在 600 米左右,实际误差我觉得大约在三四百米内。虽然误差比较大,但是在北京城里晃悠时,这个范围的误差足够能判断行进方向是否正确了,可以少问很多路。另外还有路线查询功能,有点儿烂,但好歹能用。

3. Google Sync

同步联系人和日历的工具,可以将手机联系人与 Gmail 联系人同步,将手机日程表与 Google 日历同步。这个应用实在是太酷了,在同步完联系人到 Gmail 中之后,我再也不用担心手机丢了会失掉很多人的联系方式。编辑自己的日程表也可以在电脑上进行,不用在手机上慢慢地敲字了。而且只要登出 Google 帐号,就可以删除所有联系人,换手机时候很方便。

4. Key Master

我平时不喜欢用鼠标在一堆图标中找应用程序,所以在电脑上我都是用 Launchy 来启动应用程序。Key Master 是在黑莓上自定义快捷键启动应用程序的工具,非常好用,一般情况下我都不需要再进黑莓的 Applications 目录用滚轮来找程序。

5. Mobipocket Reader

这是一个电子书管理和阅读工具,有手机版和电脑版。电脑版和 iTunes 类似,先把电子书导入到电脑版里,然后通过数据线发送到手机上的 Reader。这不是它最酷的地方,它最酷的是可以直接导入 .pdf, .html, .chm, .epub 格式的电子书。如果有某本书的 pdf 版,就不用再费尽心机寻找 txt 版了,直接导入就可以在手机上阅读。Mobipocket Reader 对 pdf 的重新格式化在我看来已经到了值得称赞的地步,太牛了!

6. 凌波微步 SmartDail

这是一款智能拨号软件,由于黑莓的电话簿不支持首字母查询功能,在电话簿中寻找联系人比较麻烦。这款软件可以支持名字首字母查询,定位联系人非常方便。

7. MidpSSH

黑莓上的 ssh 客户端,不支持中文,但是紧急情况下用来进行简单的服务器维护足够了。

8. Gmail 手机客户端

这个不用解释了。

9. 点讯输入法

用这个输入速度比黑莓原生输入法快多了,主要体现在两个方面:选字快和匹配率高。缺点就是切换麻烦,或者在一些应用中只能拷贝粘贴。

10. BerryFetion

这个软件也相当酷,可以在短信上直接选择“使用飞信回复”,可以省不少短信费!

11. Btalk

黑莓上的 Gtalk 客户端。由于官方的 Gtalk 黑莓版不支持个人用户,开源的 Btalk 让这变成了现实。但是实话说,谁用外出时还用手机挂 Gtalk 呀(又没经验值),也就是偶尔用一下而已。

12. AutoLock 和 TinyLock

自动锁屏软件,用处不大。

剩下还有一些应用,BBWeather, CallAssistant, MobCal, Anyview, BBNotePad 之类的,装上几乎没有用过,也就不评论了。

还有一方面的应用我觉得非常遗憾,我一直没有找到很棒的记事本软件。我希望这个记事本软件能支持(以优先级排序):1. 自动保存,比如15秒保存一次;2. 导出到电脑;3. 支持点讯输入法。不知道这样的应用存在不存在?

PS:在应用之外,还有一款软件不得不提,就是 BlackBerry Master Control Program,简直是安装黑莓软件的神器呀,比黑莓原版的 Desktop Manager 要好太多了!

亲历卓越“硬盘门”事件

前天晚上看到有人在推上讨论卓越超便宜的 118 元 320G 硬盘,过去一看居然是真的。其实经过“25 元门” 之后,我知道这是几乎不可能的,其实我也知道即使我下了单卓越也是会赖掉的,但是我还是抱着“全民调戏,重在参与”的心理加入了抢购大潮,并且进一步散播了这一消息...

事实证明我的预料是对的,我下的两个硬盘的订单在保持 44 个小时后,被卓越取消,卓越再一次(无耻地?成功地?开心地?)赖掉订单:

尊敬的客户:

您好!感谢您的订购。

我们抱歉地通知您,您在卓越亚马逊网站上购买的劲永牌320GB移动硬盘的价格出现错误。卓越亚马逊上有数百万种商品,因此有些时候难免会出现这类问题。根据我们在卓越亚马逊网站上公布的使用条件中的价格政策:http://www.amazon.cn/static/claim.asp?uid=478-5181363-0560506,出现商品价格错误问题时,如果商品正确价格高于错误的标价时,我们不得不取消您的订单,并且通知您。因此,您的订单已被取消。如果您仍然想购买这个商品,请根据正确的价格再次购买。

对于就此给您带来的不便,请您接受我们真诚的道歉。今后我们将继续努力,尽力确保卓越亚马逊上不再出现此类问题。

我们衷心期待继续为您提供服务。

卓越亚马逊客户服务部

不过我依然很开心能亲身见证这一过程。:)

关于 SOCKS 代理的远端 DNS 解析

经常使用 SOCKS 代理服务器的同志们会发现一种现象,即使 SOCKS 代理服务器设置正确,某些网站仍然无法访问,比如某著名微博网站。其一般原因都是 DNS 污染 (DNS cache poisoning)。

值得庆幸的是 SOCKS 5 可以通过将域名直接提交给 SOCKS 服务器来进行远端 DNS 解析,即 Address Type 0x03。DNS 服务是 Internet 的基础服务,要求 DNS 解析应当尽量地快,所以浏览器默认不会使用远端 DNS 解析。不过当使用自动代理设置脚本(.pac )时,以 SOCKS5 而不是 SOCKS 返回代理地址,可以支持远端 DNS 解析。

网友 forkei 的重要评论

chrome 的 Proxy Switchy 1.4.2 版本插件可以很好的解决这个问题。Firefox 的 FoxyProxy 插件也可以很好的解决 DNS 污染。支持插件扩展功能的浏览器功能就是强大。IE 内核浏览器和 opera 只有通过 polipo 或者 privoxy 将 socks 代理转为 http 代理才行,麻烦。

RSS Feed 迁移方法

由于政策的调整,目前很多博主都将博客域名从 .cn 迁出,相信很多朋友都会遇到 RSS Feed 迁移的问题。如果一直使用 Feedburner/Feedsky 这种第三方烧录网站管理订阅,只需要更换第三方抓取的源即可;但是如果之前订户多用 WordPress 原始的源 example.cn/feed/、example.cn/?feed=rss2,或者使用自定的域名 feed.example.cn 的话,当域名迁移时,原来的 example.cn 被弃用后,订户就无法得到文章更新了。

我之前一直使用 feed.solrex.cn 作为 Feedsky 的自定义域名,因为我觉得 solrex.cn 可能比 feedsky.com 更长久,后来发现这是非常愚蠢的想法。当我把域名迁移到 .org 时,就面临 feed 迁移的问题。

最简单的方法是将原来的 feed url 重定向到 Feedburner/Feedsky,但这要求网站主必须仍然控制原来域名,那就没有更换域名的必要了。

或者使用一篇博客来通知订户更换 feed url,但是实践证明这种方法收效甚微。很多人(包括我)不会去看自己使用的是什么源,认为自己使用的就是正确的 feed url。

起初我是使用的直接重定向,但后来一封域名注册商的邮件,威胁如果不办理某些手续,24日之后会停止我的 .cn 域名解析。我想,还是用一些略显卑劣的手段通知大家更换订阅源吧。这种卑劣的方法是:如果使用原来的源订阅本站,就会看到每天一篇的“网站迁移通知”,直到用户更改订阅源,或者无法忍受直接删除 feed。

其技术实现方法是:使用 php 模仿 WP 的 rss 源生成一个 xml 文件,该文件只包含一篇文章,将原来的源指向它(或者 url 重定向到它)。该 xml 中的更新日期、文章 url 每天更新一次,这样阅读器就会认为博客有更新,把这篇文章抓取回去。我本以为阅读器是根据更新日期判断文章是否重复,后来发现是根据文章 url 来判断。为减少工作量,我们可以将文章的 url 指向某篇目标文章,然后在 url 后面加上 “?date=***”,这样阅读器就不会认为是同一篇文章,而且读者仍然能够点入目标文章。

方法很简单,如果您比较懒的话,可以参考我使用的文件(也可以从这里直接下载 php 源代码):

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'."\n"; ?>
<?php echo '<?xml-stylesheet type="text/xsl" media="screen" href="http://feeds.feedburner.com/~d/styles/rss2chinesetwfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?>'; ?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0">

<channel>
    <title>Solrex Shuffling</title>
   
    <link>http://blog.solrex.org</link>
    <description>Engineering a better life, programming a great future.</description>
    <pubDate><?php echo date('D, d M Y ', strtotime("+7 hour")); echo '00:00:00 GMT'; ?></pubDate>
    <generator>http://wordpress.org/?v=2.7.1</generator>

    <language>en</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
        <item>
        <title>站点迁移通知-<?php echo date('d M Y', strtotime("+7 hour")); ?></title>
        <link>http://blog.solrex.org/?p=638679&amp;q=<?php echo date('Ymd', strtotime("+7 hour")); ?></link>
        <comments>http://blog.solrex.org/?p=638679&amp;q=<?php echo date('Ymd', strtotime("+7 hour")); ?>#comments</comments>
        <pubDate><?php echo date('D, d M Y ', strtotime("+7 hour")); echo '00:00:00 GMT'; ?></pubDate>
        <dc:creator>Solrex Yang</dc:creator>
       
        <guid isPermaLink="false">http://blog.solrex.org/?p=638679&amp;q=<?php echo date('Ymd', strtotime("+7 hour")); ?></guid>
        <description><![CDATA[您好,您之所以看到这篇文章是因为您仍在使用被遗弃的 feed 地址 http://feed.solrex.cn 订阅我的博客Solrex Shuffling。我已经将网站从 http://blog.solrex.cn 迁移到了 http://blog.solrex.org。由于 .cn 域名潜在被删除的危险,为了不丢失和您交流的渠道,我不得不出此下策以每天一篇博客的方式提醒您更新 feed 地址,希望您能谅解!...
]]></description>
            <content:encoded><![CDATA[<p>您好,您之所以看到这篇文章是因为您仍在使用被遗弃的 feed 地址 http://feed.solrex.cn 订阅我的博客<a href="">Solrex Shuffling</a>。我已经将网站从 <a href="">http://blog.solrex.cn</a> 迁移到了 <a href="">http://blog.solrex.org</a>。由于 .cn 域名潜在被删除的危险,为了不丢失和您交流的渠道,我不得不出此下策以每天一篇博客的方式提醒您更新 feed 地址,希望您能谅解!</p>
<p>如果您觉得<a href="">本站</a>对您还有点儿用处,可以使用以下方式继续订阅:</p>
<ul>
<li><p>如果您使用离线阅读器,请将本站的 feed 地址 <a href="http://feeds.feedburner.com/solrex">http://feeds.feedburner.com/solrex</a> 或者 <a href="http://feed.feedsky.com/solrex">http://feed.feedsky.com/solrex</a> 添加到您的订阅器中,并删除现有这个 feed。</p></li>
<li><p>如果您使用在线阅读器,比如 Google Reader、抓虾 之类,您可以点击<a href="">这里</a>到本站首页,在右侧选择您的在线阅读器,重新订阅,并将现在这个 feed 删除。</p></li>
</ul>
<p>如果您觉得<a href="">本站</a>对您不再有用,可以使用以下方式退订:</p>
<ul>
<li><p>如果您使用离线阅读器,请咨询阅读器帮助如何删除 feed,一般情况下在 feed 上直接点 del 键即可。</p></li>
<li><p>Google Reader 用户可以在左侧 Subscriptions 中找到本 feed(一般名为 Solrex Shuffling),将鼠标移动至其上,您会发现右侧有一个向下的小箭头,点击箭头,您就会发现有 Unsubscribe 的选项;或者您也可以到右上角的 Setting 中,点入 Subscriptions 标签页,对所有 feed 进行管理时删除 Solrex Shuffling 这个 feed。您可以在<a href="http://www.google.com/support/reader/bin/answer.py?hl=zh_CN&answer=73062">这个页面</a>找到更多帮助。</p></li>
<li><p>抓虾用户可以在<a href="http://zhuaxia.com/help.php#3_3">这个页面</a>找到退订的帮助。</p></li>
<li><p>其它在线阅读器用户请咨询该网站帮助。</p></li>
</ul>
<p>无论如何,感谢您一直以来对本站的支持,我希望能在<a href="">新的站点</a>继续收到您的批评或支持!祝您好运!</p>
<p>Solrex Yang</p>
<p><?php echo date('D, d M Y ', strtotime("+7 hour")); ?></p>
]]></content:encoded>
            <wfw:commentRss>http://blog.solrex.org/?p=638679&amp;q=<?php echo date('Ymd', strtotime("+7 hour")); ?>/feed/ ?></wfw:commentRss>
        </item>
</channel>
</rss>

您可以到 feed.solrex.cn 查看效果。

我的 2009 报表

2009 年,我第一次开始认真记账,使用的是“雙胞胎拔拔”的“電子式家庭記帳簿”。由于 WPS Office 无法支持很多 Excel 的高级功能,所以只能使用低版本的 V1.x。为了避免误操作,平时还将 xls 文件备份到 Dropbox。

一年来,基本上能想得起的花销都记了下来,总算形成了一份我的 2009 年报表。结果很悲剧,年终盘点,支出超过收入 1635.44 元。我原以为这每月 759.5 块的补助能使我收支平衡呢...还好我还有点儿积蓄,看来我还是高估了自己的节俭能力。

我的 2009 报表

启用新域名 solrex.org

2017年更新:博客已经切换到 姓名拼音.com 域名,以下内容已经属于历史

各位,即日起本博地址更换为 http://blog.solrex.org,原 solrex.cn 域名将逐渐作废。若有加本站为友链的朋友,麻烦您更新一下地址;使用 feed 地址 http://feed.solrex.cn 订阅本站的朋友,也请将 feed 地址更新为 http://feeds.feedburner.com/solrex 或者 http://feed.feedsky.com/solrex。谢谢!

另外,本站目前已经支持手机直接浏览,用手机浏览器访问 http://blog.solrex.org 直接看到的即是窄屏界面,无需再访问之前的 /wap/ 目录。

恰逢年底,许多人都在总结,屡次的搬迁和被搬迁,我也趁这个机会回忆一下自己博客迁移的历程。

  • 2004 年 9 月 29 日

    南大小百合 BBS 博客写下第一篇日志。可惜,现在连 isince2003 这个 ID 都因生命力太低被清除了。

  • 2005 年 6 月 12 日

    在当时的 MSN Space 开博。因为某些原因,后来被自己封闭了。

  • 2006 年 7 月 13 日

    因为受不了 MSN Space 的经常性被封,在百度空间对外开放时,抢先申请了一个,开始将更新同步在百度空间。三个月后对百度空间失去兴趣,遂废弃。

  • 2006 年 10 月 29 日

    买下了自己的 .cn 独立域名,但是依然没有主机空间,只是定义了几个域名转向。

  • 2007 年 2 月 3 日

    丢弃原 MSN Space,申请了一个新的 Live Space,并同步在 Blogspot 上更新。

  • 2007 年 6 月 18 日

    开始使用 WordPress 博客系统,在 yo2.cn 上安家,并开始使用独立博客地址 http://blog.solrex.cn

  • 2008 年 12 月 24 日

    对 yo2 很满意,因此关闭同步更新的 Blogspot 站,技术文章也不再同步到 Live Space。

  • 2009 年 5 月 16 日

    博客迁出 yo2,主要原因是当机时间太长,频率太高,而且过滤关键词。Eric 师兄两年来一直为我的主页提供托管空间,这次就把博客也迁了过去。

  • 2009 年 9 月 24 日

    Eric 主机空间所在服务器 IP 被封。由于在找工作的关头,希望几年来积累的技术博客能起些作用,于是承蒙信文君收留,博客再次搬迁

  • 2009 年 12 月 14 日

    虽然域名还有一年才到期,看着友链的一些网站变成 Connection reset by peer,某些机构这些让人寒心的行为还是让我下定决心遗弃 .cn 域名,重新在 Godaddy 注册了 solrex.org,并将所有 .cn 的链接 301 永久重定向到 .org。(在我的忽悠下更换域名的还有 Iron-feet 同学)

总的来说,这就是一个折腾的过程,但我从这折腾中获得了很多乐趣——除了某些被折腾的经历外。值得庆幸的是写下的文字都得到了保留,于我而言是一笔宝贵的财富。我以前从不写日记,从开始使用博客才有了记录生活的习惯,现在回头看看,还蛮不错的。

心中一块大石落地

从找到工作以来,我就在忙论文,因为中科院的硕士毕业是要发表论文的。还有半年临近毕业,已经火烧眉毛了,因此我一直生活在无法按时毕业的恐慌中,也不愿意在博客上多讲,可以发现我最近两个月的更新非常少。

今天是中期答辩的日子。因为没有文章,我很怕答辩时候被枪毙掉,那我只能延期毕业了。但是,昨天正在反复修改答辩幻灯片的时候,收到了一条天大的好消息,我投往 ICC 2010 的一篇文章被录用了,而且还是 oral session!ICC,IEEE 通信学会的旗舰会议啊,我这个小硕实在是太满足了,太满足了,顷刻间,我内牛满面!

再看看审稿意见,我不得不赞叹我的运气。三个审稿人,4444,4444,4434;修改意见里,一个是“没特别的修改意见”,一个是“文章太干巴,应该生动些”,只有最后一个提出了一个切实的修改意见。看到这样友好的评审结果,我又一次内牛满面!

于是乎,两篇论文,一篇已录用,我的中期答辩顺利通过。从目前来看,毕业已经不成问题,谢天谢地!我也总算不用再羞羞答答,敢挺直腰板说俺也是搞过科研的人了。

京郊云佛山一游

其实算不得游云佛,只是在云佛山度假村住了一天。12月16、17日实验室20周年庆,年会选择在了密云县的云佛山度假村。除了开会之外,还有一些娱乐活动,我也就初体验了一把保龄球和滑雪。

云佛山度假村的保龄球馆挺旧的,经常发生卡住的情况。虽然以前没有玩过,但是我感觉只要手稳的话,不滑下球道还是比较容易的,就怕想使劲却失去对方向的控制。第一局什么也不懂,扔了七十多分。本来只有一局比赛,后来看没人继续过来玩,我们就又开了一局。这时候开始注意步法,很奇怪的是别人可以做到右手出球时左腿在前,我却无论如何尝试都是右手出球时右腿在前,所以姿势有点儿诡异。第一局用的球比较轻,方向虽然不偏,但是击倒的瓶子比较少。第二局换了重一点儿的球,很费劲,扔了一百一十多分。刚开第三局,时间就到了,只好吃饭去。出了球馆就觉得手指头真累呀,尤其是扣球的中指和无名指,相当疲劳。也不知道是不是步法错误,左脚脚心忽然开始有点儿疼,不过并不严重。

中午和晚上玩了会儿“三国杀”纸牌,第一次玩,整个过程基本上都是别人对我的扫盲教学。剩下时间开会不提。晚会抽奖,没我的份儿。

第二天滑雪,南山雪场,据说是北京最好的雪场。浪费了一些时间在领雪服和雪具上,集体活动嘛,总是不可避免。刚穿上滑雪板的时候,很不适应,在平地走起路来太痛苦了。一步一步地走,会滑;用雪杖推,推不动。上初级道顶端的履带运行很慢,我也就趁机观察了一下那些滑雪教练的教学。发现初学的技巧很简单,就是内八字利用摩擦力控制速度,刹车类似于 T 刹,不过那一横在前面。于是就用自己总结的技巧开始滑了,全赖有轮滑的底子,基本上没怎么摔跤,滑得不亦乐乎。南山雪场的确不错,有两个中级道,三个半初级道,我们去的时候开了两个半,人并不算很多,等履带或者小滑车的时间都不算长。

中午在雪场的食堂吃饭,所有的饭都是35元,有面条和盖浇饭之类的。味道还可以,不过价格是真贵,看见有自己带桶装方便面过去泡的,不失为一个好想法 :)

玩了一上午的初级道,下午壮着胆子上了一下中级道。从下面看着还好,但是坐缆车上到最顶上,再往下看,真的有点儿怕了。尤其是最顶上那个坡,非常陡,往下滑时,觉得速度都快超出自己控制了。很怕摔倒,更怕被后面的人撞到,还好有惊无险。那个速度感非常刺激,大概是因为这时候身体在你控制和无法控制的临界点吧,感觉很不一样。滑了七八圈之后,最惊险的事情发生了,下缆车时没下好,摔倒了,刚抬起头,后脑壳就被缆车底部碰了一下。还好没大碍,后来想想真后怕,不应该那么早抬头的,应该等缆车过去再起来。下来后心有余悸,就没敢再上去了,也累了,到初级道滑了两圈就去还雪具退场了。

脱完雪鞋出来,发现小腿都软了,胳膊也酸痛。回到车上没什么力气,聊聊天,然后就在回程的路上睡着了。到北京时正好赶上高峰期,很堵,而且暖气开得太足,快到学校时候感觉车上闷得不行,身体很难受。于是下车时候非常匆忙要逃离这个闷罐子,然后就悲剧了,跟随了我将近三年的三星 E908,不见了。更悲剧的是——我第二天早上才发现这一事实!

所以,人生就是一个茶几呀!稍觉安慰的是,好歹已经用了三年了,而且恰好一个星期前对联系人做了备份,所以还算不是特别悲剧。

另外,一个师兄滑雪时被别人撞伤了胳膊,还住院了。鉴于这些危险经历,提醒要去滑雪的朋友,一定要多加小心!

因为真实才宝贵

读大学时我很佩服一个老师。他教过我两门课,两门都是计算机类的课程,在数学系并不很受欢迎。他讲得不错,人很好,但这不是我佩服他的原因。我佩服他,主要是因为他说真话。他敢在课堂上讲他的经历,讲那些年轻的鲁莽和中年的困扰,讲他的爱情的开始和结束,以及那些做过的好事和坏事。

说真话——这一点很难做到。我写博客,越写越不真,看的人越多,就越不敢写。所谓白纸黑字,写下来,就要后怕很多事。隐私的话,怕被有恶意的人利用;针砭的话,怕被人抓住把柄;牢骚的话,怕被相关的人误解。很慷慨地写下自己的得意和风光,却吝啬于记录下自身的失意和落魄。在互联网的一个小小角落留下点儿自己的印迹都要想那么多,可见一个“真”字有多难得!

昨天 ironfeet 从我这借走一本书,我才想起来还欠一篇自己给自己承诺下的书评。这本书的名字叫做《我是一只 IT 小小鸟》。

我开始并不看好这本书。这本书的作者里有几个是我的师兄和朋友,他们都是很杰出的人,丝毫没有诋毁的意思,但是我认为有多少人会买几个年轻人写的书呢?因此这本书推广的九月份 China-Pub 九周年庆生会,我和它的几个作者和编辑一起参加了,但是出于对读物的挑剔,我并没有掏钱买一本。

China Pub 九周年庆生会合照
(图片来自 Linjian 博客)

后来有了点儿时间,我想想自己受过这几个朋友的很多帮助,而且 EricLinjian 都提到过要将稿酬用于公益事业。那么至少出于对朋友的尊重和支持,我觉得有必要买一本来读读,于是我就到卓越上网购了一本。

和其它书不一样,这本书我不是一口气读完的,而是按照感兴趣的顺序翻看了每个人的故事。然后我忽然发现:这不是我想象的那种"IT 牛人炫耀帖合集"。首先,里面有些人其实算不得通常意义上的“牛人”;其次,里面有很多人抑制住了炫耀的欲望,写的是真挚的东西。其实,读任何故事,精彩的往往不是一帆风顺的。如果一个人讲他的经历是把握住了任何时代的脉搏,永远站立在时代大潮的顶端,那么他的故事会很乏味,我很开心地看到这些年轻的朋友们没有这样写。其中某些内容,我想,也许他们平时都不会和别人谈起,但是他们却怀着与人共享的良好意愿写了下来。写自己的经历,不难,但是对于年轻人来讲,能平静地讲述过去的真实故事,并不容易。

大学的时候,我经常读一本杂志,叫做《中国青年》。其中我挺喜欢的一个专栏,叫做“我或我身边青年的生存状态”,《我是一只 IT 小小鸟》大概也能算成“我身边 IT 青年人的生存状态”了。在内心冲突挣扎的青年时代,有一些这样的书和文章可以给自己参考和启迪,知道自己“不是一个人在战斗”,真好!

百度新人开放日见闻

前天收到百度邮件说邀请约百个校园招聘录取同学到百度大厦参加开放日活动,最近非常忙,本来打算推掉不去的。后来想想见见未来的同事也是有好处的,于是今天就横穿北京城到上地的百度大厦转了一圈。

先说说新落成的百度大厦。虽然有些人嫌它内部结构过于复杂,但我还是很喜欢的,以前南大浦口校区的教学楼比它弯弯绕多了。大厦外面有篮球场,一楼有乒乓球场,地下一层有很大的健身房和瑜伽室,食堂也在负一楼。

每层都有很多休息区,这一点我非常欣赏。休息区有免费的水果、纯净水和咖啡,零食贩卖机也比外面便宜一些。整个大厦几乎都是玻璃幕墙,阳光的通透性很好,负一楼、五楼顶和七楼顶都有花园,散散步挺不错的。

最好玩的是三楼还有专门的睡眠室和母婴室,七楼还有两个禅院。整个建筑唯一不方便的地方就是门禁太多,几乎每个门都有门禁,连进个电梯间都要刷卡。

虽然参加活动的总人数挺多,但是分到部门也就那么几个人。eCom 总共来了九位同学,其中有一个是和我一起面过斯伦贝谢 BGC 的北航女生,还有一个是我相熟的一位 IBM 前辈带过的人大男生。有点儿关系的居然占到 1/4,这世界真小!了解了一些部门的具体结构和工作内容,我想以后我应该是在 eCom 做后台相关的开发工作了。

没有管饭,每人发了本“brainwash”的书——《百度世界》。坐地铁回来的,在复兴门坐一号线,历史上第一次被工作人员硬推入车厢中。被风吹了一路,前两天刚刚好转的鼻子又有点儿不舒服了,头晕。这学期来一直很忙,都顾不上锻炼,导致抵抗力严重下降。打个流感疫苗把我的鼻炎症状加重很多,赶紧好起来吧。

写在一个电闪雷鸣的雪夜

从窗口望出去,橙黄色路灯照射下堆满积雪的屋顶散发着苍白的光芒。远处已是昏暗不清,雾罩着,看不到是否藏着别致或者异样的风景。此时心中的抑郁也许和这雪夜一样,除了眼前照亮的这点儿空间,似乎无它路可寻。

罕见地在雪夜看到红色的闪电,听到轰隆的雷声,这在汉乐府中描述的奇景不知道算不算是帝都的特色?在这样的夜里,会有几个人像我一样望着窗外的雪景,想着心中的愁绪呢?

唉,问题在,感叹也于事无补,还是洗洗睡吧。

为求职事谢诸君

我没有料到我的求职之路会那么快地结束,但事实就是如此。虽然具体细节不能泄露,我想未来雇主的名字还是可以说一下的——非常感谢百度公司,给了我期盼已久的 offer。从九月中旬开始,到十一月初结束,中间也经历了不少公司的笔试面试,有甜有苦,个中滋味,相信品过的诸位都知道。

我不会公开写什么面经,也不会炫耀自己拿了多少 offer,相反,我拿到的并不多,因为结束地太早。我的要求并不高,百度给了我很满意的 offer,而且在接触的过程中,我以及我的朋友们都感到百度的 HR 以及面试官对人非常 nice。因此在接受百度 offer 后,我就推掉了其它所有公司的笔试和面试邀请——我并不是那种在求职过程中享受到很多乐趣的人,世界上还有很多有意义的事情可以做。

在整个求职的过程中,我得到了很多朋友的无私帮助,让我非常感激。这里面有的推荐我参加面试,有的直接给我面试机会,有的给我讲解面试技巧,有的和我讨论笔试面试中遇到的难题,有的帮我打探内部消息,不一而足。能得到这么多好人的帮助,我觉得自己非常幸运。希望能借我的博客这互联网的小小一隅,表达对诸君的谢意(以拼音序):

百度的杨帆师弟、张弦小姐(《IT 小小鸟》作者)和赵柏敏师兄(曾经的面试官,现在的朋友);
和我一起奋斗的北大小伙蔡白银和曹磊;
博文视点的周筠老师
HP 的 Shin-Ming Liu;
IBM 的甘志博士李获鼎师兄
以前的老板 Intel 的 Sun Chan;
MSRA 的刘未鹏师兄(《IT 小小鸟》作者);
纳拓软件的 Yong Liu;
农行的高飞师兄;
Opera 咨询的吴新雨师弟
Synopsys 的陈怀兴先生
泰为科技的 John Zhao;
淘宝网的马震先生和章文嵩博士;
腾讯的王信文师弟
新浪网的刘立先生和张慧聪先生;
和我一起奋斗的中科院同学王捷

Fix Black Screen After Boot Problem of Ubuntu 9.10 on D630

Platform: Dell Latitude D630, Nvidia NVS 135M, Intel CPU, Ubuntu 9.10

Problem:

1. Boot from livecd, select install. After a glowing ubuntu Symbol, screen shows nothing, even no CLI.

2. After installation with "text mode", boot from HD. After a glowing ubuntu Symbol, screen shows nothing, even no CLI.

Solution:

I am not very sure whether this problem is caused by the NV 185 driver(nvidia-glx-185). Installing or removing this package gave no help. I googled a lot, found many people encountered the same problem. However, no answer could work on my laptop. Then I tried to install NV driver manually...it works! So, here is the fix:

1. When you get the GRUB boot menu screen, press 'e' to edit the fist entry. Add a word 'single' after 'linux /boot/vmlinuz..... quiet splash', then press 'Ctrl+x' to boot. (I cannot enable networking in recovery mode, so I tried with the single mode.)

2. Select the 'netroot' entry. You will get a root command line with network support.

3. Download the latest NV driver for linux (2010-11-3):

# wget http://us.download.nvidia.com/XFree86/Linux-x86/190.42/NVIDIA-Linux-x86-190.42-pkg1.run

[You can visit http://www.nvidia.com/object/unix.html for the latest NV driver.]

4. Install development tools to build NV driver on you os.

# apt-get update
# apt-get install build-essential

5. Install the NV driver:

# chmod u+x NVIDIA-Linux-x86-190.42-pkg1.run
# ./NVIDIA-Linux-x86-190.42-pkg1.run

6. Reboot.

If you are using a livecd, please use the "text mode" to install Ubuntu 9.10. After installation, try the solution above.

Ubuntu 9.10 启动后黑屏的解决方法

平台: Dell Latitude D630, Nvidia NVS 135M, Intel CPU, Ubuntu 9.10

问题描述:

1. 从 livecd 启动后,选择安装,在白色 Ubuntu 图标闪烁结束之后,无任何屏显,连命令行都没有。

2. 用文本模式安装完成后,从硬盘启动,在白色 Ubuntu 图标闪烁结束之后,无任何屏显,连命令行都没有。

解决方法:

我不太清楚是不是 NV 的 185 驱动有问题(nvidia-glx-185),安装或者删除它对状况没有任何帮助。我搜索了一下,发现很多人遇到和我类似的问题,不过没有任何解决方法可以在我的电脑上工作。无奈下我尝试手动安装了一下 NV 的最新驱动——居然解决了!下面是我的解决方法:

1. 当你进入 grub 启动菜单选择屏幕时,在第一条上按 e 进入编辑状态,在 'linux /boot/vmlinuz..... quiet splash' 这一行最后添加一个单词 single,然后按 Ctrl+x 启动。其实 recovery mode 能做类似的事,但是 9.10 的 recovery mode 好像不能启动网络,所以只好自己进入 single 模式了。

2. 启动后选择 'netroot' 选项,进入带网络的 root 命令行。

3. 下载最新的 NV 驱动(2010-11-3):

# wget http://us.download.nvidia.com/XFree86/Linux-x86/190.42/NVIDIA-Linux-x86-190.42-pkg1.run

[你可以先访问 http://www.nvidia.com/object/unix.html 查看 NV 最新驱动的地址。]

4. 安装编译 NV 驱动需要的编译工具:

# apt-get update
# apt-get install build-essential

5. 安装 NV 驱动:

# chmod u+x NVIDIA-Linux-x86-190.42-pkg1.run
# ./NVIDIA-Linux-x86-190.42-pkg1.run

6. 重启

如果您使用 livecd 安装 Ubuntu 9.10 的话,您应该选择 "text mode" 进行安装。成功安装完成后,仍然遇到黑屏问题,请尝试上述方法。

Math in CS:置换的轮换分解

随便一本《近世代数》或者《抽象代数》书上在讲到置换群的时候,应该都会讲到这样一个定理:
任何一个置换都可以表示为不相交轮换的乘积,若不计因子的顺序,其分解式是唯一的。

一、简单解释

没有数学背景的人,这句话很难读懂,下面我们来看一个简单的例子。假设我们有这样一个置换 P:

1, 2, 3, 4, 5
2, 5, 4, 3, 1

那么这个置换是什么样的轮换的乘积呢?我们先从 1 出发,1 被换到 2,2 被换到 5,5 又被换到 1,这就是一个轮换;然后再从 3 出发,3 被换到 4,4 又被换到 3,这又是一个轮换。也就是说 P 是两个不相交轮换 (1, 2, 5) 和 (3,4) 的乘积。

二、一个应用:全排列判断问题

下面我们来看这个定理有什么作用,考虑下面这道题目[1][2]:

给一个 n 长的数组,判断它是否为一个 1, 2, ..., n 的全排列,要求在线性时间,常数空间内实现。

我们可以容易看到,每个全排列都可以视为 1, 2, ..., n 上的一个置换。问题就转化为检测该数组是不是一个 1, 2, ..., n 的置换。由本文开头提到的定理可知,我们只需要检查该置换是不是由不相交的轮换构成的即可。

还是上面那个例子,怎么检查

1, 2, 3, 4, 5
2, 5, 4, 3, 1

是不是一个置换呢?首先从 1 开始,a[1]=2,那么再检查 a[a[1]]=a[2]=5,然后再检查a[a[a[1]]]=a[5]=1,这样就发现了一个轮换 (1, 2, 5)。然后接下来检测第二个,第三个轮换...

如何保证检查的高效以及所有轮换都不相交呢?我们每次检查完一个数,就将它置负,这样遇到负值,循环就终止了。如果终止前检查的那个数与起始的数相同,那么我们就发现了一个轮换,否则它就不是一个轮换,说明 P 不是一个置换。由于检查过的轮换中的数字都被置为负值,所以第二个轮换肯定不会与第一个轮换相交。如果到最后所有的数都被置为负值,且循环正常终止,那么说明它们都在不相交的轮换里,那么 P 就是一个置换。

如果想要查找过程不影响最终数组的值,到最后把所有置负的元素都重新置正即可。

代码实现如下[2]:

/* We use a n+1 elements array a[n+1] for convenience. a[0] is used to store
 * the return value, thus is not part of the permutation.  */
int test_perm(int *a, int n)
{
  int i, j;
  if (a == NULL)  return 0;     /* Test input */
  a[0] = 1;
  for (i = 1; i <= n; ++i)      /* Test input */
    if (a[i] < 1 || a[i] > n) { /* Is a[i] in the range 1~n? */
      a[0] = 0;
      return a[0];
    }

  for (i = 1; i <= n; ++i)
    if (a[i] > 0) {
      j = i;
      while (a[j] > 0) {        /* Follow the cycle */
        a[j] = -a[j];
        j = -a[j];
      }
      if (j != i)  a[0] = 0;    /* Test the cycle */
    }

  for (i = 1; i <= n; ++i)
    a[i] = a[i] > 0 ? a[i] : -a[i];

  return a[0];
}

三、另一个应用:100 囚徒碰运气问题

那么这个定理还有其它的用处没有呢?考虑下面这道题目[3][4]:

100 个囚犯,每人有一个从 1 到 100 的不重复不遗漏的号码,国王把这些号码收集起来,打乱放进 100 个箱子里,每个箱子里有且仅有一个号码。囚犯们一个一个地来到 100 个箱子面前,每人可以打开至多 50 个箱子来寻找自己的号码,可以一个一个打开(即可以根据之前箱子里看到的号码来决定后面要打开的箱子)。如果有一个囚犯没有找到自己的号码,那么这 100 个人一起被处死;只有当所有的囚犯都找到了自己的号码,他们才会被国王全部释放。

囚犯们可以在没开箱子前商量对策,但是一但打开了箱子,他就不能告诉别人箱子和号码的对应关系。问他们应该用什么样的策略以保证最大的存活概率?

显然,每个人随机选 50 个箱子打开,100 个人的存活概率会是 1/2 的 100 次方,即1/1267650600228229401496703205376,可以小到忽略不计。但是事实上有一种极简单的办法,其存活概率高达 30% 。至于有没有更好的办法?我不知道。

存活率达 30% 的策略就是:

囚犯打开自己号码对应的箱子,就按照箱子中的号码打开另一个箱子,一直到找到自己号码或者选50 次为止,这样就能保证整体有 30% 的存活概率。

这个策略背后的数学原理是什么呢?其实国王所作的事情,就是一个 1 到 100 元素集合的置换,囚犯所做的事情,就是顺着自己号码所在的轮换找自己号码。那么什么时候所有人都不用死呢?就是这个置换中所有的轮换长度都不大于 50,因为每个囚犯号码的轮换都不大于 50,那么他总能在 50 次以内找到自己的号码。

怎么计算这个概率 P 呢?{这个置换中所有的轮换长度都不大于 50 的概率},就是 1 - {存在轮换长度大于 50 的概率},进而 1 - {存在轮换长度为 51, 52, ..., 100 的概率},由此,我们可以得到下面的等式:

P=1-\frac{1}{100!}\sum_{k=51}^{100}\binom{100}{k}(k-1)!(100-k)!=1-\sum_{k=51}^{100}%20\frac{1}{k}=1-(H_{100}-H_{50})

其中,Hn 代表调和数(Harmonic Number)。虽然调和数没有精确的公式,但是我们知道调和数和自然对数有着密切的联系[5],那么我们就可以用自然对数来近似:

P\approx1-(ln(100)-ln(50))=1-ln(2)\approx0.30685281944005469059[6]

因此,我们可以得到,使用这种策略 100个囚犯的存活概率 P 约为 30%。

[1] http://yueweitang.org/bbs/topic/22
[2] http://fayaa.com/tiku/view/84/
[3] http://tydsh.spaces.live.com/Blog/cns!435F1A315756AD5D!833.entry
[4] http://fayaa.com/tiku/view/141/
[5] http://en.wikipedia.org/wiki/Harmonic_number#Calculation
[6] 求和得到的更精确的结果是:0.31182782068980479698,Bash 代码:

STR="1-("
for i in `seq 51 99`; do
  STR+="1/$i+"
done
STR+="1/100)"
echo $STR | bc -l