Monday, October 27, 2008

从Mephisto迁移到wordpress

原先blog用的mephisto,最近出现spam,索性关了comments,决定换回wordpress。今天抽个空闲,终于是转换了过来。

幸好Caleb Jaffa因为有同样的需求写了转换脚本

下载 wordpress 2.5.1,安装,运行,运行转换脚本,更新 wordpress 2.6.1,设定 permalink,原先的 feed archinves url 转换设定,磕磕碰碰遇到点小问题,半个小时之内还是搞定了。

买了 linode 的 VPS,用debian的image,安装mysql编译apache、php,一切顺利,总算可以对备案说 fu**k you了,:-p

Update:

Thursday, September 18, 2008

How to Install Adobe air 1.1 beta on Ubuntu hardy 64bitJHow

adove air logo

Adobe Air 最近放出 1.1 beta for linux, 不过仍没有 64bit 支持。经过一番尝试,成功安装。

下载

cd /tmp
wget http://download.macromedia.com/pub/labs/air/linux/adobeair_linux_b1_091508.bin
chmod +x adobeair_linux_b1_091508.bin

安装

./adobeair_linux_b1_091508.bin
Error loading the runtime (libnss3.so: wrong ELF class: ELFCLASS64)

locate 了一把发现系统存在 libnss3.so,但由于是 64bit 的,adobe air 无法使用。理论上安装 32bit 的 libnss 库应该可以解决这个问题,Ubuntu/Debian 自带的 lib32 库并未包含 libnns,需要手工安装。测试安装过程中发现,还需要 libnspr4 库。
下载依赖 deb 包

wget http://mirrors.cn99.com/ubuntu/pool/main/n/nss/libnss3-1d_3.12.0.3-0ubuntu5_i386.deb
wget http://mirrors.cn99.com/ubuntu/pool/main/n/nspr/libnspr4-0d_4.6.6-3_i386.deb
wget http://mirrors.cn99.com/ubuntu/pool/main/n/nspr/libnspr4-0d_4.7.1+1.9-0ubuntu0.8.04.5_i386.deb

手工解 deb 包

