在 Mac OS X Snow Leopard 上安装 Ruby 和 Rails

昨天刚发布的 Rails 3.0.6 包含重要的安全更新,所以刚好在升级 Rails 的时候顺便把 Ruby 也升级一下。Mac OS X Snow Leopard 默认的 Ruby 版本是 1.8.7 的,貌似直接源代码编译升级到 1.9.2 有一些问题(网上有不少人升级到 1.9.2 的时候出问题)。最好的办法是用 RVM (Ruby Version Manager),又简单又方便,而且不会替代系统自带的 Ruby 1.8.7,以后可以随时在 1.8.7 和 1.9.2 之间切换,适合开发和移植程序,Rails 3 也支持 Ruby 1.9.2 版本。

安装必要工具

安装前确定 Mac OS X 已经安装了最新的 Xcode 开发工具,至少是 3.2.1 版本。然后安装 git 工具:

$ xcodebuild -version
Xcode 3.2.6
Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
BuildVersion: 10M2518

$ sudo port install git

安装 RVM

安装 RVM 的方法有点不同:

$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

如果有代理的话,用 -x 设置代理服务器:

$ bash < <( curl -x 192.168.0.1:3128 http://rvm.beginrescueend.com/releases/rvm-install-head )

配置 RVM:

$ vi ~/.bashrc
# This loads RVM into a shell session.
[[ -s "/Users/vpsee/.rvm/scripts/rvm" ]] && source "/Users/vpsee/.rvm/scripts/rvm"

关闭 Terminal 后重新打开以便 .bash_profile 文件生效,这个时候用下面命令可以验证 rvm 是否安装成功:

$ type rvm | head -n1
rvm is a function

安装 Ruby

安装最新的 Ruby 1.9.2-p180 稳定版本:

$ rvm install 1.9.2

系统上原来是 1.8.7 的,把系统默认的 ruby 解释器设置成 1.9.2:

$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]
$ rvm --default 1.9.2
$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.7.0]

检查 gem 版本是 1.3.7 或以上,以及 sqlite3 版本是 3.6.12 或以上,然后使用 gem 安装 sqlite3-ruby:

$ gem -v
1.3.7

$ sqlite3 -version
3.7.5

$ gem install sqlite3-ruby
/Users/vpsee/.rvm/rubies/ruby-1.9.2-p180/bin/gem:4: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777

$ sudo chmod go-w /usr/local/bin
$ gem install sqlite3-ruby

安装 sqlite3-ruby 的时候出现目录权限警告, 修改一下 /usr/local/bin 的权限就好了。

安装 Rails

安装 Rails 3.0.6 版本:

$ gem install rails

$ rails -v
Rails 3.0.6

升级 Ruby 和 Rails 完毕后我们就在 Snow Leopard (Mac OS X 10.6.7) 上有了一个最新的 Ruby on Rails 开发环境。

几个 Nginx 子目录 rewrite 的例子

我们已经有很多客户在 VPS 上使用 Nginx,对于刚从 Apache 转过来的客户最常遇到的一个问题就是怎么弄 Nginx 下的 rewrite 以及怎么把 Apache 里的 .htaccess 转化成 Nginx,网上关于这方面的资料一大堆,关于 wordpress, discuz, phpcms, ecshop, shopex 等的 rewrite 应有尽有,直接 copy 就可以。还有一个 Nginx 新手常见的问题是拿到这些 rewrite 规则后不知道怎么改,比如 Nginx 下子目录的 rewrite 应该改成什么样子?/ 下是 wordpress,/bbs 下装个 discuz,/ 是 discuz,/blog 下装个 wordpress 或者 / 下是 wordpress,/blog 下再装个 wordpress 等,这样的 rewrite 怎么改呢?弄几个例子放到我们的 FAQ 里供参考:

WordPress 安装在子目录 /blog 下:

location /blog/ {
    root   /home/www/vpsee.com;
    index  index.php index.html index.htm;
    if (!-e $request_filename) {
       rewrite ^.+/?(/blog/wp-.*) $1 last;
       rewrite ^.+/?(/blog/.*\.php)$ $1 last;
       rewrite ^(.+)$ /blog/index.php?q=$1 last;
    }
}

Discuz! 7.2 安装在子目录 /bbs 下:

location /bbs/ {
    root   /home/www/vpsee.com;
    index  index.php index.html index.htm;
    rewrite ^/bbs/archiver/((fid|tid)-[\w\-]+\.html)$ /bbs/archiver/index.php?$1 last;
    rewrite ^/bbs/forum-([0-9]+)-([0-9]+)\.html$ /bbs/forumdisplay.php?fid=$1&page=$2 last;
    rewrite ^/bbs/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /bbs/viewthread.php?tid=$1&extra=page%3D$3&page=$2 last;
    rewrite ^/bbs/space-(username|uid)-(.+)\.html$ /bbs/space.php?$1=$2 last;
    rewrite ^/bbs/tag-(.+)\.html$ /bbs/tag.php?name=$1 last;
}

