我的Linux/Unix不完全折腾史

2012-07-24 23:00

我的Linux/Unix不完全折腾史

by

at 2012-07-24 15:00:00

original http://www.soimort.org/tech-blog/2012/07/24/distros.html

曾经折腾过的发行版

OpenSolaris

大一的时候因为参加ACM/ICPC而第一次接触到除了Windows以外的系统,因为当年北京赛的赞助商是Sun。

也是第一次接触到开源软件,JDK,NetBeans这些半懂不懂的名词。

北京赛后的讲座听了一堆关于Solaris的ZFS文件系统的好处,虽不懂但觉厉。结束后在场每人发一张OpenSolaris 2008.05的Live CD,第一次知道操作系统原来可以比Win XP的盗版碟还便宜。

比赛结束之后偶尔还会在VirtualBox上折腾一阵。后来还装了MilaX,精简的Live CD发行版。

其后几年见证了Sun的被收购,Oracle的种种劣行,以及OpenSolaris的无疾而终。

如今基于开源版Solaris内核的社区项目还有OpenIndiana,Illumos和Nexenta。但是没有了Sun这样的大公司强推,感觉整个Solaris的用户群已经非常小众(尤其是在桌面这一块)。

openSUSE

我在VirtualBox上安装的第一个Linux系统。初学者友好的发行版之一。选择它的原因是因为看到某师兄在用。

比起基于GNOME 2的OpenSolaris,当时装的openSUSE是使用KDE桌面的。不过它的漂亮界面并没给我留下什么深刻的印象,可能是因为笔记本性能问题,在虚拟机里面运行起来效果略卡。于是后来几乎就没再碰过。

后来GNOME 3发布之后,曾经用基于openSUSE的Live CD尝试过新的GNOME。但是没有用它的打算。

btw:openSUSE的安全策略在前一阵子被Linus喷过,因为它在用户执行一些最基本的日常任务时都会不胜其烦地要求输入密码。

Ubuntu

第一次使用Wubi安装。

初学者友好的发行版之一,基于Debian,但隐藏了许多底层细节,软件库的更新比Debian快。不知为何,它缺少吸引我的要素(大概是因为当时对GNOME 2无感),所以在安装之后就迅速地被我遗忘了。

再次接触到Ubuntu就是在Unity发布之后了。在尝试了可是说是史上最难用的Unity之后,我决定放弃它。

Linux Mint

第一次在硬盘分区上安装的发行版。

初学者友好的发行版之一,基于Ubuntu。出于当时对“轻量级桌面”的追求,我用的是基于LXDE的版本。

当时我没有继续用下去的理由是:1、进入桌面之后硬盘指示灯常闪,而且无从找到进程疯狂损耗硬盘的原因;2、LXDE很没有质感,鼠标点击窗口拖动觉得各种生硬。

尽管如此,Linux Mint还是在我硬盘上停留了相当长一段时间。直到iGEM 2010期间,还偶尔进几次Mint用来编译Linux平台下的程序。

Chakra

初学者友好的发行版之一,基于Arch。

在转移到Arch之前,Chakra显然是在我硬盘上停留时间最长的发行版之一。基本上从2011年年初到9月份之前都在折腾这个系统。

使用Chakra的契机是试图在旧的HP笔记本上使用Arch失败,还没装X就经常内核启动莫名其妙地freeze。于是就发现了Chakra这个Live CD发行版,还有学校服务器上正好有KDEmod的源。

Chakra的图形化安装界面是我见过最好的(没有之一),整个安装流程异常简单。

基于KDE SC的桌面定制得非常华丽。

当时Chakra和Arch的开发库还没有完全独立,因此想要的软件(SciTE编辑器)在Chakra的库里没有,可以直接拿Arch库里的过来安装。

但是逐渐一些问题出现了:

Chakra尚处于开发状态,很多东西还不稳定,有时候升级之后某些Bundle无法正常安装,双击安装之后就消失,新的桌面图标也没有出现,不知道安装去哪了。

Bundle系统这个东西本身就很坑爹。下载好的一个Bundle文件双击之后就自动安装,安装之后该文件就自动消失,隐藏了这中间的底层细节,这是它严重背离了Arch哲学的地方。

