Author: qingbo

  • lighttpd, web.py, spawning fcgi failed

    基于 web.py 的程序开发起来还是非常简单的,但是我没想到在服务器上部署的时候却遇到了不少麻烦。我用的 web server 是 lighttpd,不能正常启动,查看错误日志,发现如下几行:

    2009-12-15 19:48:04: (server.c.1503) server stopped by UID = 0 PID = 25128 2009-12-15 19:48:30: (log.c.166) server started
    2009-12-15 19:48:30: (mod_fastcgi.c.1104) the fastcgi-backend /var/www/code.py failed to start:
    2009-12-15 19:48:30: (mod_fastcgi.c.1108) child exited with status 1 /var/www/code.py
    2009-12-15 19:48:30: (mod_fastcgi.c.1111) If you're trying to run your app as a FastCGI backend, make sure you're using the FastCGI-enabled version.If this is PHP on Gentoo, add 'fastcgi' to the USE flags.
    2009-12-15 19:48:30: (mod_fastcgi.c.1399) [ERROR]: spawning fcgi failed. 2009-12-15 19:48:30: (server.c.931) Configuration of plugins failed. Going down.
    

    经历了许多周折之后,问题终于解决掉──实际上不是仅仅一个问题。在这儿把经验分享一下,如果有人遇到同样的问题,至少可以少走一些弯路。请按照一下几点检查错误:

    code.py 可以执行吗?

    当然你可能没有用 code.py 这个名字,我给可执行文件的名字是 root.py

    检查一下文件的权限,code.py 必须是可执行的。如果没有执行权限,那么给它加上:

    # chmod 755 code.py
    

    同时,要保证文件头部有这样的指令:

    #!/usr/bin/env python
    

    hello world 的例子可以正常运行吗?

    把你的 code.py 的内容用 web.py 首页的例子替换(别忘了加上第一行的指令):

    #!/usr/bin/env python
    import web
    
    urls = (
        '/(.*)', 'hello'
    )
    app = web.application(urls, globals())
    
    class hello:
        def GET(self, name):
            if not name:
                name = 'world'
            return 'Hello, ' + name + '!'
    
    if __name__ == "__main__":
        app.run()
    

    一般情况下这个例子是可以正常运行的。这说明可能是我们自己的程序比 hello world 多引用的库出了问题。

    检查一下 egg cache 的权限

    我的程序要链接 MySQL 数据库,所以用到了 MySQL-python,启动失败肯定有它的份。现在试试在 hello world 里加上 import MySQLdb,果然不能启动了!为了看到原因,我们用 try-except 来捕获 import MySQLdb 引发的异常,并且把它输出到网页上。把上面 hello 类的 GET 函数改成:

    try:
        import MySQLdb
    except Exception, e:
        return str(e);
    return 'hello'
    

    打开 localhost:8080, 我看到了如下的错误信息:

    Can’t extract file(s) to egg cache The following error occurred while trying to extract file(s) to the Python egg cache: [Errno 13] Permission denied: ‘/sbin/.python-eggs’ The Python egg cache directory is currently set to: /sbin/.python-eggs Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory.

    又是权限问题,解决办法有很多种,我就把它的 owner 改成了运行 lighttpd 的用户(我配置文件里写的是 daemon):

    chown -R daemon.daemon /sbin/.python-eggs
    

    lighttpd 使用的是哪个 python?

    lighttpd 执行环境的环境变量可能和你在 shell 里使用的是不一样的!我有两个 python,一个是 CentOS 自带的老旧 python 2.4,另一个是我后来自己编译的 python 2.6,在我的 $PATH 里,python 2.6 所在的目录是优先的,但是后来发现 lighttpd 使用的竟然是旧的 python 2.4!如果是这样,比较简单的办法就是在 code.py 的头部写上 python 2.6 的完整路径,比如我的:

    #!/usr/local/bin/python
    

    还是没有解决?暂时我也想不到了……

  • Mac 软件更新不了 – 解决方案

    今天打开 iTunes,提示我有更新,是否下载,点了下载之后,Mac 的软件更新程序开始运行。但是过了一会它告诉我,你的软件已经是最新的,刚才明明 iTunes 自己说有更新的!于是我突然想起前几天在 twitter 上好像有人说 Mac 软件更新不了。我第一反应就是软件更新需要连接的 apple 服务器被封掉了 (事实证明不是),决定花点时间弄清楚这个问题。

    懒得往下看的直接使用解决办法:

    • 在 /etc/hosts 文件添加一行: 80.67.74.160 swcdn.apple.com

    有兴趣的请继续……

    首先 Google 这个问题,确实已经有不少用户开始在各个论坛上抱怨了,包括苹果的官方论坛,但是似乎没有让人满意的答复,大多数人都说把几个 com.apple.SoftwareUpdate.plist 文件删掉然后重启 Mac 试试 – 你不用试了,没用的。

    从苹果官方网站的文章看到,Mac 软件更新需要连接的服务器有:

    • http://swscan.apple.com
    • http://swquery.apple.com
    • http://swdownload.apple.com
    • http://swcdn.apple.com

    Google swscan.apple.com, 第一条结果即是重要线索,该页面可以正常打开,说明此域名没有问题。页面上有好多 URL,域名都是 swcdn.apple.com,随便复制一个打开,都会首先显示 page not found, 然后跳到该域名的首页。这是一个 domain parking page,顶部还显示“您的域名已经到期,请联系您的服务商续费”。

    dig 的结果很有趣:

    $ dig swcdn.apple.com
    
    ; <<>> DiG 9.6.0-APPLE-P2 <<>> swcdn.apple.com
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18722
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 2, ADDITIONAL: 2
    
    ;; QUESTION SECTION:
    ;swcdn.apple.com.       IN  A
    
    ;; ANSWER SECTION:
    swcdn.apple.com.    1178    IN  CNAME   swcdn.apple.com.akadns.net.
    swcdn.apple.com.akadns.net. 279 IN  CNAME   swcdn.apple.com.edgesuite.net.
    swcdn.apple.com.edgesuite.net. 19178 IN CNAME   swcdn.apple.com.edgesuite.net.globalredir.akadns.net.
    swcdn.apple.com.edgesuite.net.**globalredir**.akadns.net. 279 IN CNAME a1562.ce.w.ytcdn.net.
    a1562.ce.w.ytcdn.net.   1179    IN  A   74.63.75.122
    
    ;; AUTHORITY SECTION:
    ytcdn.net.      59910   IN  NS  **dns6.expirenotification.com**.
    ytcdn.net.      59910   IN  NS  **dns5.expirenotification.com**.
    
    ;; ADDITIONAL SECTION:
    dns5.expirenotification.com. 2803 IN    A   67.159.44.159
    dns6.expirenotification.com. 377 IN A   67.159.44.159
    
    ;; Query time: 6 msec
    ;; SERVER: 124.207.160.106#53(124.207.160.106)
    ;; WHEN: Sat May 15 23:33:33 2010
    ;; MSG SIZE  rcvd: 305
    

    看来应该不是常见的 DNS 投毒。我没搞清楚 ytcdn.net 到底是谁的,可能是属于 akamai 的,也有可能是 Akamai 在中国的合作伙伴。在域名解析之后,我们的请求被分配给 ytcdn.net 的服务器了。注意 dig 结果加粗的部分,然后查 ytcdn.net 的 whois 信息,哇,XIN NET 出现了:

    Domain Name: ytcdn.net
    
    Registrar: XIN NET TECHNOLOGY CORPORATION
    Whois Server: whois.paycenter.com.cn
    Referral URL: http://www.xinnet.com
    Status: clientUpdateProhibited
    
    Expiration Date: 2011-04-30
    Creation Date: 2008-04-30
    Last Update Date: **2010-05-01**
    
    Name Servers:
        dns5.expirenotification.com
        dns6.expirenotification.com
    See ytcdn.net DNS Records
    
    Information Updated: Sat, 15 May 2010 15:40:22 UTC
    

    注意加粗的 Last Update Date,回头看网上 Mac 用户发帖求助的日期,都是 5 月 2 日以后。大家请猜测去吧,ytcdn.net 到底属于谁, expirenotification.com 到底属于谁?我是懒得想了,反正 DNS 解析结果指向 ytcdn.net 就完蛋了,因为最终的 IP 并不是真正的 CDN 服务器。

    登录到美国的一台机器(使用的 DNS 服务器跟我的 Mac 不一样),尝试访问在 swscan.apple.com 页面上找到的 swcdn.apple.com 域名的 URL,可以正常下载文件。再看解析 swcdn.apple.com 的结果:

    $ dig swcdn.apple.com
    
    ; <<>> DiG 9.3.6-P1-RedHat-9.3.6-4.P1.el5 <<>> swcdn.apple.com
    ;; global options:  printcmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62285
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
    
    ;; QUESTION SECTION:
    ;swcdn.apple.com.       IN  A
    
    ;; ANSWER SECTION:
    swcdn.apple.com.    3600    IN  CNAME   swcdn.apple.com.akadns.net.
    swcdn.apple.com.akadns.net. 300 IN  CNAME   swcdn.apple.com.edgesuite.net.
    swcdn.apple.com.edgesuite.net. 21600 IN CNAME   swcdn.apple.com.edgesuite.net.globalredir.akadns.net.
    swcdn.apple.com.edgesuite.net.globalredir.akadns.net. 300 IN CNAME a950.gi3.akamai.net.
    a950.gi3.akamai.net.    20  IN  A   80.67.74.176
    a950.gi3.akamai.net.    20  IN  A   80.67.74.160
    
    ;; Query time: 146 msec
    ;; SERVER: 74.207.241.5#53(74.207.241.5)
    ;; WHEN: Sat May 15 23:35:05 2010
    ;; MSG SIZE  rcvd: 231
    

    现在修改 Mac 上的 hosts 文件让 swcdn.apple.com 指向这个 80.67.74.176,重新开始检查软件更新,一切正常了。

    Apple, 后果很严重,请尽快联系你们的 CDN 服务商解决此问题。其实我看到有一些用户其实已经亲自到 apple store 尝试让 apple 员工帮忙解决了,但是他们也不知道原因。

    Update: 后来发现这里有网友说改 DNS 服务器也可以解决,应该是没问题,不过我自己没有测试。改 hosts 文件是短期内绝对保险的做法,除非 akamai 经常变动它的 IP. 从苹果官方论坛那个帖子看,受影响的用户在中国的居多,但是其它国家的似乎也有。

  • Symbian Series 60 程序开发 (2) ListBox

    上一篇:Symbian Series 60 程序开发(1) Hello World

    继为 S60 成功编译 hello world 程序之后,我又尝试了一下跟实用程序更接近一步的开发——使用列表控件即 ListBox,这是在 S60 手机上比较常见的控件。大概花了5个小时的时间,终于知道最基本的用法,然而我已经开始对 Symbian 开发失去兴趣,因为 ROI 太低了。花的时间多,费的力气多,这还只是刚刚开始。我后来看了一眼怎么开发利用 API 如 flickr、evernote 等的应用,发现了由 Nokia 自己写的,网上广为流传的 CClientEngine 类,很复杂,用起来也很复杂。所以本来打算写一系列文章的,可是到这个第二篇,也许就是最后一篇了,目前不太想在这个事上浪费时间。

    最后的代码很简单,时间都浪费在文档查找与尝试的过程中。大致过程如下:

    1. 在 AppView 类的头文件中包含必要的头文件,添加成员变量定义
    2. 在 AppView 类的 ConstructL 函数里添加创建 ListBox 的代码
    3. 给 AppView 类实现 CountComponentControls,提供接口告诉外层容器该 view 包含多少个控件(本例是1)——我感觉这是设计缺陷
    4. 给 AppView 类实现 ComponentControl(TInt aIndex), 提供接口给外层容器,使其可以根据 index 取得相应的控件——感觉同上,如果你没有实现这两步,程序就是个白板,ListBox won’t be rendered.
    5. 给 AppView 类实现 OfferKeyEventL 函数,将按键事件传递给 ListBox 控件
    6. 千万不要忘记在 CHelloS60AppUi::ConstructL 中 AppView 被创建后,将它加入 Control Stack,否则按键事件不会传递过去
    7. 编辑 group 文件夹下面的 mmp 文件,添加需要链接的 lib 文件
    8. 编译方法照旧

    我懒得每一步都贴出代码了,不过我在 Google code 上创建了一个 project: hello-s60. 它基于 svn 的 browse source 功能比在这里贴代码清楚多了。Revision 3 即是本文中所介绍的代码修改,可以非常清楚地看到具体在哪些文件,哪个地方。

    这里给出一些稍微有点价值的文档:

    最后抱怨一下,基于 Frame 的文档用户体验相当不好,浏览器地址栏的 URL 从来不会改变,因此不便于分享。

    这程序安装到我的 E71 上,我每天就靠按上下键打发时间……哈哈

    上一篇:Symbian Series 60 程序开发(1) Hello World

  • SEO 重复内容问题

    几天前无聊在 Google 看对我这个站点的收录情况 (site:qingbo.net),结果让我很意外:

    site:qingbo.net

    看截图,严重的重复内容!SEO 之大忌,这里有 Google 关于重复内容的解释。重复内容事实上是说不同的页面(即链接,URL)有相同或过度相似的内容。当然这对用户来说很不友好,而搜索引擎作为方便用户查找信息的工具,也当然不喜欢这样的站点。

    不过我的站点被 Google 收录的所谓重复内容,实际上都是同一个页面即首页,只不过 Google 给首页加了参数 (?s=xxx) 之后来爬取,我在写程序的时候并没有考虑到。这确实不是爬虫普通的行为,出现这样的情况是因为我改了域名并且在 Google Webmaster Tools 里面使用了 Change of address 功能,而我又没有沿用原来的程序。Google 将原来存在的 url 替换了域名之后来爬取,就出了这样的问题。

    解决的办法有多种,比如 canonicalization, 301 redirect, Parameter handling tool 等等。我修改了一下自己的程序判断 URL,如果不是正规的就 301 跳转一下,并且加了 canonical 标签,希望可以解决重复内容。

  • Symbian Series 60 程序开发 (1) Hello World

    下一篇:Symbian Series 60 程序开发 (2) ListBox

    Symbian 平台的程序开发很困难,似乎是众所周知的问题。我目前还不了解是什么造成这种困难,开发工具、开发环境?相对 iPhone 平台来说,众多的屏幕尺寸也是一个问题。另外可能由于 Symbian 平台长期以来主要只是一些大企业在开发应用程序,导致对之有兴趣的个人程序员比较少,而且盈利的机会也不怎么多。如果 iPhone 不是把利益分配给大批的个人程序员和小团队,app store 也不可能这么繁荣吧。开发者少就直接导致社区规模小,开发资料少。

    我基本上还没有接触 Symbian 开发,所以上面的仅仅是个人猜想。不过我这几天倒是初步试了一下 s60 的开发,至少发现工具多而乱,文档多而乱,这里就把写一个 Hello World 程序的过程记下来。本文标题里有个编号,所以我还会继续探索,并继续记录。

    开发工具选择

    我在使用的手机是 E71, 系统是 S60 3rd Feature Pack 1. 开发语言不必仅限于 C/C++,但是我比较在意性能问题,并且似乎在官方文档里看到过用 Symbian C++ 可以有最大限度的灵活性。我很理解苹果为什么修改 SDK license agreement 禁止代码转化器或者生成器Qt 似乎有更好的开发工具,可是虽然它被诺基亚收购了,商业开发仍需支付不菲的费用。我很奇怪诺基亚为什么不为开发人员降低用 Qt 开发移动应用的成本。

    开发环境搭建

    安装之前注意,所有这些工具都必须安装到同一个磁盘分区,包括打开 IDE 时需要选择的 workspace 路径,以省去不必要的麻烦。

    1. 安装 Carbide.c++,这是一个基于 Eclipse 的 IDE
    2. Carbide.c++ 安装完成后,应该会弹出一个网页,要求你安装 ActivePerl-5.6.1.635 – 必须是这个特定的版本
    3. 接下来选择要安装的 SDK,我的 E71 就是 S60 3rd FP1, 列表里默认的就是,直接下载安装

    Hello World

    我是参考 Carbide.c++ 文档中的例子做的 Hello World,不需要写代码即可生成一个 S60 的应用,当然了,和所有的 hello world 一样,和所有 IDE 生成的程序一样,这个应用很没用。我这里就不再复制文档里的内容了。

    debug 过后,肯定想知道如何在手机上运行这个程序吧,虽然它很没用。请到这里看:Building a SIS File in Carbide.c++. 没错,刚才的文档是在 nokia.com 上,现在你得跑到 symbian.org 的 wiki 里了,这就是我为什么说 Symbian 平台的文档多而乱了。Symbian 不缺文档,只是太乱了,我很奇怪为什么他们不提供一条清晰的线索供初学者起步。

    按照该链接中提到的方法创建一个 sis builder之后,右键点击该 Project -> Build Configurations -> Set Active,选择 Phone Release (GCCE) [S60_3rd_FP1],否则生成的 sis 文件很大并且无法安装。然后右键点击该 Project,选择 build project,就会在 sis 文件夹里生成一个 sis 文件,通过蓝牙或 PC Suite 安装到手机上,就可以运行了!

    本人初次接触 S60 开发,如走了歪路敬请专业人员指正 🙂 我还会继续探索,但是还没想好要做一个什么应用好。想法很多了,比如 Evernote 的 S60 客户端,或者 todoist/rememberthemilk 的客户端,但是我会挑最简单的尝试。尝试过程中有价值的东西我会记录下来,作为该文章的后续。

    下一篇:Symbian Series 60 程序开发 (2) ListBox

  • Ruby 逗号带来的问题

    几个月前写了一篇 “Ruby 的一个陷阱“,这几天又因为大意得到了另一个教训。

    程序有一段代码本来是 Hash 的,大约如同:

    a = {
      :x = 1,
      :y = 2,
      :z = 3
    }
    

    程序结构变化后,我需要给改成变量的赋值,但是忘记删除每行后面的逗号了,于是变成下面的样子:

    x = 1,
    y = 2,
    z = 3
    

    我觉得学校里那一类闲得没事干的老师肯定会在考试的时候或者课本的习题中出这样的题:请写出变量 x 现在的值。你猜是什么?是一个数组:

    [1, 2, 3]

    看到答案就明白为什么了,是吧……看来 Ruby 语法很灵活,解释器为你发现错误的机会就少了,写程序的时候千万要注意。

  • Mac OS X 中的怪事

    Mac 一直用得好好的,不过最近发现两件比较奇怪的事情。

    有一天离开办公桌一会,习惯性地锁屏。回来之后一动鼠标,奇怪怎么没锁屏呢?仔细一看,不对,确实出来锁屏状态请求输入密码的对话框了,但是它后面并不是以往的黑屏,而是所有的窗口都可以看到,并且所有操作都可以正常进行,只是密码对话框永远居于所有窗口的前面。我本来想多玩一会再截屏的,不过玩了一小下,一切恢复正常,屏幕变黑,必须输入密码了……

    没过几天,又发现一个 bug,但这个我觉得可能是 Firefox 的问题。两个显示器上分别有一个 Firefox 的窗口,其中一个是正常的,但另一个在地址栏输入的时候,出来的提示竟然跑到另一个显示器上一个奇怪的地方!应该是这个窗口创建那个输入提示的 UI Control 的时候,找错显示器了。将出问题的 Firefox 窗口稍微移动一下位置,问题就没了。

    对了,我的系统还是老旧的 10.5.8.

  • Gravity 在 E71 上怎么用 GPS

    有了个新手机 (E71) 之后就比较喜欢折腾,尤其对基于位置的应用非常感兴趣,比如在 google maps 中打开 latitude 图层,分享自己的位置,以及查看朋友们都在什么地方,可惜 google buzz 的图层在国内无法使用。

    foursquare 是目前最流行的一个基于位置的服务了,另外 twitter 也开始支持 geotagging,尽管 s60 的应用跟 iPhone 比起来太少,有人还是做出了一个出众的软件 Gravity. 它最先只支持 twitter,现在最新的测试版不仅支持 twitter 自定义 API proxy,还支持了 foursquare, facebook, google reader, 新浪微博等一堆 web 服务。提一下,用 Gravity 看 Google reader 非常舒服。

    几天前在机场比较无聊,又急着想方便地使用手机的 GPS 功能在 twitter, foursquare 上面分享位置,于是买了个 Gravity 的 license,这玩意的 UI 在 symbian 上确实是算好的,可惜的是文档太少,很多只能自己摸索,或者看山寨文档。比如一开始我用试用版就以为试用版限制了不能发布信息呢,后来才知道直接输入文字即可。

    最郁闷的是我连续折腾了好多天,都没有在 E71 上让 Gravity 成功使用 GPS. 本来想着在机场买了就可以用的,结果回来之后才搞明白,现在真相大白,不得不把 E71 上 Gravity 的用法分享出来,以造福广大劳苦人民。

    其实很简单——安装 FP2 版本!janole (Gravity 作者,此为其 twitter 用户名) 每次发布新版,总是有两个版本,比如最近发布了 6375 测试版,就给了两个短链接 bit.ly/6375ALL 和 bit.ly/6375FP2 (此域名被封,无需尝试)。我们普遍都认为 E71 是 FP1,于是就安装 6375ALL,这样无论如何都不能使用 GPS 的(我用尽了各种招数,包括打电话给朋友抱怨这软件垃圾……)。 在写 tweet 的界面使用上方向键,只能让 GPS icon 消失或者显示灰色;点击菜单 “options – tools – gps to clipboard”, 没有任何反应。foursquare 也找不到 checkin 的地方。

    Gravity 6375 FP2 下载 – Gravity 更新频繁,请 follow @janole 以获取最新信息。

    安装了 FP2 版本,发现 E71 也是支持的,一切都变得很容易。foursquare 多了一行 “Places nearby”,进去以后可能右下角会显示个气泡说 “waiting for GPS”,然后就搜到附近的地点了。twitter 发布信息的时候,按上方向键可以使 GPS icon 变成橘黄色,同时显示个省略号表示正在锁定位置,省略号消失时图标变成绿色就表示锁定成功了,否则使用上一次位置(我猜的)。其实在安装的过程中,在程序接入提醒那一步我就惊喜地发现多了一条:接入定位数据。

    当然了,想要在 twitter 使用 geotagging,你必须登录 twitter 账户并打开该设置。因为 twitter 不会默认给你打开这个特性,以避免意料不到的隐私泄露。

    似乎有消息称 Gravity 还要支持 google buzz,如果真这样就无敌了。

  • 世界很小

    半个月前,美国那边过来一个同事,聊天时我第一次从他那儿知道百姓网的渊源(以前没怎么关注过),于是就查了一下相关的新闻,当时就看到了王建硕的主页,但是没太在意,只粗略浏览了一篇访问 Facebook 的记录。

    恰好几天后,有好友发给我一个链接,是王建硕的最新一篇 blog post,上面竟然有我主页的链接(Nice Technical Blogs)。

    这事一方面在时间上很巧,另一方面也说明技术圈挺小的,我不太记得那个美国同事是不是跟王建硕也见面过了。后来我猜测,应该是 Robert Mao 推荐了我大学同学兼室友 xlvector郑昀,他们都在研究推荐系统相关课题,正好 xlvector blog 有我的一个链接,我就被不小心发现了。包括我在内的三个人都是来自中国科学技术大学,这也算是个巧合……

    被点名了,流量有小幅跳跃,google reader 增加了几个 subscriber, 给我加了点动力(压力),得提高文章质量。

  • dabr 架设与修改

    我的 Nokia 3100 已经用了大约有四五年了,最近很有冲动要买个 iPhone,不过某人却给我买了个 E71,粉碎了我的梦想。在 Nokia 3100 退休之际,看一下它的丰功伟绩:发出的信息 10243,收到的信息 11431.

    其实 E71 我也比较满意,不买 iPhone 也省下一笔钱。先配置了一下 Share Online,让它可以把照片上传到 flickr,然后就开始整 twitter. 先试了一下 Gravity,界面挺不错的,就是不是免费软件,最关键的是听说流量耗费比较大,我试用了一会确实如此,实在想不到为什么它会用那么多。

    我一直在想自己做一个 twitter 客户端,只需要能够发布和查看与自己相关的信息(我发布的或者提到我的),几个月前曾经用 Adobe AIR 尝试过,后来因为时间问题搁浅了,也许以后有空了还会拣起来。我关心的信息就这么多,但是 Gravity 不管这些,它会定时更新默认的 timeline,一方面耗费流量,另一方面信息过载让我比较头疼。

    dabr 是个非常好的选择,后来我使用也非常喜欢,虽然它只是个 mobile web interface. 第一,它可以让我访问到 twitter; 第二,只有在你操作的情况下它才会刷新页面,产生数据流量,且流量相当小; 第三,它是开源软件,可以非常方便地修改来适应自己的需求。其实它的安装就是比普通的 PHP 程序多了个 rewrite rule,很简单。不过我的配置比较特殊,也作了些修改,所以记下来,就当是个另类的 dabr 教程。

    我的服务器上有两个 web server,lighttpd 运行着包括 qingbo.net 在内的一些 PHP 或者 python 程序,监听 80 端口,apache 监听 443 端口,是我的私人 svn repository 和 trac 的前端,只能 https 访问。由于还没有为 apache 配置 PHP 环境,所以我仍然把 dabr 的程序分配给 lighttpd 运行,但是给它单独开了一个新端口(比如 3000),且只能本机访问(请求目标地址为 127.0.0.1)。又因为 lighttpd 没有配置 ssl,就用 apache 做个 ProxyPass,指向 127.0.0.1:3000,这样外部还是只能通过 https 来访问 dabr,避免某些安全隐患。

    dabr 的 SetupGuide 没有给 lighttpd 的 rewrite 写法,其实基本上跟 Apache 是一样的。我的规则如下:

    url.rewrite-once = (
      "^/images/.*$" => "$0",
      "^/(.*)\?(.*)$" => "/index.php?q=$1&$2",
      "^/(.*)$" => "/index.php?q=$1"
    )
    

    之后是 dabr 程序的调整 (Update – 我流量包月以后,发现根本无需改这些设置,默认的也没多少流量,呵呵):

    限制 twitter 用户

    默认情况下架设一个 dabr 程序是任何人可以访问的,如果知道的人太多,可能给服务器造成比较大的负担。

    避免这个情况的方法在 dabr 的 SetupGuide 里就介绍了,把一段代码放在 config.php 里就可以。

    去除不需要的菜单项

    dabr 默认在页面顶部和底部都有一长串的链接,但是很多可能是我们不需要的。它们是使用函数 menu_register 添加的,在源代码目录执行命令 “grep -r menu_register *” (Linux 系统) 即可找到所有调用了该函数的文件,然后进去找到你不想要的菜单项,注释掉即可。

    例如 index.php 一开始就调用了这个函数,”about” 一般来说没用,把它注释了。需要注意,common/twitter.php 里调用 menu_register 时的参数数组有非常多的条目,其中许多包含一行 'hidden' =&gt; true,,这种并不是显示出来的菜单项。

    修改每页展示的 tweets 条数

    我修改了 twitter_user_page, twitter_home_page, twitter_replies_page 几个函数,给它们定义的 $request 变量 url 中增加了 count=5 这个参数

    强制 text only 模式

    主要是为减少不必要流量,另外我屏幕也比较小。打开 common/settings.php, 改一下 setting_fetch 函数,当获取 ‘browser’ 配置值时,总是返回 ‘text’:

    function setting_fetch($setting, $default = NULL) {
      $settings = (array) unserialize(base64_decode($_COOKIE['settings']));
      if (array_key_exists($setting, $settings)) {
        return $settings[$setting];
      } else {
        if ($setting == 'browser') {
          return 'text';
        }
        return $default;
      }
    }