Xupeng's blog

圆外之大,心向往之

使用 VPS 和 Gentoo 打造安全高效的个人网络基地 – 安装 Gentoo

首先需要使用 Linode 的管理后台部署一个 64 位系统,利用它来安装 Gentoo,我选择了使用 CentOS,部署 CentOS 时我只使用了我一小部分的磁盘空间(2G),以便留下足够的空间给 Gentoo 使用。

部署完 CentOS 后,可以从 Linode 的管理后台看到多了一个叫 My Centos 5.2 64bit Profile 的 Configuration Profile,这个 Profile 的第一个磁盘是部署 CentOS 时创建的磁盘,可以创建另外一个磁盘用来安装 Gentoo,创建完之后编辑 My CentOS 5.2 64bit Profile,把新创建的磁盘挂载到 /dev/xvdc

此时就有了一个可以启动的 64 位 CentOS,它有三个磁盘,第一个磁盘 /dev/xvda 是 CentOS,第二个磁盘 /dev/xvdb 作为交换分区,第三个磁盘 /dev/xvdc 将被用来安装 Gentoo。

首先要让 Gentoo 能够在Linode 启动,Linode VPS 基于 Xen,在 Xen 中构建一个 Linux 系统跟在物理机上安装一个系统有些许不同,但总的来说更容易。启动 Centos,从管理后台看到状态改变 为 running 之后就可以通过 SSH 连接,登陆之后可以看到 /dev/xvdc 的存在。

  1. 下载Gentoo stage3 amd64版本:
    cd
    wget http://gentoo.chem.wisc.edu/gentoo/releases/amd64/ \
         current/stages/stage3-amd64-008.0.tar.bz2
  2. 挂载/dev/xvdc,解压stage3,并且chroot到Gentoo环境中:
    mkdir /root/gentoo
    mount /dev/xvdc /root/gentoo
    tar xf ../stage3-amd64-2008.0.tar.bz2 -C /root/gentoo
    cp /etc/resolv.conf /root/gentoo/etc
    mount -t proc proc /root/gentoo/proc
    mount -o bind /dev /root/gentoo/dev
    chroot /root/gentoo /bin/bash
  3. 更改系统时区设置:
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  4. 编辑/etc/conf.d/clock,设置:
    CLOCK="local"
    TIMEZONE="Asia/Shanghai"
  5. 更新portage tree:
    emerge --sync
  6. 升级portage:
    emerge -av portage

要让 Gentoo 能够在 Linode 的 Xen 环境下正常启动并工作起来,有一些工作要做:

  1. 编辑/etc/fstab。
    /dev/xdva / ext3 defaults,noatime 0 1
  2. 安装dhcpcd。我们使用DHCP来动态获取IP/主机名/DNS等信息而不是手动设定:
    emerge -av dhcpcd
    echo 'config_eth0=( "dhcp" )' >> /etc/conf.d/net
  3. 使sshd自动启动。
    rc-update add sshd default
  4. 更改root密码。
    passwd

到此为止,Gentoo 系统就是 boot ready 的了,与物理机安装 Gentoo 不同,在 Xen 中安装 Gentoo 不需要编译内核,Linode 已经提供了多个可供 Xen 使用的内核,有稳定的 2.6.16/2.6.18,也有最新的 2.6.28。在它可以启动之前,需要在 Linode 的管理后台创建一个新的 Profile,在 Profile 的 配置中,可以选择要使用的 kernel,我比较喜欢尝鲜,所以我选择的是2.6.28,除了内核之外需要把安装了 Gentoo 的那个磁盘挂载到 /dev /xvda,之前在配置 /etc/fstab 时也配置了 /dev/xvda 为根。

Ok,保存新的 Profile,停掉 CentOS,启动为 Gentoo 新创建的 Profile,等待两分钟,幸运的话,第一次就可以成功的登陆新打 造的 64 位 Gentoo,如果有些不幸,那也没有关系,可以使用 Linode 的 Lish 登陆查看 console 以便进行 debug,这就具体问题具体分析 了。成功启动后,得到一个最基本的 Gentoo 系统,还有一些基本的系统升级、基础配置工作需要做,接下来:配置 Gentoo

使用 VPS 和 Gentoo 打造安全高效的个人网络基地 – 开篇

是的,我承认我有点偏执有点疯狂,有点完美主义,我要使用 VPS+Gentoo 打造我的个人网络基地,所涉及到的软件和系统会有 Gentoo, Apache, Nginx, tinyproxy, daemontool, Blog, Trac 等等以及以后可能会使用的一些系统,还会涉及到 Linux 的安全配置和优化,借此记录一下完整的构建过程,留作日后参考。