之所以需要Bundle这种东西,是因为Chakra试图做一个“纯粹KDE”的发行版,所以官方源里面只包含基于Qt的GUI程序,排斥一切GTK+程序。这也是个很坑爹的设定,因为许多GTK软件(Chromium,Firefox,GIMP,Inkscape)是难以找到功能相当的Qt替代品的。如果用户需要的只有一两个还好说,如果用户要用的GTK+程序多了,难道安装的每个Bundle里面都要包含各自的一套独立的GTK+库?

Chakra和Arch的关系很不明朗。虽然Chakra至今为止仍然使用pacman作为包管理方式,但是Arch是完全滚动升级,Chakra不是。难以知道哪些Arch的软件包可以用在Chakra上,哪些不能。

PC-BSD

基于FreeBSD+KDE的桌面BSD系统,DVD镜像看起来是个庞然大物。

BSD在桌面领域的应用鲜为人知。不知道是显卡驱动的问题还是Xorg移植的问题,总觉得BSD下的KDE桌面较Chakra的KDE桌面卡不少。

第一次接触到BSD的ports系统,体验了一把从编译到安装GNU octave需要七个多小时是什么概念。机器发热剧烈(很可能还是导致旧的HP笔记本后来显卡烧掉的间接原因……)。

FreeBSD的bootloader自成一体,可以引导Windows但是几乎没有像样的界面,所以安装之后赶紧用GRUB替换然后chainloader到BSD分区。

FreeBSD分区的文件系统更是自成一体,UFS2,在Linux下读写有困难。

总结,BSD只适合服务器,就目前来看,的确不适合用来做桌面环境。遇到麻烦也诸多不便。

Slackware

最古老的发行版之一,项目主页的样式古老,开发方式古老,光盘镜像的发布风格古老,包管理方式古老。

优点是架构简洁,对上游软件代码几乎不做额外的定制,采用类BSD风格的初始脚本。适合中高级用户DIY。以前包依赖关系的处理是个比较头疼的问题,所幸有slapt-get的出现。

缺陷是如今比起其他发行版,更缺少相对活跃的社区,文档较为匮乏。完全采取封闭式开发,版本发布缓慢,官方软件库过于陈旧,且提供的桌面环境只有KDE。但稳定性和持久性的确是这种方式带来的一大好处,这是Gentoo和Arch所不能比拟的。

Slax

本质上是基于Slackware的一个最小化定制Live CD。它是一个非常有趣的发行版。首先,它内置syslinux作为bootloader,镜像可以简单地拷贝到U盘或者移动硬盘的FAT32分区上,只要执行官方提供的脚本就能够写入MBR用来引导系统,完全不需要使用其他发行版制作Live USB所必需的UNetbootin等外部工具;其次,它镜像文件系统内的包是高度模块化的,如果只需要Slax Core,可以做到非常之小,即使再加上KDE 3桌面环境、Firefox和一些基础的开发工具,总计也不超过200M。

除了Slax之外,由Slackware衍生来的还有其他一些有趣的轻量级Live CD,诸如SliTaz和Zenwalk。它们保持了Slackware的高度稳定性和可定制性,当然,也继承了Slackers的开发更新缓慢的特性。

Parted Magic

已经不记得什么时候开始起用的Parted Magic了,这个发行版一直以来常驻U盘,用来做系统灾难时的数据抢救、GRUB恢复,当然还有折腾新系统前对硬盘进行各种分区准备工作。

后来因为这个发行版更新得太频繁,不想每次更新都重写一次U盘镜像,于是把iso放在硬盘的一个分区里通过burg来引导。

再后来就开始习惯在电脑上装双Linux,一个系统出问题了还有另一个,于是Parted Magic就很少再需要用到了。

Gentoo

拿到了学校的Dell四核笔记本后,我决定尝试Gentoo。

Gentoo是基于源码的发行版,也是让我从真正意义上戒掉了对Windows依赖的第一个Linux发行版。之前用Chakra仅仅还是停留在“玩”的阶段,并没有真正用它来写代码和处理日常工作什么的。直到转移到Gentoo,才开始习惯了用Linux工作(或者不如说是习惯了用Openbox工作)。