Discuz! X1.5 安装在子目录 /bbs 下:

location /bbs/ {
    root   /home/www/vpsee.com;
    index  index.php index.html index.htm;
    rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last;
    rewrite ^([^\.]*)/article-([0-9]+)-([0-9]+)\.html$ $1/portal.php?mod=view&aid=$2&page=$3 last;
    rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
    rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last;
    rewrite ^([^\.]*)/([a-z]+)-(.+)\.html$ $1/$2.php?rewrite=$3 last;
    if (!-e $request_filename) {
        return 404;
    }
}

如果对理解 ^([^\.]*)/([a-z]+)-(.+)\.html$ 这样的正则表达式有困难并对这方面有兴趣的话可以看看一些书,最好的一本应该是 O’Reilly 出的 Mastering Regular Expressions(也有中文版:《精通正则表达式》)。

使用 Nginx 和 GeoIP 模块来处理不同国家的访问

如果想屏蔽某个地区的 IP 访问的话,用 iptables 把来自某个国家的 IP 重定向到预定页面不是特别灵活的办法,如果只有一个 IP 可用而有多个网站在同一 VPS 上怎么办?用 iptable 屏蔽某个网站的话也会屏蔽同一 VPS 上的其他网站的访问。所以正统的办法还是用 GeoIP 配合对应的 web 服务器模块,比如:apache + mod_geoip 或者 nginx + http_geoip_module 等。

安装 Nginx

因为要用到 http_geoip_module 模块,系统自带的 nginx 一般不带这个模块,所以要下载 nginx 源代码后自行编译:

# wget http://nginx.org/download/nginx-0.9.6.tar.gz
# tar zxvf nginx-0.9.6.tar.gz
# cd nginx-0.9.6
# ./configure --without-http_empty_gif_module --with-poll_module \
--with-http_stub_status_module --with-http_ssl_module \
--with-http_geoip_module
# make; make install

安装 MaxMind 的 GeoIP 库

MaxMind 提供了免费的 IP 地域数据库(GeoIP.dat),不过这个数据库文件是二进制的,需要用 GeoIP 库来读取,所以除了要下载 GeoIP.dat 文件外(见下一步),还需要安装能读取这个文件的库。

# wget http://geolite.maxmind.com/download/geoip/api/c/GeoIP.tar.gz
# tar -zxvf GeoIP.tar.gz
# cd GeoIP-1.4.6
# ./configure
# make; make install

刚才安装的库自动安装到 /usr/local/lib 下,所以这个目录需要加到动态链接配置里面以便运行相关程序的时候能自动绑定到这个 GeoIP 库:

# echo '/usr/local/lib' > /etc/ld.so.conf.d/geoip.conf
# ldconfig

下载 IP 数据库

MaxMind 提供了免费的 IP 地域数据库,这个数据库是二进制的,不能用文本编辑器打开,需要上面的 GeoIP 库来读取:

# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
# gunzip GeoIP.dat.gz

配置 Nginx

最后是配置 nginx,在相关地方加上如下的配置就可以了:

# vi /etc/nginx/nginx.conf

http {
...
geoip_country /home/vpsee/GeoIP.dat;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
...
}

server {
...
        location / {
            root   /home/vpsee/www;
            if ($geoip_country_code = CN) {
                root /home/vpsee/cn;
            }
            ...
        }
...
}

这样,当来自中国的 IP 访问网站后就自动访问到预定的 /home/vpsee/cn 页面。关于 Nginx + GeoIP 还有很多有用的用法,比如做个简单的 CDN,来自中国的访问自动解析到国内服务器、来自美国的访问自动转向到美国服务器等。MaxMind 还提供了全球各个城市的 IP 信息,还可以下载城市 IP 数据库来针对不同城市做处理。

Infinitie Networks:$9.99 256MB OpenVZ VPS

infinitie