VPS 我选用了 Linode,并且放在了 Linode 在 Fremont 的机房,因为有网友讲对中国用户来说 Fremont 的机房是网速最快的,经过测试的确是要比 Dallas 的机房快不少。

Linode 提供对多个 Linux 发行版的支持,比如:Arch, CentOS, Debian, Fedora, Gentoo, OpenSUSE, Slackware, Ubuntu 等等,我偏爱 Gentoo,这也是我最初选择 Linode 的原因之一,但是很无奈 Linode 提供的 Gentoo 镜像是 2007.0,已经是相当老了,Gentoo 有一个比较严重的问题在于升级时间间隔过长的话(2个月以上?),在升级过程中会有很大的概率遭遇各种奇怪的问题,比如循环依赖,比如某些 lib 坏掉,再比如某些 lib 升级后需要 revdep-rebuild 等等,如果是初次遇到类似的问题还真是比较棘手,另外一个问题是,隔很长时间才更新一次也就意味着会有相当多的软件包需要升级,如果是服务器的话可能会在比较长的一段时间内影响到正在运行的服务。

即便我认为 Gentoo 也有它的诸多不是,当相对于它带给我的好处来说那也只能算是吹毛求疵,所以我还是选择了 Gentoo,因为我实在喜欢 Gentoo 给我的掌控力,我可以简单地通过 USE 来控制每个软件包的编译参数,去掉一切我不需要的功能使它跑得更欢实也更安全,Gentoo 让我在新的软件和高可靠性之前找到了一个恰当的平衡点,因此与其说我用 Gentoo 是为了自己根据硬件调整编译参数来提高性能,倒不如说是为了 Gentoo 给我的掌控能力和我的尝鲜欲望,或者说仅仅是为了我作为 Linux 狂热爱好者的 Gentoo 情节。

Linode 没有提供 64 位的 Gentoo,于是我打算自己在 Linode 安装一个,借助 Linode 提供的多个磁盘镜像和强劲的 CPU 资源,使得从 stage3 安装一个 Gentoo 不是什么难事。

继续阅读下一篇:使用VPS和Gentoo打造安全高效的个人网络基地 - 安装Gentoo

使用 PostgreSQL 时遇到的编码错误

PostgreSQL 数据库的编码为 UTF8(在 PostgreSQL 里 UNICODE 是 UTF8 的别名,二者要表达的意义是一样的),当往数据表的 varchar 字段里插入字符串的时候,遇到编码错误:

1
2
3
test=# insert into bb values (E'\x80\x02]q\x01(U\x01aU\x06\xe5\x93\x88\xe5\x93\x88q\x02e.');
ERROR:  invalid byte sequence for encoding "UTF8": 0x80
HINT:  This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".

为了理解造成这个错误的原因,我和小蔡花了差不多一个小时在这上面,从这个错误的字面意义上理解,是在以 UTF8 编码存储这个字符串的时候,遇到了编码错误,其实类似这样的编码错误在使用 Python 进行文本解析做编解码时会经常遇到,但又通常忽略之。

还是从遇到这个问题的源头说起,起因是要使用 cPickle 把一个不算太大的 Python dict 序列号以后存储到数据库中,但是在使用默认参数进行序列化后向数据库中存的时候就遇到了类似上面的编码错误:

1
2
3
data = {'title' : 'This is the title', ......}
s_data = cPickle.dumps(data, 2)
# Insert s_data into PostgreSQL database table

在经过一番 RTFM 和揣摩验证之后发现,当往 UTF8 的 PostgreSQL 数据库中存储字符串时,PostgreSQL 会根据 client_encoding 判断字符串的编码,然后根据这个编码解码,再编码为 UTF8 进行存储。可以在 PostgreSQL 的 console 下使用 show client_encoding 来查看当前的客户端编码,同时也可以使用 \encoding CLIENT-ENCODING 来设置客户端编码。