用Gentoo之前习惯了KDE这种重量级的桌面环境,WM只知道一个Fluxbox(之前在Slax下面弄的)。认识了一个德国人,用Arch+Openbox,才知道窗口管理器并不是什么已经淘汰的老古董,正好Gentoo的wiki上面有详尽的Openbox教程,于是开始接触Openbox,还有tint2、feh、conky、idesk、cairo-dock,一堆乱七八糟的组件。

Gentoo下面没有太多现成的东西,但是也因此更容易把系统定制成符合自己习惯的工作方式。

从Gentoo最初的stage3安装成功,到定制出适合自己的Openbox环境,再到通宵编译整套的KDE,整个过程不但是对机器性能的考验,更是对搜索和阅读文档能力的考验。

在我看来Gentoo最突出的一点是有着强大的技术社群(Ubuntu衍生版用户的普遍水平是比不了的……)。这一点体现在文档上,于是有时候我在其他发行版下遇到问题,都会想到直接去翻Gentoo的wiki。

用Gentoo时遇到的最大问题是Xorg偶尔假死,不明真相。屡次重新编译,翻遍各种文档,依然不能完全解决问题。

在升级过一次gcc-lib后,系统被破坏,某些程序开始无法正常运行。试图从stage3恢复系统,结果发现要恢复一个损坏的肮脏系统比重装一个干净的系统麻烦得多。

重装,又需要花费极大的时间代价,因为一切都得用新版本的gcc重新编译一遍。系统是用来干活的,不能整天为了编译一个不一定稳定还搞不好以后哪次更新又会被破坏掉的系统而折腾。于是索性放弃。

无论如何,使用Gentoo的经历让人受益良多。任何一个想用Linux但是又指望别人手把手教他的新手都应该去自行装一遍Gentoo,才能真正领会RTFM和STFW的真谛。

而且在折腾过Gentoo之后会发现,原来其他所有的发行版都是如此地user-friendly……


正在折腾的发行版

Arch Linux

多年之前,我就曾经试图在旧的HP笔记本上安装Arch,结果却遇到了诡异的kernel freeze。这使得我对它的稳定性产生了极坏的印象。

放弃Gentoo之后,我第一个想到的就是Arch。原因其一,机器已经不是当年的HP笔记本了,内核也不知升级了多少版本,我的运气应该不会好到再次碰上kernel freeze的地步;其二,反正之前用了那么久的Chakra,对pacman的包管理方式还算熟悉。

起初,Arch看起来就像是“不用浪费时间编译的Gentoo”,安装过程异常简单。重新配置了类似以前的Openbox环境,也没有遇到过任何问题。一切看起来很好。

Arch上的Openbox并没有用很久,因为我发现了GNOME 3。

起初我并不喜欢GNOME 3,一半是因为网上铺天盖地的批评(比如无视桌面用户体验什么的),另一半是因为缺少任务栏和启动菜单的GNOME Shell确实让我心理上无法接受。然而,当我发现tint2可以与GNOME Shell神奇般地协同工作之后,我的看法改变了。

GNOME很好地体现了简约主义的原则,没有多余的东西(除了没有任务栏这一点确实很让人不爽之外),可以设置的地方也相当有限。相比之下,你可以用KDE定制出一套非常复杂和华丽的界面,高仿上网本,再加上各种分页,面板,花里胡哨的小插件……

其实不管是重量级的桌面环境还是轻量级的WM,最重要的是切换和拖动窗口的快捷程度和视觉效果。这是能直接影响到工作效率的因素。别的,对我来说都是浮云。

Arch从去年年底用到现在,其间经历过若干次系统升级产生的问题(并且导致了我的3次重装系统):

  • 2012年2月4日的linux 3.2.3-1更新(不记得是不是内核的问题了……),导致启动时提示INFO: rcu_preempt detected stalls on CPUs/tasks,然后系统freeze。

2月4日正巧是在布鲁塞尔参加FOSDEM的第一天。会场有无线网络,随手升级了一下系统(无聊的时候pacman -Syu习惯成自然了……),于是就悲剧了。跑到会场外面的“hacker room”重装系统,异常欢乐。

  • 2012年4月的consolekit 0.4.6-1更新(正好是在Google Code Jam资格赛前一天),导致无法进入GNOME。

虽然很快这个bug就被修复并且放出了新的包,但是我重新安装之后,奇葩地依然进不了GNOME,就连GNOME删掉重装都不行。急于准备比赛,不找原因了,直接重装全系统。