Infinitie Networks 是 Eonix Corporation 旗下的一个注册服务品牌,2000年创立,现在提供几乎所有的 hosting 服务,从虚拟主机、Reseller、VPS/VDS 等到服务器租用、托管,VPS 业务里面又有 Xen VPS, OpenVZ VPS 和 Windows VDS,VPSee 建议避免这种看上去 “大而全” 的公司,什么都想做往往什么都做不好,世界上优秀的公司都是专注一个业务,比如 Rackspace, Softlayer 专注服务器租用,Linode, Slicehost 专注 Xen VPS,BlueHost 专注虚拟主机,Name 专注域名托管等等。Infinitie Networks 的服务器在凤凰城的 I/O 数据中心,虽然凤凰城不在西海岸,但凤凰城的有些机房对中国的速度比西海岸的某些机房还快,所以机房的位置不是很重要,重要的是机房提供的线路。这家不支持 PayPal 支付,更要命的是在他们的服务条款上的第15部分(Section 15. Early Termination Fee)居然对提前终止服务收取325美元的费用,也就是说买了他们的 VPS 后如果想提前终止使用的话需要额外付325美元,汗~,VPSee 不推荐这家服务商,建议大家从不知名服务商购买 VPS 的时候不要选择信用卡支付以及购买时注意看一下他们的用户服务条款(User Agreement)。VPS 配置如下:

256MB RAM
20GB 硬盘
250GB 流量
8 IPs
9.99美元每月

没有服务器硬件配置。

用 iptables 把来自某个国家的 IP 重定向到预定页面

上次我们介绍了如何用 iptables 屏蔽来自某个国家的 IP. 昨天有位客户想在他网站上阻止所有来自中国的 IP 并且把来自中国的访问重定向到某个预定的页面(或网站)。正统的做法应该是用 apache + mod_geoip 或者 nginx + http_geoip_module 来做,但是发现这位客户使用了 apache/directAdmin/suexec,suexec 好像和 mod_geoip 在一起有问题,VPSee 不想大动客户的配置,所以打算用 iptables 来实现这个要求。想法是这样的,用 iptables 把来自中国的流量全部导向到网站的 81 端口,并在 apache 上启动监听81端口,放上预定的页面(或网站)。

先到 IPdeny 下载以国家代码编制好的 IP 地址列表,比如下载 cn.zone:

# wget http://www.ipdeny.com/ipblocks/data/countries/cn.zone

得到需要的所有 IP 地址后,用下面的脚本逐行读取 cn.zone 文件并加入到 iptables 中:

#!/bin/bash
# Redirect traffic from a specific country to a specific page
# written by vpsee.com

COUNTRY="cn"
YOURIP="1.2.3.4"

if [ "$(id -u)" != "0" ]; then
   echo "you must be root" 1>&2
   exit 1
fi

iptables -F
iptables -X
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
iptables -A OUTPUT -o eth0 -j ACCEPT

# Redirect incoming http (80) from China to 81
for c in $COUNTRY
do
        country_file=$c.zone

        IPS=$(egrep -v "^#|^$" $country_file)
        for ip in $IPS
        do
           echo "redirecting $ip"
           iptables -t nat -I PREROUTING -p tcp --dport 80 -s $ip -j DNAT \
                   --to-destination $YOURIP:81
        done
done

iptables-save > /etc/sysconfig/iptables
chmod go-r /etc/sysconfig/iptables
service iptables restart

这样来自中国的 IP 访问 YOURIP 这个网站后就会自动导向到 YOURIP:81 这个端口,然后我们修改 apache 的配置,增加一个 Listen 81 和 以及在 DocumentRoot 里面放上预定的页面(或网站)就可以了。

CleverKite:$10 512MB OpenVZ VPS

cleverkite

CleverKite 是去年10月份在加利福利亚注册的一家LLC 公司,仍处于创业阶段,经过几个月的开发于今年1月正式开放。从他们网站的介绍来看他们的 CTO 来自 UC Berkeley 的 EE/CS 专业,技术背景很强。他们正在自己开发控制面板 “harmony” 估计今年年底可以完成。他们使用 Ksplice 来升级 Linux 内核,这样不用重启系统就可以完成内核升级。Ksplice 每月每个结点服务器收取的费用是9.95美元,和 Xen VPS 有自己的内核不同 OpenVZ VPS 的内核依赖母机上的内核,所以及时升级内核不重启对客户和服务商来说都是有价值的。他们的这款 VPS 正在打折,使用优惠码 LEB 会得到30%的折扣,折后只需要7美元每月,价格还不错。他们的数据中心在加州的 Tustin,租用的是 ServInt 的服务器。VPS 配置如下:

512MB RAM
10GB 硬盘
150GB 流量
10美元每月

服务器硬件配置信息:

Each main VS node (Supermicro) is powered by two of the latest generation Intel & AMD enterprise CPUs and paired with a minimum of 24GB of ECC registered memory for absolutely phenomenal performance. We also utilize hardware RAID10 disk arrays with hot-swappable hard drives.