mkdir airlib
dpkg -x libnss3-1d_3.12.0.3-0ubuntu5_i386.deb
dpkg -x libnspr4-0d_4.6.6-3_i386.deb
dpkg -x libnspr4-0d_4.7.1+1.9-0ubuntu0.8.04.5_i386.deb
手工安装 deb 包
sudo cp -a airlib/usr/lib/* /usr/lib32
重新运行 air 安装文件,顺利安装完毕。
测试了 twhirl,顺利安装启动,但无法获取信息,可能和 nss 的库有关。

Monday, September 08, 2008

Linux下通过wine安装google chrome

Chrome还没有linux下完整可用的版本,如果你有兴趣编译,这里有linux下Chrome的编译指南

目前在linux下跑Chrome,wine成了唯一可能的方式,幸运的是,通过geek们的尝试,Chrome已经可以用wine驱动。

安装 wine

首先需要安装 wine 的最新版本 1.1.3。如果你是 Ubuntu 用户:

wget -q http://wine.budgetdedicated.com/apt/387EE263.gpg -O- | sudo apt-key add -

For Ubuntu Hardy (8.04):

sudo wget http://wine.budgetdedicated.com/apt/sources.list.d/hardy.list -O /etc/apt/sources.list.d/winehq.list

For Debian Etch (4.0):

sudo wget http://wine.budgetdedicated.com/apt/sources.list.d/etch.list -O /etc/apt/sources.list.d/winehq.list
sudo apt-get update
sudo aptitude install wine

安装 winetricks

wget http://www.kegel.com/wine/winetricks
sudo cp winetricks /usr/local/bin

安装Chrome的依赖包

winetricks riched20 riched30 flash
winetricks allfonts

安装Chrome

wget http://gpdl.google.com/chrome/install/149.27/chrome_installer.exe
wine chrome_installer.exe

启动Chrome

Chrome安装完成后,无法直接启动,需要一点 hacking,我使用下面的小脚本代替 wine chrome 启动:

$ cat ~/bin/chrome
#!/bin/sh
Exec=env WINEPREFIX="$HOME/.wine" wine "C:\\windows\\profiles\\$LOGNAME\\Local Settings\\Application Data\\Google\\Chrome\\Application\\chrome.exe" --new-http --in-process-plugins

Note: HTTPS 无法正常工作。

Saturday, August 02, 2008

我看 SNS 和 facebook

缘起在广州豆瓣上和PH囧ENIX讨论

SNS 的根本是人何人之间的关系,剥离这层关系,剩下名字和技术是空洞的。即便没有 "Web 2.0", "AJAX" 这些时髦(看到这个词的时候,镜头要拉到三年前)的词语,也会出现 Axax,真正推动技术的是背后的需求,是互联网发展的趋势。

  

早期的 SNS,是用来维持线下朋友关系的网络,比如出现于 95 年的 classmates.com,sixdegrees.com,国内有 chinaren 是陈一舟当年的模仿作品。

  

当前的 SNS,是用来分享和维护关系网的工具。比如国内的校内,5gsns,真实的线下关系是网站的动力源。

把镜头再拉近聚焦到 facebook,它已经完全超越了 SNS 的概念,成为平台。APP的横空出世大获成功,截至到目前,已经超过 14,000 个 APP 应用,最近 F8 上Connect的推出,已经确立了 facebook 的互联网平台提供商地位,说它是下一个 google,毫不夸张。

Thursday, July 31, 2008

QQ for linux, for the future

QQ for linux logo

QQ for linux 终是放出了。

腾讯多年来一直没有开发基于 linux 版的 QQ,linux 用户以前只能使用 gaim QQ/LumaQQ/eva 等开源 QQ 实现。腾讯做为一家商业公司,从纯粹的短期利益角度出发,这么做无可厚非,也无关道德,不过,只是当年施加压力给分析 QQ 协议的 gaim qq 老爹以及三天两头修改协议未免显得无耻和小气。无论如何,今天 QQ for linux 的推出,还是非常正面的,至少我在给 MM 推荐linux 的时候,可以很放心的说,linux 下也可有 QQ。

用腾讯自己的话说:

Tencent QQ for Linux是腾讯公司把握市场需求,针对日渐增多的Linux用户,推出的基于Linux的即时通讯软件。

可见市场占有率才是硬道理,geek 们即便在这个全球化了的新经济时代也永远只能是小众。很有意思的是,QQ for linux 的 logo 上的宣传口号是 “for linux, for the future!",Ubuntu 老爹毅然决然的杀入 Linux 市场,看中的也就是这个 future, 微软被迫拥抱开源同样如此,没有人能够战胜未来,在趋势面前,你会发现垂死抵抗直如螳臂挡车,最后剩下的只会是历史车轮后躁动的飞灰,而那,是留给历史学家的。

废话不多说,放两张截图

Tuesday, July 15, 2008

Ubuntu hardy 上安装 CouchDB

下载

wget http://www.apache.org/dist/incubator/couchdb/0.8.0-incubating/apache-couchdb-0.8.0-incubating.tar.gz
tar zxvf apache-couchdb-0.8.0-incubating.tar.gz
cd apache-couchdb-0.8.0-incubating.tar.gz
sudo aptitude install automake autoconf libtool build-essential erlang libicu libicu-dev libreadline5-dev checkinstall libmozjs-dev
./configure --sysconfdir=/etc --localstatedir=/var
make && sudo make install 
sudo adduser couchdb --home /var/lib/couchdb/ --disabled-password
sudo chown -R couchdb /var/lib/couchdb
sudo chown -R couchdb /var/log/couchdb
sudo /etc/init.d/couchdb start

浏览器打开 http://localhost:5984/_utils/index.html,访问 CouchDB 自带的管理工具。

开源和商业模式

原文发布于 szlug,是szlug聚会时和 xning 兄讨论后的一些思考。

szlug周末聚会回来后,回来之后一直在想开源软件和商业模式这档子事情。

首先自由不是免费,Richard Stallman 说:

"Free software is a matter of liberty, not price. To understand the
concept, you should think of 'free' as in 'free speech', not as in
'free beer'"。

自由不是免费,理解偏差不代表原意的异化。

自由软件允许任何人在同样自由的条款下使用,学习,修改,拷贝,重发布。开源和商业模式并不冲突,开源从来不排斥商业模式。如何建立开源的商业模式呢,一般都是基于软件附加价值,如支持,培训,定制,集成,认证等。基于软件授权的商业模式和开源是不相容的。基于此比较成功的公司有,MySQL, Zend。国外也有很有小型顾问公司提供开源支持,像 MySQL、rails 特别多。

除去自由软件,我们日常接触最多的是开源软件,自由软件是开源软件的子集。在我看来,自由软件和商业更近,自由软件最主要的特点是开发模式的变化,所谓集市和教堂,围绕软件社区的建立,带来的效用很明显,加速软件开发,节省宣传费用,自由软件背后的公司可以基于开源成果建立商业版本或者是解决方案,成功案例有,XFree86,eclipse, Zope 等。

MichaelBibby 的 iredmail 就属于邮件类别的解决方案,而yahoo 收购 Zimbra(同样也是做邮件整体解决方案的) 可是花了 350M 美刀。

所以,我的关点是,开源从来不排斥商业模式,如果你开源的目的是未来利润(利润从没有贬意),而开源后并未带来预期的成功,那么我想需要考虑的更多的是产品的定位,而不是因此否决开源不适合商业。

另外我同意李的低利润说,对于很多软件来说是如此的,所以 IBM 才会早早转向服务,google 做平台,靠长尾的量赚钱。从 1983 自由软件至今,软件行业已经被改变,门槛也已经拔高,软件生产的趋势一定和传统产业的生产线没有太大区别,单纯靠产品赚钱,需要的恐怕是大智慧。

Monday, July 14, 2008

KVM guest 连接 USB 设备临时解决办法

默认的 kvm guest 启动并未模拟 usb, 模拟 usb,需要启动时加上 -usb 参数,qemu 为 guest模拟一个 8 port 的 Intel SB82371 UHCI USB 控制器。

kvm -hda /path/to/your/kvm/image/hda.qcow2

在使用 USB 之前,需要找出 USB 的设备 ID,如:

$lsusb
Bus 007 Device 002: ID 05ac:8502 Apple Computer, Inc.

输出中的 05ac:8502,分别为 <VendorID>:<ProductID>

启动 guest 系统后, CTRL + ALT + 2 转到 Monitor ,手工加载 usb 设备(用上面的输出替换):

#usb_add host:<VendorID>:<ProductID>
Could not open /proc/bus/usb/devices

回到 host 系统发现 /proc/bus/usb/devices 文件不存在,google 后发现相关的 Ubuntu BUG report。Ubuntu 等发行版早将 /proc/bus/usb/devices deprecated 一年之久,hardy 已经完全转向 /dev/bus/usb/devices,相比较 proc 获得有更灵活的权限控制、安全性更高。Ubuntu bug report 中给出了 workaround。

编辑 '/etc/init.d/mountdevsubfs.sh' 取消 40 行后的相应注视:

 # Magic to make /proc/bus/usb work
  #
  mkdir -p /dev/bus/usb/.usbfs
  domount usbfs "" /dev/bus/usb/.usbfs -obusmode=0700,devmode=0600,listmode=0644
  ln -s .usbfs/devices /dev/bus/usb/devices
  mount --rbind /dev/bus/usb /proc/bus/usb

执行这个脚本。

$ sudo /etc/init.d/mountdevsubfs.sh start

用此法成功加在招行 USB key,可以进入专业版,实际实验查帐等操作正常,转帐验证时候失败。

Saturday, July 12, 2008

手工配置 Ubuntu hardy KVM 网络

Ubuntu hardy 中安装 KVM 速记中网络配置采用 KVM 默认方式,此法简单易用。

用户网络

使用情形

  • 最简易的从虚拟机访问宿主,Internet,和其它本地网络资源
  • 你不需要从一个 guest 访问另外一个 guest
  • 你不追求最高性能

警告:用户网络不支持部分网络特性如 ICMPP,影响一些程序(如 ping) 无法完全正常工作。

前置需求

  • 你需要 kvm 启动并运行
  • 非 root 用户运行需要拥有 /dev/kvm rw 权限
  • 如果你需要访问 Internet 或本地网络,你的宿主系统必须可以访问 Internet 和本地网络

解决方案

以参数 "-net nic -net user" 运行 kvm , 例如:

kvm -hda /path/to/hda.img -net nic -net user

注意

  • IP地址由qemu 自带的 DHCP 服务自动分配
  • 如果你在一个宿主上运行多 guest 系统,你无法为每个 guest 指定不同的 MAC 地址
  • 你仍可访问一个指定的端口,你可以使用 "redir" 选项(译者按:启动 kvm 时)

公共网桥

警告: 下面的方法,不适用于大部分的无限驱动,因为他们不支持 bridging 功能。

使用案例

  • 你不想指定 IP 地址到你的虚拟机器并且使它们可以从本地网络访问
  • 希望性能于虚拟机无关

前置需求

  • kvm 已启动并运行
  • 非 root 用户运行需要拥有 /dev/kvm rw 权限

停止当前网络接口

sudo /etc/init.d/networking restart

编辑 /etc/network/interfaces 设置 bridge 接口,注释或替换原配置为(修改为对应你网络的配置):

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet static
        address 192.168.0.10
        network 192.168.0.0
        netmask 255.255.255.0
        broadcast 192.168.0.255
        gateway 192.168.0.1
        bridge_ports eth0
        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

或使用 DHCP(对 laptop 比较有用,但不能使用无线,囧)

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet manual

auto br0
iface br0 inet dhcp
        bridge_ports eth0
        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

这将用来创建虚拟接口 br0

重启网络

sudo /etc/init.d/networking restart

手工或用下面的脚本创建 MAC 地址

#!/bin/bash
# generate a random mac address for the qemu nic
# shell script borrowed from user pheldens @ qemu forum
echo $(echo -n DE:AD:BE:EF ; for i in `seq 1 2` ;
do echo -n `echo ":$RANDOM$RANDOM" | cut -n -c -3` ;done)

注:原脚本用的环境为 /bin/sh,ubuntu 上出错,所以这里我替换为 /bin/bash

用生成的 MAC 地址替换下面的 $macaddress 启动 KVM

kvm -hda /path/to/hda.img -net nic,macaddr=$macaddress -net tap

现在可以 ping 通本地网络了,:-)

Wednesday, July 09, 2008

校内网的“开放”平台

2007 年六月24 日,Facebook推出Facebook Open Platform,大获成功,被媒体誉为网络操作系统,截至到目前,已经有超过 14,000 个应用。一年零一周后,被称为中国版的Facebook校内网推出其校内开放平台,校内一贯以模仿Facebook著称,此次却迈出大胆的一步,在协议上勇敢的创新,或者称之为本土化。

此协议将中文互联网巨头们的一贯作风和嘴脸表现的淋漓尽致,达到了梦寐已久的高潮,特摘录存照。

  • 2.3 其已经取得开发作品(即应用程序)其他权利人(如有)的书面授权,并已与前述权利人就权益分配达成内部协议,保证其在将应用程序提交、上传至校内网前对开发作品拥有充分、完整、排他的所有权及知识产权,并可通过校内网插件应用程序开发许可,将上述产品及产品权利转让给校内网;
  • 校内网保留对以下类型的插件应用程序自有开发和应用权利,即开发者所设计、开发的插件应用程序不得涉及一下领域,否则校内网有权不对该类程序给予审核通过,直至取消该开发者开发许可资格: 1、和校内网主营业务有冲突的; 2、通过校内插件应用程序引导用户注册第三方网站或服务的; 3、在校内插件应用程序内包含外部链接的; 4、涉及以下领域的插件应用程序:招聘、旅游、音乐、个人相册。
  • 六、插件应用程序的权利归属 1. 开发者在活动校内网插件应用程序开发许可证、且将其开发的作品提供给校内网,即视为其已经将基于作品的全部权利,包括但不限于所有权及知识产权永久性、不可撤销的、独家让渡给校内网。 2. 经开发者创作完成并提交给校内网的应用程序,校内网在全世界范围内享有免费的、永久性的、不可撤销的权利和许可,以使用、复制、出版、发行、以原有或其他形式进行改编、转载、翻译、传播、表演和展示此等内容(整体或部分)。同时开发者承诺,不就上述作品以及上述作品的改编作品对任何第三方进行任何形式的许可或授权使用。 3. 经开发者创作而产生的文本、图片、图形、音频和/ 或视频等资料的所有权及知识产权归属于校内网,未经校内网同意,开发者保证不以任何形式直接或间接发布、播放、出于播放或发布目的而改编或再发行,或者用于其他任何商业目的。同时保证不许可任何第三方从事上述行为。

李大维说的好,签个卖身契至少有主人养,签了校内网开放平台开发者协议后呢?

Update: 2008-07-09 14:35, 校内已对协议中最引人争议的条款进行了修订,080709版第六条:

六、插件应用程序的权利归属
插件应用程序的权利归属于开发者或开发商。 

感谢为此做出努力的朋友,你们让我看到中文互联网走向开放的勇气和义无反顾的态度。

Tuesday, July 08, 2008

重新调整 qemu 镜像文件大小一法

qemu 的镜像文件格式 raw, qcow2 采用了文件系统的打孔技术,镜像文件实际大小同实际写入的数据扇节相关。因为担心硬盘空间不足,之前创建的镜像文件仅为 2G,现在看来完全没有必要,尝试重新调整到 10G。

qemu 没有提供调整硬盘镜像文件的工具,google "qemu disk resize" 说法各异。我的 guest 文件系统为 NTFS,按照此法调整成功,记录一下:

转换为 raw 格式

$qemu-img convert hda.qcow2 -O raw hda.raw

增大raw镜像文件到 10G

$dd if=/dev/zero of=hda.raw seek=10 obs=1GB count=0

修正 NTFS BPB

$hexedit hda.raw

转到 7E00: 7E00
替换 7E1A 的 80 为 FF
保存退出:Ctrl-x --> y

gparted livecd 启动 guest 重新调整 NTFS 分区大小

$kvm -hda hda.raw -cdrom gparted-livecd-0.3.4-11.iso -boot d

重启 windows,windows 将进入自检

 
$qemu hda system.raw

重新转换为 qcow2 格式

$qemu-img convert hda.raw -O qcow2 hda.qcow2

Monday, July 07, 2008

Ubuntu hardy 中安装 KVM 速记

kvm hit the road

介绍

KVM(Kernel-based Virtual Machine) 是 X86 平台上基于 linux kernel 的全虚拟化技术,通过 Intel-VTAMD-V 技术实现全虚拟化。Linux kernel 自 2.6.20 已经包含了 KVM,各大发行版也陆续提供支持。

准备工作

本文以 Ubuntu hardy 为例记录安装过程。

系统环境

OS: Ubuntu hardy 8.04 64bit
Kernel: 2.6.24-19-generic SMP x86_64 GNU/Linux
Hardware: Macbook Pro 3rd(Santa rose), Intel(R) Core(TM)2 Duo CPU     T7500  @ 2.20GHz

检查 CPU

KVM 需要 CPU 支持原生虚拟以得到最佳性能,官方文档称当 CPU 不支持原生虚拟时,将自动回退到 qemu 模拟方式。Ubuntu 中如果系统不支持原生虚拟,KVM 将拒绝启动,检查 CPU 是否支持原生虚拟:

$egrep '(vmx|svm)' /proc/cpuinfo

有输出即说明 CPU 支持原生虚拟。

安装 KVM

$sudo aptitude install kvm

安装 guest 系统

#mkdir -p /media/work/kvm/
#qemu-img create -f qcow2 /media/work/kvm/hda.qcow2 10G
#kvm -hda /media/work/kvm/hda.qcow2 -m 256 -vnc :0 -daemonize -cdrom /media/ENT/iso/Windows.XP.Professional.VLK.CN.SP2.full.iso -boot d
  • qcow2 是 qemu 支持的硬盘镜像格式之一,支持 snapshots 以及 AES 加密,zlib 压缩,其它格式可以参考 man qemu-img
  • ext3、NTFS 文件系统支持打孔,只有实际写入的扇区才会占用存储空间
  • KVM 启动参数指定 guest 内存为 256M,以 CDROM 启动

kvm 以 daemon 方式运行,通过 vnc 访问:

$xvncviewer localhost:5900

Windows 安装完成后,关闭系统kvm 进程会自动关闭。如需重启:

#kvm -hda /media/work/kvm/hda.qcow2 -m 256 -vnc :0 -daemonize

系统同样可以通过 VNC 来访问。

网络

默认启动 kvm 或者参数 kvm -net nic -net user 将创建一个 10.0.2.0/24 的网络:

         QEMU VLAN      <------>  Firewall/DHCP server <-----> Internet
                           |          (10.0.2.2)
                           |
                           ---->  DNS server (10.0.2.3)
                           |
                           ---->  SMB server (10.0.2.4)

guest 系统从 10.0.2.15 开始依次分配 IP 地址,VNC 登入 Windows,系统已通过 DHCP 分配到 10.0.2.15 IP地址,Windows 系统此时已经可以正常访问网络。如果不需要提供外部服务的话,默认的网络方式已经可以,非常简便。

links

ext3 文件系统上恢复误删除文件

最近手很贱,骡子辛辛苦苦驼来的 2G 文件被自杀(rm -f)了。

为了表现我们还是很专业的,第一时间,保护现场:

#umount /media/work

没有人含泪劝告,所以我还是要找回这个文件的,没错,即便是放弃做俯卧撑和打酱油的时间。

google 如何恢复 ext3 文件系统中已删除的文件,感谢 Carlo Wood,写了如此强大的 ext3grep。 这里有个 How to。鉴于我一贯不求甚解,How To 中 BLAH BLAH BLAH 的技术细节直接掠过。

安装ext3grep

ext3grep 当前最新版本是 0.7.0, 编译依赖于 e2fslibs-dev 开发库。

#aptitude install e2fslibs-dev
#cd /tmp
#wget http://ext3grep.googlecode.com/files/ext3grep-0.7.0.tar.gz
#tar zxvf ext3grep-0.7.0.tar.gz
#cd ext3grep-0.7.0
#./configure
#make
#make install

恢复过程:

#ext3grep /dev/sdb2 --restore-file mule/Incoming/XXXX.mkv

检查当前目录,文件已经在 RESTORED_FILES 中,简单到死。

我痛哭流涕,我要再次感谢 Carlo Wood 手贱删除了他的 ~/home 目录,由此诞生了如此强大的 ext3grep,也正是因此,我才有了继续打酱油的时间。

Wednesday, June 25, 2008

ruby 可执行任意代码漏洞

今天看 slashdot,才知道 ruby 最近爆出的非常严重的漏洞,而我居然全然不知,出了一身冷汗,搜索订阅的 RSS 新闻,果然早有文章提起,夹杂在大量资讯中间,大约被直接忽视掉了。幸好我的项目还没有上线,以最快的速度订阅了 ruby-core 的 mailing list,下载 1.8.6 p230 开始升级。

去掉 debian 的 patches,dpkg-buildpackage 很顺利,安装过后,重启服务,随意访问了几个页面,出现 500 错误。检查 log:

ActionView::TemplateError (wrong argument type FalseClass (expected Proc))
*** glibc detected *** /usr/bin/ruby1.8: corrupted double-linked list: 0x00000000014eb220 ***
======= Backtrace: =========
/lib/libc.so.6[0x7ff36c97e01d]
/lib/libc.so.6[0x7ff36c97e146]
/lib/libc.so.6[0x7ff36c9802cc]
...

google 一下,发现我并不孤独,升级到 1.8.6 p230 后,都遇到了 segment fault 等问题。而奇怪的是,到目前位置,官方仍然没有一个解决方案,目前存在的解决方案和进展:

Friday, June 20, 2008

防作弊评分算法

Web 2.0 网站中最常见的功能之一就是用户投票,常见的可选分值范围为 [1,2,3,4,5],最终得分则等于用户评价的数值平均头。这种算法有个显而易见的漏洞,容易作弊,比如某内容共计一用户投了 5 分,则此项最终评分为 5。

理想的效果是评价数越少,得分越低,最简单的解决办法是 bayesian average。贝叶斯平均使得单项评分更往平均评分靠近,对评价总数低的条目更加明显。

    b(r) = [ W(a) * a + W(r) * r ] / (W(a) + W(r)]

    r = average rating for an item
    W(r) = weight of that rating, which is the number of ratings
    a = average rating for your collection
    W(a) = weight of that average, which is an arbitrary number, but should be higher if you generally expect to have more ratings for your items; 100 is used here, for a database which expects many ratings per item
    b(r) = new bayesian rating 
    b(r) = [100 * 6.50 + 3 * 10] / (100 + 3)
    b(r) = 680 / 103
    b(r) = 6.60

当 W(a) 足够大的时候,少量的作弊无法明显改变结果。

Wednesday, June 18, 2008

在 lenny 上降级 ruby 解决 rails 2.0 不兼容 ruby 1.8.7 问题

production 系统用的是 lenny,前两天 upgrade 了一把,ruby 1.8.7,当时并未在意,直到今天 cap deploy 后,部分页面出错,检查了一把,代码没问题,看来应该是升级到 1.8.7 后出现的问题了。google 了一番,的确如此:

Debian bug#484351 中有人指出最近的 rails 2.1.0 修正了1.8.7 兼容问题,事实上官方下载页面明确指出了 rails 还不兼容 ruby 1.8.7,看来升级到 rails 2.1.0 并不能解决这个问题,只能降级 ruby 了。

好在 debian 中还有 ruby 1.8.6 的 source,自己动手 build 吧。

wget http://debian.cn99.com/debian/pool/main/r/ruby1.8/ruby1.8_1.8.6.114-2.diff.gz
wget http://debian.cn99.com/debian/pool/main/r/ruby1.8/ruby1.8_1.8.6.114.orig.tar.gz
tar zxvf ruby1.8_1.8.6.114.orig.tar.gz
gzip -d ruby1.8_1.8.6.114-2.diff.gz
cd ruby-1.8.6-p114
aptitude build-dep ruby
dpkg-buildpackage
cd ../
dpkg -i --force-all irb1.8_1.8.6.114-2_all.deb libopenssl-ruby1.8_1.8.6.114-2_amd64.deb libreadline-ruby1.8_1.8.6.114-2_amd64.deb libruby1.8_1.8.6.114-2_amd64.deb rdoc1.8_1.8.6.114-2_all.deb ruby1.8_1.8.6.114-2_amd64.deb ruby1.8-dev_1.8.6.114-2_amd64.deb ruby1.8-elisp_1.8.6.114-2_all.deb
降级到 ruby 1.8.6 后 mongrel 的依赖出现问题,同样需要 rebuild,好在这个时候重启 mongrel,问题已经解决了。 如果希望能够解决 mongrel 的依赖问题的话:
apt-get source libsetup-ruby
cd libsetup-ruby-3.4.1
dpkg-buildpackage
cd ../
dpkg -i libsetup-ruby1.8_3.4.1-4_all.deb
apt-get source ruby-pkg-tools
cd ruby-pkg-tools-0.13
dpkg-buildpackage
cd ../
dpkg -i  ruby-pkg-tools_0.13_all.deb
rebuild 需要满足 rdoc 包,rebuild rdoc 的话需要一堆的依赖,我偷懒了一把
ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc
apt-get source mongrel
cd mongrel-1.1.5
dpkg-buildpackage
cd ../
dpkg -i  mongrel_1.1.5-2_amd64.deb
依赖解决后,需要 hold ruby 1.8.6 的包,防止 upgrade 的时候再次升级。
aptitude hold irb1.8 libopenssl-ruby1.8 libreadline-ruby1.8 libruby1.8 mongrel rdoc1.8 ruby1.8 ruby1.8-dev ruby1.8-elisp

Friday, June 13, 2008

rails tips: 动态载入 JavaScript 文件

rails 中一般的 JavaScript 机制在 layout 中用 javascript_include_tag 载入需要的脚本文件,对默认整站需要的脚本文件来说很方便,但实际情况是我们经常需要在某些页面动态载入需要的脚本文件来避免调用过多外部文件影响页面载入速度。rails 提供了 javascript_include_tag 和 register_javascript_include_default 都可以用来载入脚本文件,register_javascript_include_default 每次调用都会增加一项到 @@javascript_default_sources,会导致重复载入同一文件,文档中已说明 register_javascript_include_default 用来在 plugin 载入时更改默认载入脚本。所以正确的方法应该是 javascript_include_tag。

javascript_include_tag 后调用直接输出 html script 标记,意味着脚本在 body 解释时才会载入,而我希望的结果是放置到 head 标记内。第一反应是搜索文档看是否存在 response 动态增加载入 javascript 的方法,rails 并没有提供此方法。正觉得无奈的时候忽然想到 rails layout 中用到了 yield,这里不是可以用 yield 达到同样的结果吗。 layouts/application.thml.erb

<%= javascript_include_tag :defaults %>
<%= yield :javascript_files %>
在需要载入的模板文件中:
<% content_for :javascript_files do -%>
<%= javascript_include_tag("some_file_to_load_on_demand.js") -%>
<% end -%>

Tuesday, June 03, 2008

用 monit 自动启动 mongrel 和 backgroundrb 服务

Capistrano 部署 Rails 项目速记中解决了代码更新时候 mongrel/backgroundrb 重启等问题,还需要保证系统重启时服务能够自动启动。

mongrel cluster 自带了 mongrel-cluster 启动管理脚本,Debian 系统的话链接 mongrel_cluster.yml 到 /etc/mongrel-cluster/sites-enabled/ 目录,系统启动的时候 /etc/init.d/mongrel-cluster 会自动启动 mongrel daemon,然而 backgroundrb 的启动问题还是没有解决,需要手工写启动脚本,google 了一番之后,找到 Monit 这个小工具:

# 摘自 monit deb package description.
A utility for monitoring and managing daemons or similar programs
 monit is a utility for monitoring and managing daemons or similar
 programs running on a Unix system. It will start specified programs
 if they are not running and restart programs not responding.
 .
 monit supports:
  * Daemon mode - poll programs at a specified interval
  * Monitoring modes - active, passive or manual
  * Start, stop and restart of programs
是否可以用 Monit 来启动 mongrel 和 backgroundrb 呢,答案是肯定的,事实上这也应该是推荐方式。

安装 Monit

$sudo aptitude install monit
修改 /etc/default/monit 配置:
startup=1
CHECK_INTERVALS=30 # monit 监控检测时间价格,推荐设置成 30 秒
配置 monit
$sudo grep '^[^#]' /etc/monit/monitrc
set daemon  30
set logfile syslog facility log_daemon
set httpd port 2812 and
     use address localhost  # only accept connection from localhost
     allow localhost        # allow localhost to connect to the server and
include /etc/monit/conf.d/*
$sudo mkdir /etc/monit/conf.d

配置 Daemon 项

$cat 001_neo_mongrel.conf
check process mongrel_neo_8000
  with pidfile /project/code/path/shared/pids/mongrel.8000.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8000"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8000"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo

check process mongrel_neo_8001
  with pidfile /project/code/path/shared/pids/mongrel.8001.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8001"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8001"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo

check process mongrel_neo_8002
  with pidfile /project/code/path/shared/pids/mongrel.8002.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8002"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8002"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo
$ cat 003_neo_brb.conf
check process brb_imigu_11006
  with pidfile /project/code/path/shared/pids/backgroundrb_11006.pid
  start program = "/bin/su -c 'cd  /project/code/pathcurrent && RAILS_ENV=production nohup ./script/backgroundrb start > /dev/null 2>&1' josh"
  stop program = "/bin/su -c 'cd /home/josh/www/imigu/current && RAILS_ENV=production && ./script/backgroundrb stop' josh"
  group neo

启动 Monit 和监测

$sudo /etc/init.d/monit restart
$sudo monit -c /etc/monit/monitrc status #查看系统状态
通过 monit 已经可以自动启动管理 mongrel 和 backgroundrb,那么谁来保证 monit 的稳定运行呢,答案是 linux 系统 init。 编辑 /etc/inittab 加入:
# Run monit in standard run-levels
mo:2345:respawn:/usr/sbin/monit -Ic /etc/monit/monitrc
mo:06:wait:/usr/sbin/monit -Ic /etc/monit/monitrc stop all
重启 monit
$sudo /etc/init.d/monit stop
$sudo telinit q

参考:

  • Monit man page
  • 2008, Ezra Zygmuntowicz and Bruce Tate, Deploying Rails Applications

Friday, May 30, 2008

Capistrano 部署 Rails 项目速记

项目快上线了,以前一直采用传统的方式进行部署,从最早的 FTP 到后来的 SVN+SSH,既然现在是 Rails 项目,当然试一把 Capistrano。

安装

使用 Capistrano 进行部署只需要在本地机器安装 Capistrano 即可,Capistrano 通过 SSH 与服务器端进行交互。

gem install -y capistrano
当前最新版本是 2.3.0。

配置

Ubuntu 8.0.4 上 gem 包相关的 bin 目录并不在系统路径中,需要手工加入gem bin 路径:

$cat "export PATH=$PATH:/var/lib/gems/1.8/bin" >> .~/bashrc
$source ~/.bashrc

生成基础配置文件:

$cd RAILS_APP_DIR
$capify .

调整 config/deploy.rb 中相关配置项,并加入一行:

set :runner, "ACCOUNT_NAME"
用你服务器端的登录用户名取代 ACCOUNT_NAME,如果不设置此行,默认用户为 app,会导致设置失败。

初始化服务器端目录:

$cap deploy:setup
Capistrano > 2.3.0 开始默认启用 sudo,所以,服务器需要支持 sudo 支持,将 ACOUNT_NAME 加入到 sudo group, 并确认 /etc/sudoers 中设置:
# Uncomment to allow members of group sudo to not need a password
 %sudo ALL= ( ALL ) NOPASSWD: ALL

SSH 自动登录:

$ssh-keygen -t dsa
$chmod 700 ~/.ssh
$scp ~/.ssh/id_dsa.pub USER_NAME@REMOTE_SERVER
在服务器:
$cat id_dsa.pub >> ~/.ssh/authorized_keys
$rm -f id_dsa.pub

运行设定和依赖检查:

set :deploy_via, :remote_cache
set :runner, "josh"
depend :remote, :gem, "chronic", ">= 0.2.3"
depend :remote, :gem, "packet", ">= 0.1.5"
depend :remote, :command, "gnuplot"
depend :remote, :command, "svn"
depend :remote, :command, "mongrel_cluster_ctl" # make sure /usr/sbin in the $PATH
需要注意的是 debian 中的 mongrel_cluster_ctl 脚本在 /usr/sbin 下,而通过 ssh 获得的系统 $PATH 并没有包含 /usr/sbin 目录,需要修改 .ssh/environment 和 ssh 的相关配置加入 /usr/sbin 目录。 Mongrel && backgroundrb 启动配置
rails_env = "production"
set :mongrel_environment, "production"
set :mongrel_conf, "#{deploy_to}/current/config/mongrel_cluster.yml"

namespace :deploy do
  
  desc "Restart the Mongrel cluster and backgroundrb"
  task :restart, :roles => :app do
    stop
    start
  end
  desc "Start the mongrel cluster and backgroundrb"
  task :start, :roles => :app do
    mongrel.cluster.start
    start_backgroundrb
  end
  desc "Stop the mongrel cluster and backgroundrb"
  task :stop, :roles => :app do
    mongrel.cluster.stop
    stop_backgroundrb
  end

  desc "Start the backgroundrb server"
  task :start_backgroundrb , :roles => :app do
    begin
      puts "starting brb in folder #{current_path}"
      run "cd #{current_path} && RAILS_ENV=#{rails_env} nohup ./script/backgroundrb start > /dev/null 2>&1"
    rescue RuntimeError => e
      puts e
      puts "Problems starting backgroundrb – running already?"
    end
  end
  desc "Stop the backgroundrb server"
  task :stop_backgroundrb , :roles => :app do
    begin
      puts "stopping brb in folder #{current_path}"
      run "cd #{current_path} && ./script/backgroundrb stop"
    rescue RuntimeError => e
      puts e
      puts "Backgroundrb appears to be down already."
    end
  end
end

需要注意的是 Capistrano 每次 deploy 的时候会重新检出代码,用户上传文件需要单独做 link:
namespace :assets do
  task :symlink, :roles => :app do
    run <<-CMD
rm -rf #{release_path}/assets &&
ln -nfs #{shared_path}/assets #{release_path}/assets
CMD
  end
  after "deploy:update_code" , "assets:symlink"
  
  task :create_dirs, :roles => :app do
    %w(assets).each do |name|
      run "mkdir -p #{shared_path}/#{name}"
    end
  end
  after "deploy:setup", "assets:create_dirs"
end

参考文档:

Thursday, April 24, 2008

MySQL InnoDB 性能调节 Gotchr

按照Innodb Performance Optimization Basics文章调谐 MySQL InnoDB 的性能,结果重启出现错误:

ERROR 1033 (HY000): Incorrect information in file: './imigu_dev/demo.frm'

google 了一番,也没有确切说法,一条一条恢复 my.cnf 中修改的部分测试,发现是 innodb_log_file_size 这行出了问题。 这里给出了解答

  • 退出 MySQL,确定无错误信息。
  • 删除 log。
  • 修改配置重启

refs:

  • http://blogs.sun.com/luojiach/entry/mysql_innodb_performance_tuning_for

Friday, March 14, 2008

ruby block 局部变量

今天遇到的问题,在 block 中定义的变量为局部变量,无法在 block 外以及下一次迭代中使用,必须定义在 block 开始之前。

Wednesday, March 12, 2008

flymake 运行 rails scripts/runner 脚本文件

写了几个脚本,用到了 rails script/runner: {{{ #!/usr/bin/env /project_path/script/runner }}} 结果发现 emacs flymake mode 执行了这个文件,而不是默认的 c (check) 语法检查。 去官方看了一下 bug,原来已经有人报告过了, 修改为 {{{ #!/usr/bin/ruby /project_path/script/runner }}} 问题修正。反正系统只会是 linux,没有这烦人的问题就成。

Tuesday, February 26, 2008

rails tips

随手记录开发中遇到的小问题,备忘。

install plugins

undefined method `paginate' for
安装 plugin 后,需要重启 web server。

radio for boolean field

<%= f.radio_button :direction, "true" %>
<%= f.radio_button :direction, "false" %>

selected for options key value pairs array

it didn't well documented, here is the example:
	  <%= select_tag(
	      :sector_id,
	      options_for_select(
	        [["--请选择--", ""]].concat(Sector.get_for_list.collect {|o| [ o.name, o.id ] }), 
	        [@sector.id, @sector.name])
	      )
	  %>

Monday, January 21, 2008

tar 解压单个文件

每次都得查 man,备忘一下。

tar -tvf from.tar.gz | grep something
tar xvf from.tar.gz something.path

Monday, January 14, 2008

ubuntu 下无显示器时的分辨率问题

手头一台机器,做为 repos server 和 desktop 混合用途,偶尔远程登录上去使用。开启了 GNOME 默认的远程桌面(vino),GDM 的自动登录,客端用 xvncview 登录。多余出来的显示器正好配合本本玩 dual monitor。重启后发现问题,X 没有探测到显示器,fallback 到 640x480 的桌面。需要在 xorg.conf 中 monitor 节做如下设定:

   HorizSync       30.0 - 82.0
   VertRefresh     56.0 - 76.0
重启 gdm 恢复正常分辨率大小。