我的客户端编码为 UTF8,同时数据库编码为 UTF8,因此 PostgreSQL 把我提交的字符表当做 UTF8 串来对待,而再回头看我要插入的字符串: “\x80\x02]q\x01(U\x01aU\x06\xe5\x93\x88\xe5\x93\x88q\x02e”,这下恍然大悟了,为什么呢?因为这根本不是一个合法的 UTF8 串,错误消息也明确的说\x80是’invalid byte sequence for encoding “UTF8”’,好,那看一下 UTF8的定义:

80-BF是只能出现在多字节字符的第二、三或者第四字节,而在这个字符串中它却出现在了第一个字节,因此很显然它不是合法的 UTF8 串。那为什么会有这样的一个字符串呢?恩,是我的字段拿 cPickle.dumps(data,2) 序列化以后产生的,经过试验,在使用 cPickle.dumps(data,2) 对字典做序列化后,会有 \x80 作为前缀,如此以来,这个序列化后的串就不能被存储在 UTF8 的 PostgreSQL 数据库中,但是事实上使用 protocol 1 来进行序列化就可以了:

1
2
3
data = {'title' : 'This is the title', ......}
s_data = cPickle.dumps(data, 1)
# Insert s_data into PostgreSQL database table

分享一点关于虚拟主机的经验

到现在为止我用过三家的虚拟主机,积累了一点点的经验教训,我想这丁点东西对刚接触虚拟主机的兄弟们可能会有一些用处。

我用的第一个虚拟主机是51boo.com,这是当时国内号称唯一支持Django,有SSH的虚拟主机,兴高采烈的花了199买了一年的服务,没成想只用了两个月51boo.com就销声匿迹了,于是我的第一个虚拟主机就这样灰飞烟灭了。

51boo给了我一个教训:不要贪便宜,况且那样的资源那样的价格也不便宜,国内的主机服务不靠谱,这不仅仅跟国内的政策有关系,还和部分主机提供商的责任心有关系,我想我不会再在国内买主机了。

第二个是Hostmonster.com,说实话,Hostmonster还不错,只是它目前不太适合我了。买Hostmonster的主机时主要看中了它的这些东西:

  1. 便宜。一个月4.95或者5.95美元
  2. 无限的存储空间和带宽
  3. 有很好的数据备份服务
  4. 提供免费的域名
  5. 有SSH
  6. 可以使用fastcgi来跑Django应用
  7. … …

但是使用了几个月以后我还是失望了,因为我发现在hostmonster用fastcgi跑Django非常的慢,另外他们是有CPU和内存使用限制的,尽管我买的时候没有注意到。前不久突然收到Hostmonster的邮件,说我的服务被停止了,因为我的站点造成了性能问题,我的数据也会在15天后被删除,而事实上我仅仅是跑了一个访问量很小的blog。这可吓了我一跳,赶紧去看我的站点,发现已经不能访问了。后来在他们的support站点上和他们的售后进行交涉,总算把服务给我恢复了,但让本来就有些不太满意(主要是至指对Django的支持)的我失去了信心,于是就打算换到另外一家服务商去。

就在我打算换服务商的时候,我发现我干了一件蠢事:我使用的域名不能转到别的域名提供商去。因为这个域名是在购买hostmonster的服务时“免费”送的,域名的Techinical Information中的email被修改成了support@hostmonster.com,我无法收到域名transfer确认邮件,因此也无法完成域名转移,更可悲的是hostmonster那里的域名管理系统只开放了很有限的控制功能,没有办法把我的子域名指向别的主机,这也就意味着我以前的域名只能在hostmonster使用了,惨。

现在我换到 Linode 有将近两个月了,目前还是很满意的,VPS给我了最大的自由度,这很讨我这个喜欢折腾的人的欢心,现在我除了把我的blog跑在了上面,还有我的个人知识管理系统,代理服务器啊,还有其他一切我自己需要的服务,我将要它变成我个人的网络基地,把我日常使用的软件都迁移到网络上去,让自己的生活更轻松更方便,回头再专门写blog介绍如何搭建一个安全高效的个人服务器吧。

在经过这一段使用虚拟主机的经历之后,简单总结一下教训,就是:

  1. 千万不要使用主机提供商“免费”赠送的域名,尤其是当这个域名对你很重要的时候,否则日后换服务商的时候会吃大亏。 1.不要被服务商广告里的噱头给迷惑了(比如无限存储空间,无限带宽,因为除非你开下载站,否则你根本用不了多少),要盯紧了看看自己真正需要的东西能不能得到满足。

更新了一下两年前写的用来从百度下载歌曲的脚本 - getsong

前一阵子有网友告诉我我两年前写的从百度下载歌曲的脚本不工作了,原因呢是百度修改了歌曲 URL 的加密算法,嗯,我是挺久没有使用过这个脚本了,最近也比较忙,今天花了点时间看了一下,对脚本做了一下更新,功能与之前没有任何的改动,只是修改了解析歌曲 URL 的部分,让它现在可以工作了。 之前最新的代码放在了啄木鸟社区的 SVN 仓库,google code 只有一个比较老的版本,不过这次把代码提交到了google code,以后如果再有更新的话也都会提交到 google code 去。 项目地址是:http://code.google.com/p/getsong/,可以从 SVN 仓库中 checkout 最新的代码: svn checkout http://getsong.googlecode.com/svn/trunk/ getsong 或者下载目前最新的可工作版本:http://getsong.googlecode.com/files/getsong.tar.gz