Pinboard 的 PHP/MySQL 架构

Pinboard 是一个提供在线书签服务的网站,和 Delicious 类似,不同的是 Pinboard 不是免费的,而且是从一开始就收费——采用有趣的渐进式收费,也就是说每增加一个人、后来的人就需多付0.001美元(按照 number of users * 0.001 的公式),这样的收费方式利用了人们的 “趁便宜赶快买,明天会更贵” 的心理,提供了一套独特的收费模式。让 VPSee 惊讶的是他们背后的技术出奇的简单,没有 Fotolog 那种 MySQL 集群+Memcached 集群,也没有 Netlog 那么复杂的数据库切分。在他们的 About 页面上,这位来自罗马利亚的创始人说:

Pinboard is written in PHP and Perl. The site uses MySQL for data storage, Sphinx for search, and Amazon S3 to store backups. There is absolutely nothing interesting about the Pinboard architecture or implementation; I consider that a feature!

数据

1亿6千多万个书签
5200多万个标签
9400多万个 urls
989 GB 的数据

平台

MySQL
PHP
Perl
Ubuntu
APC
Sphinx
Cron jobs
Amazon S3

硬件

服务器 1:64 GB, 主数据库(master),用来存储用户数据和搜索;
服务器 2:32 GB, 备用主数据库(failover master),用来爬 feeds 等一些后台任务
服务器 3:16 GB, web 服务器和从数据库(slave)
另外提一下,他们租用的这三台服务器有两台是从 DigitalOne 租用的,还有一台是从 ServerBeach 租的。

pingboard arch

架构

  • 他们运行的是 Ubuntu 操作系统;
  • 每台服务器上(一共3台)均保留一份整体数据库的拷贝;
  • 网站运行在 16GB 的服务器上,数据库完全放在内存里,页面装载时间提高了10倍;
  • 采用 master-master 数据库架构加上一个只读的 slave,所有写操作都在一个数据库上进行,第二个 master 数据库服务器主要用来计算,比如统计全局链接数,用户统计等;每天晚上数据库用 mysqldump 备份,然后备份的数据以压缩的形式储存在 Amazon S3 上。
  • Perl 脚本用来运行后台任务,比如下载 feeds、缓存页面、处理 email、生成 tag 云标签、备份数据等。他们选择 Perl 的理由是因为自己很熟悉而且有大量的库可以使用。像 “最受欢迎的书签” 这样的功能一般都是在晚上里通过后台的定时任务(cron job)完成。PHP 用来生成 HTML 页面,没有使用任何 templating engine,也没有使用任何框架(framework)。APC 用来做 PHP 缓存,没有用其他缓存技术,Sphinx 用来做搜索引擎。

经验

  • 使用成熟、老掉牙的技术,这样保证网站和程序运行快而且不会因为软件 bug 丢失数据。(VPSee 非常赞同这点,使用简单和可以理解的技术,我们相信技术是拿来用的,不是拿来炫的。)
  • 保持小规模会有趣得多,当你自己亲自提供客服支持和与客户打交道的时候你会发现很有价值;
  • 服务器成本用每 GB 内存(或存储)的价格来衡量,Pinboard 最初使用的是 Linode 和 Slicehost 的 VPS,后来发现 VPS 不够用,随着内存增大 VPS 越来越贵,价格不如独立服务器。(按照 VPSee 的个人经验,低端(<= 4GB)用 VPS 划算、高端(>=16GB)用独立服务器划算。)
  • 按照服务划分服务器,比如 web 服务器就拿来做 web 服务器,最好不要拿来干别的。

VAZAPI:$4.99 256MB OpenVZ VPS

vazapi

VAZAPI 是 ServerMinds 旗下的面向低端的一个业务品牌,其创办人是 ServerMinds 的 CEO 也同时是 Graxis 的 CEO,Graxis 在2009年的时候收购了 Buzzservers 以及 SharedLayer, Zabogo 等,他们 CEO 提到他们的策略是收购一些 one man 工作室和小公司,整合资源和技术,然后重组合并到自己旗下变成一家稍大的公司,可是他们2009年收购的 SharedLayer 和 Zabogo 在2010年7月又卖给了 North Texas Connect Inc. 与其说是在收购、整合,不如说是在倒卖客户,老外对拉客户特别舍得下血本,记得在美国主机刚开始在中国流行的时候拉一个客户(通过推广链接购买)可以获得至少50美元的提成,甚至有的服务商给出120美元的诱人分成,相信大家都很怀念那个年代~~。他们的一个机房在芝加哥的 Continuum 数据中心(测试 IP:64.79.100.38),另一个机房位置在加州的 San Jose(测试 IP:199.48.146.2),他们的 VPS 使用 SolusVM 控制面板。除了 VPS 外他们还提供 美国,荷兰、英国、卢森堡四地的服务器租用业务。VPS 配置如下:

uVZ-1 uVZ-2
256MB RAM 512MB RAM
512MB Burst 1GB Burst
10GB 硬盘 20GB 硬盘
1TB 流量 1TB 流量
1 IP 2 IPs
4.99美元 9.99美元

服务器硬件配置信息:

Vazapi’s Virtual Private Servers are hosted on high-quality hardware nodes based on XEON Processors.

安装 OpenNebula 基于 Web 的管理控制台

我们一般用 onehost/onevm/onevnet 这些命令行工具来管理 OpenNebula 云计算平台,不过有个项目组开发了 OpenNebula Management Console 管理工具,基于 PHP 和 MySQL,安装和配置也不是很复杂,和配置普通 CMS 系统差不多。上周我们在两台服务器上安装和配置了一个最小的 OpenNebula 云计算平台,我们将在生产环境测试一段时间 OpenNebula,争取能用 OpenNebula 替换我们自己的脚本,并逐步用这个平台来统一管理我们的 Xen 服务器。VPSee 周末试了试这个基于 Web 界面的 OpenNebula 管理工具,界面简单清晰,使用也很方便。这个控制台管理工具(onemc)只能安装在前端(Front-End)服务器上。

安装必备软件包

onemc 是基于 PHP 和 MySQL 的,需要安装一些必要的软件包:

# yum install php php-mysql mysql-server php-curl php-xmlrpc httpd \
php-pear php-devel php-adodb

下载 onemc

下载和解压 onemc-1.0.0.tar.gz 后直接放在 apache 的默认目录里(懒得改 httpd.conf):

# cd /var/www/html
# wget http://dev.opennebula.org/attachments/download/128/onemc-1.0.0.tar.gz
# tar zxvf onemc-1.0.0.tar.gz
# cd onemc

配置数据库

# mysql -uroot -p
Enter password: 
mysql> create database onemc;
mysql> create user 'oneadmin'@'localhost' identified by 'oneadmin';
mysql> grant all privileges on onemc.* to 'oneadmin'@'localhost';
mysql> \q

# mysql -u oneadmin -p onemc < /var/www/html/onemc/include/mysql.sql

配置 onemc

# vi /var/www/html/onemc/include/config.php
...
// vmm: kvm or xen
$vmm = "xen";
...
// ADODB settings
$adodb_type = "mysql";
$adodb_server = "localhost";
$adodb_user = "oneadmin";
$adodb_pass = "oneadmin";
$adodb_name = "onemc";
...

登录

如果系统设置了 http_proxy 环境变量的话一定要先关闭,然后重启 one 和 httpd:

# unset http_proxy
# one stop; one start
# /etc/init.d/httpd restart

打开 http://172.16.39.110/onemc/index.php 页面后就会显示登录信息(172.16.39.110 是 OpenNebula 前端的 IP 地址),用户名和密码是安装和配置 OpenNebula 的时候在 one_auth 中设置的密码(cat "oneadmin:password" > one_auth)。

opennebula management console

GoVPSGo:$7 160MB Xen VPS

govpsgo

Go VPS GoEliteDataHosting 的创始人 Terri 卖掉 EDH 后新开的一家,他们以前是少数几个能提供低价的 FreeBSD Xen 的服务商,专注低价 BSD VPS 利基市场。Terri 是个不错的系统管理员,可是设计做的不怎么样,他们以前的 EDH 和现在的 GoVPSGo 的网站都很难看,这个可以理解,有很多好的技术人员就是没有设计天赋,不能理解的是为什么不能花钱请个设计呢或者至少可以上网买个模版吧,20-100美元左右的模版就足够了。虽然这家 VPS 服务商上个月才开张,但是考虑到 Terri 的技术不错加上又有 EDH 的实战运营经验,他们应该能很轻松驾轻就熟,唯一让客户担心的可能就是会不会像以前那样做一段时间后又把客户卖掉?Terri 声称卖 EDH 是个人的原因,不知道同样的原因会不会发生在 GoVPSGo 上。他们的服务器放在 Kansas City 的 Wholesale Internet,Wholesale 提供低价服务器托管和租用并有中文页面,国内有很多人代购这家公司的服务器。VPS 配置如下:

Go160Go Go256Go
160MB RAM 256MB RAM
320MB Swap 512MB Swap
10GB 硬盘 20GB 硬盘
100GB 流量 175GB 流量
7美元 10美元

服务器硬件配置信息:

Intel Core 2 Quad