爱好 debian 的 Linuxer  通常很看不上基于 rpm 的系统,和 debian 的 apt 系统比起来,RedHat 的 up2date 简直就是一个鸡肋,升级要账号不说,网络稍微有点毛病,就彻底卡死了。还不能建立个人镜像,每次都得从米国 redhat 的老家下,非常之慢。最重要的,up2date 并不支持 apt-get dist-upgrade 这样跨越 dist 的升级,装了 RH 7.3 这样的老系统,就只能一条路走到死,升级必须得用光盘才行,这对于丢在机房的机器来说简直是不能接受的。

不过事情并没有大家想像的那么严重,实际上 RPM 系列系统(特别的,指 RedHat 系列的 RedHat, Fedora Core, RedHat ES/AS 等系统,像 Suse 虽然也是 RPM based,但是 Suse 提供了很拽的 YAST 工具可以用)也可以在不停机的条件下面在线升级成更新的 distribution。当然,需要是师出同门的,比如 RedHat 升级成 Fedora Core,  或者 RedHat ES 升级到 CentOS ,等等。

这个操作的原理说起来很简单,就是手动用新系统的 rpm -U 升级上去,这个事情可真是一个技术活,需要胆大心细,大部分时候,把新发行版的 rpm 堆在一起,然后 rpm -Fvh 可以搞定大部分,但是发行版升级时候,发行商经常会用一些名字不同的包 obsolete 掉原来的某些包,这种情况 rpm -Fvh 就不顶事情了,怎么办呢?对手工操作来说,最简单的方式其实是连蒙带猜,例如 RH9 升  FC2 时候,会发现 redhat-config-mouse 没有,在 FC2 rpm 里面找一下,能发现有 system-config-mouse,那么先 rpm -U 上去 system-config-mouse 就可以了。总的来说,手动升级具有最大的灵活性,但是也是一个非常体力的活,不是今天我们要讨论的主题。。。

感谢天,感谢地,感谢MJ,RPM 系统上面有一些软件包管理程序,可以比较简单的解决这个问题,这里面比较常见的就是 yum 和 apt-get(rpm),这些包管理程序可以分析 RPM 包里面的依赖关系和替代关系,从而在升级时候自动找到正确的 rpm 来升级系统。下面我们分 yum 和 apt-get 两种情况来介绍如何用这两种包管理系统在线升级你的 Linux 系统到最新发行版本。

升级前的准备工作

首先,在升级之前,有一些事情是你需要事先了解和知道的:

1:  用包管理系统升级并不代表你就上了保险,实际上,还是很有可能导致系统崩溃不得不用光盘修复或者重装,这取决于你使用 Linux 系统的习惯(比如是不是在系统里面装了太多杂七杂八的软件,升级以后这些东西很可能跑不了了),以及遇到意外情况的处理经验,当然,最重要的是人品,RP 非常好的话,怎么着都装不死的。所以,尽可能的备份你系统上的所有有价值东西。

2:  尽量不要跳级升系统,如果有个 RedHat 7.3 系统要升级到 FC4,最好先升级到 9 ,然后 FC1,然后 FC 2, 然后 FC3 ,最后 FC4,这是因为跨越版本太远的话,rpm 包里面的依赖关系和替代关系可能断开了。导致找不到对应的包,这种情况下包管理程序会不升级这个包甚至卸掉,就出事了。实在没有办法的话,那就赌一下人品好了。但是请作好去机房的心理准备。

3:  升级之前最好先清理系统,使它尽可能接近一个原装系统,尽可能多的清理掉第三方 rpm 软件,需要的话在升级完之后再装回来就好了。否则容易造成一些不能解决的依赖关系。

4:  kernel 升级一向是比较烦人的事情,用包管理器升级最好用官方的 RPM kernel , 最不容易出事,自己 build kernel 虽然很有快感,但是等需要某些特殊功能的时候,说不定就要重编了, stock kernel 虽然性能差一点,但是不是特别繁忙的服务器基本体现不出来的。另外自己 build kernel 在升级到 FC3 的时候,会被搞一下。这个我们后面还会讲到。在升级到 FC3 之前,请先用 tar 备份一下你的 /dev 目录!

5:  为了使用包管理器,你需要有一个目标发行版的 package repository,对于 yum 来说,官方站就是一个 repository, apt-get 的需要人手工建立,不过网上也有不少地方已经替你建好了,在 apt4rpm 的网页上面我记得有链接。清华校内的可以直接用 ftp.tsinghua.edu.cn 上面的镜像。

好了,该说的都说了,下面就让我们开始在线升级系统吧。哦,对了,在升级之前,请多开几个 root 的 shell 窗口挂着,以防中间出现某些问题,导致 ssh 不能连接,或者无法 su 等等。

用 yum  升级

yum 是 FC 系列里面默认的包管理器,通常用来做 FC 系列之间的升级,从 RH7.3/9 升级一般考虑用 apt-get,因为有现成的 repo,而且 apt-get 的速度更快一些。yum 的配置并不是本文讨论的范围,不过我在这里还是要友情提示一下教育网和其他连接受限用户,配置 yum 的 repos 时候,请删除掉所有不用的 repo, 特别是位于国外等连不上地方的,另外 mirrorurl 项一般取消掉。这是因为 yum 这个东西非常之弱智,启动时候会试图连接所有的 repo 以及 mirror ,连不上就像死了一样,半天不动。

升级的第一步是先升级现有系统到最新版本,这个用 yum 可以很简单的做到,配置正确的情况下面直接 yum update 就可以了。