这次重装过程中还出了点有惊有险的意外,嗯,写USB镜像的时候移动硬盘分区表被Image Writer破坏了……

这是一个上游库导致的问题,与Arch本身无关。我的解决方法是git二分找出了产生问题的commit,手动滚回去。此后用的一直都是自己构建的包。

这是上游kernel的问题,与Arch无关。我没有像上次找到PulseAudio的问题一样成功git bisect,原因之一是Linux的代码库实在是过于庞大,从一个发布版本到下一个发布版本之间n多commit;原因之二是每次测试一旦失败则意味着要强制关机(好像kexec切换内核不能……),对机器伤害太大(这种具体机器环境相关的测试又不能在虚拟机下进行)。

我的解决方案是降级到3.3.7的内核,从此直接忽略linux的更新。

  • 2012年7月12日,为了准备ICFP需要安装VirtualBox,这个时候内核版本滞后带来的问题显示出来了。

virtualbox-modules是与linux内核模块直接相关的,因此依赖于特定的内核版本。此时linux次版本号已经进入了3.4阶段,故virtualbox-modules的依赖是linux>=3.4和linux<3.5。

如此一来,virtualbox就无法在我当前的系统(linux 3.3)上安装。而Arch Linux的官方库又不保留过期的软件包,因此唯一的解决方法是去Arch Rollback Machine上找旧版本的包,或者自己从PKGBUILD手动构建。

  • 2012年7月14日,glib 2.16.0-2升级,系统中原来/lib目录的内容全部转移到/usr/lib/lib代之以指向/usr/lib的符号链接。

官方提供的升级方案是:

# pacman -Syu --ignore glibc
# pacman -Su

如果仍然出现冲突错误,说明/lib中仍然有属于其他包(glibc之外的包)的文件,需要重新构建这些包把它们所使用的位置改到/usr/lib。不能使用--force选项强行升级,否则会破坏整个系统。

没错,我当前的系统上是有这么一个包使用了/lib。这就是linux 3.3.7

最新的3.4.5版内核确实是使用了/usr/lib来取代/lib作为内核模块的位置,所以毫无疑问可以和新的glibc一同正常工作。我理应把linux 3.3.7用类似的编译选项重新构建一遍。但是我当时正处于ICFP比赛当中,不可能有空去折腾这些。于是,我直接了忽略glibc这个包的更新。而且,我实在是看不出Arch开发团队把/lib迁移到/usr/lib有什么实质的意义。

然后问题就来了:你希望保持某些版本的包不再更新因为它们相对稳定,但Arch却总是假设你使用的所有包永远都处于最新状态。也就是说,Arch的哲学是每个人都理应处于最前沿的bleeding edge,不接受旧版本包的bug报告、甚至不提供旧版本包的下载都是这种Arch哲学的体现。一个包做出了某种更新,所有依赖它的包都必须立即重新构建,如果你压住了一个非常底层的包(比如,有很多其他的包依赖于它)不进行更新,那么,事实上你就会越来越脱离Arch的开发主线,以后再进行任何更新都可能导致意料之外的问题。

glibc就属于这种典型的情况。你永远无法计算Linux上面有多少软件包是依赖于glibc的。

在忽略了glibc 2.16.0-2的更新后不久,binutils也相应地升级了。仅仅给出了一条“启动时将从/usr/lib/modules而非/lib/modules读取”的提示,之后便升级成功。按理说,这个升级是完全依赖于glib 2.16.0-2这一升级的,但是不知为何,并没有写入相应的依赖关系。果然,在重启系统时出错,无法读取内核模块。通过创建/usr/lib/modules这个符号链接指向/lib/modules,暂时解决了问题。

更新的binutils依赖于glibc 2.16.0-2的升级这一事实被我意识到了,然而,肯定还有其他的更新的包依赖于这个升级,我不可能全部意识到。事实上,问题很快就随之出现:在编译某些以前可以正常编译的程序时,蹦出来一堆GLIBC库相关的错误,于是我意识到,我需要把我的glibc升级到2.16.0-2了。

为了升级glibc到2.16.0-2,我必须把linux的内核模块从/lib/modules迁移到/usr/lib/modules,由于>=3.3.8的内核在我的笔记本上都存在不能关机的问题,因此,我只能重新自行构建我的旧版本linux 3.3.7。但是,为了构建linux,我又必须要依赖于glibc,而事到如今凡是牵涉到glibc的程序,都无法成功编译。这样一来就形成了类似于Catch-22的一种状况。

我试图退回glibc和所有依赖它的组件到过去的版本,结果发现有些依赖关系是很难逆转的。比如,gcc-libs依赖于glibc>=2.16,然后还有无数软件包依赖于gcc-libs(想都不用想也知道)。glibc本身也依赖于特定的linux-api-headers版本,比如,glibc 2.16.0依赖于linux-api-headers>=3.4。因此,几乎很难对glibc这个东西进行降级。

退后不行,于是我只能尝试前进,希望新版本的内核解决了不能关机的问题。升级linux到官方的最新版本3.4.5-1(构建时已经使用了/usr/lib/modules以代替/lib/modules),glibc于是也就这样成功升级到了2.16.0-2。悲剧的是然后我发现,3.4.5的内核依然存在着不能关机的严重问题。不知道是不是之前升级的kmod 9-2同样依赖于glibc 2.16.0-2的更新,最后我更加悲剧地发现,试图重新退回安装linux 3.3.7,在生成内核模块的时候会报错。也就是说,事实上自从我忽略glibc 2.16.0-2以来的一系列其它没有得到系统警告的更新,不仅使旧版本glibc 2.16.0-1库有关的编译无法正常进行,也破坏了旧版本3.3.7内核模块的持续性。

重启,内核模块错误,不能进入系统。于是,不得不进行第三次重装。

经历过这次glibc的/lib位置升级、相应一系列包的升级与旧版本linux不兼容所导致的灾难,我终于意识到了Arch这种滚动升级方式带来的稳定性缺陷,并且面临着两种选择:一、迁移到Debian或者Fedora的稳定版本,虽然可能每年发布新版本需要重装一次,但是比起玩Arch半年就因为升级出故障重装三次要好的多;二、借助Arch Rollback Machine,安装一个处于linux 3.3.7版本时间点的系统,软件包不是最新,但是也绝对算不上过时,至少可以先稳定地用上一阵子,不用再受到每天pacman -Syu一次的诱惑,也不会在手头正忙得要死的时候因为无意升级了一下系统结果把Arch搞崩溃,不得不停下要做的事去修复(甚至重装)系统。

最终,我选择了后一种。嗯。但是,事情还远没有结束。


未来可能会折腾的发行版

Fedora

实际上Fedora 16曾经在我的硬盘里呆过一段时间。不得不说,在我Arch内核崩溃无法启动的时候,作为硬盘上的备用系统它发挥过很大的作用。

不过比较糟糕的是我装的是32位的Fedora,所以无法chroot进64位的Arch……结论是以后装双Linux要么都用32位,要么都用64位。

Fedora的两点好处,一是同样具有强大的技术社群(如今Linux的很大一部分都是RedHat那帮人的贡献),可以和Gentoo、Arch和Debian相媲美;二是软件包更新很快(和Debian相比而言)。从我个人的角度来说,Fedora预设的桌面环境是GNOME 3,这也是一个额外的好处。(预设KDE的发行版我应该不会再产生兴趣了……)

上一次Arch玩坏之后我曾经试图转向Fedora 17,图形化安装界面很舒服,结果安装过程进行中突然提示我“文件系统不能正确创建,需要在其他系统下进行修复”什么的,然后就自动帮我重启了(而且是在我把原来的硬盘分区连同/boot都清干净了之后……)汗。对我来说这种“用户友好”可能做得有点过头了。

结果还是没发现文件系统有什么问题,之后在同一个分区上装Arch好好的。暂时不会再考虑Fedora了。

Debian

准备在下一次Arch崩溃之后换到Debian。(Debian也许是所有厌倦了无止尽折腾的用户的最终归宿?)

唯一一次接触Debian是前一阵子参加ICFP的比赛,官方提供的用于测试程序的6.0 squeeze虚拟机镜像。(结果被很多参赛队伍抱怨Debian稳定版提供的包太老旧了……于是后来就改成了允许使用wheezy的软件库)