接下来要使 yum 知道用新发行版的包来升级,这个怎么做呢?理论上讲直接手动修改 yum  的 repo  目录,让他指向新发行版就可以了,但是这样显得很衰,如果你用的 repo server 像 ftp.tsinghua.edu.cn 一样保持原目录结构镜像了所有文件的话,那么不用去修改配置文件,直接下载新发行版里面的 fedora-release  这个 rpm ,rpm -U 升级上去即可,因为 yum 的默认配置里面,repo 目录用变量指向不同的路径,而决定这些变量值的,就是这个 xxxxx-release 这个 rpm。 如果你没有这么全的 repo, 那就只能手动修改了。。

repo 目录修改以后,后面升级的事情,就像一次普通升级一样简单,直接 yum update 搞定一切。如果 yum 抱怨有些依赖关系被破坏的话,仔细看看,多半是你以前安装的第三方软件包有毛病,记住它们的名字,卸载掉,等一切搞定再装。

注意:在 yum 升级决定升级的时侯,会提示你一些信息,说哪些包要升级,哪些包会增加,哪些包会卸载,还有哪些包会不升级,观察一下卸载包里面,有没有对系统非常重要的包,比如 kernel ,mkinitrd ,grub 之类,有的时侯 yum 可能会判断失误,错误删除掉包,这都需要你人工帮助他纠正一下,防止真的造成遗憾。

用 apt-get 升级

用 apt-get 升级的过程和 yum 升级基本大同小异,过程也是分为修改 repo , 执行 apt-get 两步。

apt4rpm 的 sources.list 文件默认配置好像没有环境变量,至少我这里用的是这样的,因此你很可能需要手动改里面的 source url 成新的地址。

和 yum 不同,apt-get 有专门的一个命令用来升级发行版,是 apt-get dist-upgrade ,如果直接运行 apt-get upgrade 的话,会有不少系统关键包不会被升级,造成很多奇怪的现象比如 gcc 不能用之类,因此这里千万要用 apt-get dist-upgrade 来升级。

apt-get 比起 yum 来要挑剔很多,对系统包的依赖关系要求非常严格,用 apt-get 升级的时侯,更要仔细观察,他将会删除哪些包,以及哪些包将不会升级,用笔记录下来,将来发现升级后系统不正常的时侯,首先检查这些包是不是升级过程中出了问题。

此外,因为 apt 是一个 native 的程序,依赖于特定版本的 libstdc++ ,所以有时侯升级发行版他甚至会因为 libstdc++ 升级而把自己卸载掉。这点要注意一下,可能需要手动下载新版本的再装一遍。

升级完成后的检查列表

升级完成以后,不要急于重新启动系统,如果着急重启,很可能你就得跑机房了,程序没有人那么聪明,他做的事情很多时侯不够干净,因此人替它擦屁屁是很必要的。

  • 首先检查系统常用命令是否正常,ls, rpm, ssh 三样是否工作正常, su 是否可以成功 su ,一般来说如果不行的话,你的 RP 已经算比较差的了,比较难以修复。。为了尽点人事,检查 glibc , openssl , db3/4 , rpm, libstdc++ 这几个包是不是正确升级了,没有的话,下载下来强行 rpm -U –force –nodeps 装一下。
  • 接下来检查一下远程能否正常登录 ssh, 以及 ssh 是否在启动项里面,如果 ssh 登录总说密码错误,那么把 openssh , openssl  重装以后 service sshd restart 一下,基本就能解决了,可能还需要重装 pam 这个 rpm。
  • 然后需要检查的是 kernel 启动部分,这部分情况比较复杂,首先先保证你常用的 boot loader 确实在起作用,如果你习惯 lilo ,就运行一下 lilo ,如果你习惯用 grub ,就 grub-install <第一个硬盘设备名> 一下,保证这个 boot loader 确实在起作用,然后检查 boot loader 的配置文件里面,你打算用的内核是不是在正确的启动项上面,以及内核文件是不是真的存在在磁盘上面,等等。
  • 特别的,如果你是从 FC3 以下版本升级到 FC3 ,那么千万要注意,FC3 里面开始使用了 udev,udev 的工作原理是,在系统启动时侯,会启动一个叫做 udevd 的进程,它根据你系统的硬件情况,在 /dev 下面创建设备文件节点,但是系统启动时侯需要 /dev 下面的 console 和 log 这两个设备,更变态的是,udev 这个包 obsolete 了原来的 dev 这个包,在卸载 dev 这个包的时侯,原来你系统 /dev 下面那一堆堆的设备文件就都删光光了。如果你自己编译的 kernel 没有使用 initrd, 系统启动时侯就会卡住,stock kernel 里面是用 initrd 来解决这个问题的。

不打算使用 initrd 的,还记得在准备过程里面,用 tar 备份的那个 /dev 目录吗?对,就是用它恢复 /dev 下面的东西就可以了,不过 /dev/log 这个 sock 文件没法用 tar 备份,你需要手动 mksock /dev/log 。

  • 在升级过程中,如果有些你觉得对系统非常重要的包被 yum 之类给卸载了,手动把他们拣出来装上。

这几项检查做完了,基本就可以重启了,当然,最好给佛爷上把香,让他保佑你不要死。。

前面说了这许多,看起来在线升级好像是个非常危险的事情一样,其实情况不见得有这么复杂,我升级了几十台机器,基本都没有见到出问题的。但是,在线升级毕竟是一个对系统影响很大的事情,如果对系统没有一定的了解,不出问题还好,出了问题不会处理,基本就算死掉了。如果你非常害怕这个的话,还是不要升级好了,或者用 debian/FreeBSD 等很容易升级的 OS。 apt-get dist-upgrade 和 make world 比本文要简单多了。。