2007年2月9日星期五

Windows 到 Linux 之旅: Part 9

Windows 到 Linux 之旅:

第 9 部分. 安装软件

安装 Linux 时首先注意到的事情之一,就是 Linux 发行版本中有如此多可用的包。大多数发行版本都附带了 Linux 操作系统、安装工具和管理工具。它们还包括 Internet 工具、开发工具、办公工具、游戏,以及一些您不曾听说过的程序。Linux 发行版本附带 数千个可用包的情况并不鲜见。如果您没有选择“完整安装”,则只会安装这些包的一个子集。

现在您可能想知道“如何删除不想要的包?如何安装遗漏了的包?是否能够使用不是该发行版本附带的软件?”

RPM

在安装 Linux 时,您或许会注意到关于正在安装的 RPM 的许多信息。 RPM 代表 Redhat Package Manager(Redhat 包管理器),这是 Redhat 的贡献,现在已成为管理 Redhat 和 UnitedLinux 以及其他许多发行版本上的软件的标准。

RPM 本质上就是一个包,包含可以立即在特定机器体系结构上安装和运行的 Linux 软件。例如,在“ 第 3 部分. Webmin 简介”中,我们通过一个 RPM 安装了 Webmin 包。最初加载到发行版本中的所有软件都是通过一个 RPM 来安装的。

RPM 剖析

RPM 是文件包。它包括的 .spec 文件提供了关于包及其功能和依赖关系(即在该包能够运行之前必须安装其他哪些包)的信息。.spec 还包含包中的文件清单,指定这些文件必须加载到系统中的何处,以及它们的初始权限如何。RPM 还包含安装前脚本,这是由包开发人员编写的。RPM 其次还包含已编译的二进制文件。最后,RPM 包含了安装后脚本。

RPM 结构

.spec安装前脚本二进制文件二进制文件...二进制文件安装后脚本

在安装 RPM 时,系统首先检查该包的依赖关系是否得到满足。如果不满足, 安装过程就会终止,除非您指定了迫使安装无论如何都要继续的选项。

如果一切顺利,安装前脚本就会运行。这个脚本可以做任何事情。它通常创建用户和目录。然而,它可以做许多类型的动态配置,甚至以自定义的方式编译运行系统的源代码。

了解 RPM 来自何处

RPM 在安装时将文件复制到您的系统上,并执行脚本。由于 RPM 是以 root 身份运行的,因此所有这些功能都以 root 身份执行。因而在将某个 RPM 安装到系统之前,知道它的由来是很重要的。就像许多 Windows 软件一样,恶意的代码可以像包含在其他包中一样容易地包含在 RPM 中。来自厂商的 RPM 一般都是安全的,但是要对从未知来源随机下载和安装的内容保持警惕。

如果安装前脚本成功完成,二进制文件将依照清单被复制到系统上。在复制完所有的文件和设置了它们的权限之后,安装后脚本就会运行。同样,这个脚本几乎能够做任何事情。

一旦完成所有这些步骤,关于包的信息就被添加到 RPM 数据库,安装过程就完成了。使用这种简单的机制,您能够执行通过更完善的商业安装程序所能执行的所有功能。

RPM 数据库

RPM 的优雅之处是 RPM 数据库。这个数据库通常位于 /var/lib/rpm 目录,它包含关于系统上已安装的每个 RPM 的信息。这个数据库知道包之间的依赖关系,当删除某个包将导致其他包无法工作时,它将发出警告。这个数据库知道最初随某个包安装的每个文件以及这些文件在 系统上的最初状态。它还知道每个包的文档和配置文件的位置。这听起来好像是大量的信息,事实上确实如此。但它并不是过多而庞大的。在一个包含 1,066 个包、由 203,272 个文件组成的系统上,数据库文件仅有 45 MB!在加载和卸载包时,RPM 使用这个数据库来检查依赖关系。用户还可以在这个数据库中查询关于包的信息。






使用 RPM

配合 RPM 包使用的程序被相应地命名为 rpmrpm 以多种不同的模式运行,不过最常见的任务是安装、升级、查询、验证和删除。

rpm -i (装)

在第一次安装某个包时,您要使用 -i 或安装模式。只需将 rpm 指向某个二进制包并执行它, rpm 就会把该包安装到您的系统上。安装过程一般只需几秒钟。我经常会在安装包时使用 -v (详细)开关来提供关于该过程的更多信息,以及使用 -h (哈希线)开关来通过输出在控制台上的哈希(#)符号提供安装进度更新。下面是安装某个包的例子:



清单 1. 安装 MyPackage
$ rpm -ivh MyPackage-1.0.0.i386.rpm
Preparing... ########################################### [100%]
1:MyPackage ########################################### [100%]

就是这个样子!MyPackage 现在已经安装完成,可供使用了。

rpm 必须以 root 身份运行

必须以 root 身份执行 rpm 安装和删除,因为需要访问文件系统和 rpm 数据库。

rpm -e (删除)

要删除已安装的包,可使用 -e 开关。 rpm 将使用数据库来删除该包的所有文件。如果有已安装的其他包依赖正在删除的包, rpm 将会异常退出。您必须使用 nodeps 开关来执行强制删除( nodeps 还可以用于强制安装)。在使用这个开关来强制安装或删除时,务必 非常 小心。删除其他包所依赖的包,可能会导致灾难性的结果。下面这个命令删除我们在上面安装的包:

$ rpm -e MyPackage

注意,包的删除并不一定需要它的完整名称(包括版本号)。安装时需要完整名称,因为我们是在引用一个文件名称。已安装的包仅通过它们的名称来引用。包的名称是版本号之前的所有内容。

rpm -V(验证)

验证开关非常有用。它将包文件的当前状态与它们在安装时的原始状态作比较。两种状态之间的区别将用一个代码来显示:

文件验证结果

S 文件大小不一致
M 模式不一致(包括权限和文件类型)
5 MD5 校验和不一致
D 设备主要/次要编号不匹配
L readLink(2) 路径不匹配
U 用户拥有关系不一致
G 群组拥有关系不一致
T mTime 不一致

如果您对某个包运行 rpm -V ,并且发现某个可执行文件的大小发生了变化,那可能就是安全漏洞的征兆。

rpm -U(升级)

一旦某个包已经安装,尝试安装具有相同名称的包将产生一条消息,指出该包已经安装。 如果想要将某个包升级到更新的版本,可使用 -U 开关来升级。升级还具有另一个影响。当对多个包名称运行升级时,它将设法按依赖关系的顺序放置包。换句话说,必需的包将首先安装。不管某个包是否已经安装,都可以对它使用升级开关,许多人使用它而不是使用 -i 开关来执行安装和升级。下面是使用升级开关来加载多个 rpm 包的例子:



清单 2. 交互式升级
$ rpm -Uvh My*.rpm
Preparing... ########################################### [100%]
1:bMyPackageDep ########################################### [ 50%]
1:aMyPackageNew ########################################### [100%]

在上面的例子中,bMyPackageDep 是 aMyPackageNew 的前提条件,因此尽管文件名称以相反的顺序排列, rpm 也会对它们正确排序。

rpm -q(查询)

可以从 rpm 数据库中查询多种有用的信息。对 rpm 数据库拥有读访问权限的任何用户都能够运行查询。默认情况下,全部用户都拥有读访问权限。要运行一个查询,可使用 -q 开关带上要查询的包的名称。这样将返回该包的版本。

$ rpm -q MyPackage


MyPackage-1.0.0

包的名称必须精确匹配,不允许使用通配符。然而,如果记不住包的完整名称,您可以使用 grep 工具来帮助找到它。可以使用 -qa 开关来查询所有已安装的包,并用 grep 来管道输出您能记住的信息。例如:

grep 之乐

grep 是一个具有广泛用途的文本搜索工具。默认情况下, grep 将搜索文件以显示您指定的行。在这里的例子中,它搜索单词“IBM”。 grep 是脚本编写和控制台工作方面的一个强大工具。

$ rpm -qa | grep IBM


IBMWSAppDev-Product-5.0-0


IBMWSSiteDevExp-Core-5.0-0


IBMWSSiteDev-Core-5.0-0


IBMWSTools-WAS-BASE-V5-5.0-0


IBMJava118-SDK-1.1.8-5.0


IBMWSWB-samples-5.0-0


IBMWSWB-5.0-0


IBMWSAppDev-Core-5.0-0


IBMWSAppDev-5.0-0


IBMWSTools-5.0-0

除了版本号外, rpm -q 还可以提供关于包的其他有用信息。下面就是这样一些例子:

使用 rpm 查询获取信息

rpm -q changelog 显示包的开发变更历史记录
rpm -qc 显示包的配置文件
rpm -qd 显示包的文档文件
rpm -qi 显示包描述
rpm -ql 显示包的文件的列表
rpm -qR 显示包的依赖关系

还有另一个有趣的查询命令,它针对文件而不是针对包运行。

rpm -q whatprovides 

上面这个命令将识别与给定的 filename(文件名)相关联的包。filename 必须包括文件的绝对路径,因为信息就是以这种方式存储在 rpm 数据库中的。






RPM 前端

从控制台操作 rpm 很容易,但有时使用图形用户界面会更方便。在典型的 Linux 风格中,有一些前端程序为 rpm 程序提供界面。每种发行版本都有一个前端,但是它们各不相同。请参考您的发行版本文挡,以了解关于所提供的包管理工具的信息。







Webmin 软件包

Webmin 也为处理 RPM 包提供了一个基于 Web 的简单前端。


图 1. Webmin RPM 界面
图 1. Webmin RPM 界面

软件可以从这个界面容易地安装、删除和查询。还可以直接从 URL 站点安装软件。如果安装了诸如 apt 或 Redhat Network 之类的 rpm 增强工具,Webmin 将识别它们并为它们提供一个界面。






源代码

由于 Linux 是开放源代码的操作系统,它附带了编译软件所需的所有开发工具。虽然您使用的大多数包将以二进制 RPM 的形式提供,但是您并不仅限于使用那些包。如果愿意,您可以为您的系统下载原始源代码,并以自定义的方式进行编译。

应该对在生产系统上编译源代码保持谨慎,因为这样可能导致问题,或者不再支持系统上正在使用的商业软件(比如 IBM DB2)。然而,熟悉从源代码编译软件的过程将使您能够对软件应用补丁,以及使用从其他环境移植过来的包。一旦成功地编译代码,创建您自己的 RPM 也是可以做到的!







Corewars 源代码演示

为演示从源代码编译软件有多简单,我们将编译一个名为 Corewars 的模拟游戏(请参阅 参考资料)。下面是来自他们 Web 站点的关于 Corewars 的说明:“Corewars 是一款模拟游戏,其中许多武士在虚拟的计算机中奔跑时竭力相互攻击对方。可以采用两种类似汇编程序的语言中的一种来编写武士程序,这两种语言分别叫做 Corewars 和 Redcode。Corewars 是默认语言,更易于学习和理解。Redcode 提供更高级和更强大的指令,但是需要更多的时间来学习。”

编译源代码的第一步是从 Web 站点下载源代码包:

在代码下载完成之后,需要展开这个包。

tar -xvzf corewars-0.9.13.tar.gz

文件将展开到当前目录。标准的做法是将源代码包含在一个与产品名称匹配的目录中。在此例中,源代码位于一个名为 corewars-0.9.13 的目录。

首先进入该目录,找到源代码和一些文档、配置脚本和 README 文件。大多数源代码包都带有一个名为 INSTALL 和一个名为 README 的文件。您应该在编译软件之前首先阅读这些材料。它们在问题出现之前识别问题,并为您建议正确的编译和安装步骤,这样通常可以让您少走许多弯路。我在编译源代码时遇到的大多数问题都是因为我没有遵循那些指导。

通常执行的下一步是运行 configure 脚本。 configure 是 Autoconf 包的一部分,包括在 Linux 发行版本的开发工具中。这里引用一段 Autoconf 的包描述:“GNU 的 Autoconf 是一个用于配置源代码和 Makefile 的工具。通过使用 Autoconf,程序员能够创建可移植和可配置的包,因为建立包的人可以指定各种配置选项。”

configure 脚本在系统上运行一系列测试,以确定为您的发行版本和系统体系结构编译包的最佳方式。然后它为您的系统创建一个定制的 Makefile。如果在您的系统上编译时遇到问题, configure 将会告诉您。 configure 通常允许您自定义将要在编译中包括的特性,或允许您提供关于库或者其他必需文件的位置参数,以便能够成功地编译包。下面我们将不带参数执行 configure

./configure

在系统上多执行几次测试,最终就会编译成功。下面使用如下命令来生成程序:

make

如果编译有错误,就需要确定问题并修复它们。这可能是一件繁琐的任务,也许需要关于环境和程序设计的大量一般知识。如果一切顺利,我们一般会使用以下命令来安装软件:

make install

文件将被复制到系统中的正确位置,文件权限会被更新,配置文件将被复制,文档也会被添加到手册页。

现在通过执行该程序来测试我们的劳动成果。它是一个图形化的程序,因此要在启动它前运行 X 系统。上面执行的 make install 命令应该已将程序放到了可执行文件路径中。

corewars

作为对我们的奖赏,一个图形化的屏幕应该会出现。



图 2. 大功告成!
图 2. Corewars 游戏

corewars 规则的主题超出了本文的讨论范围,不过您会在手册页( man corewars )中找到关于这款有趣的模拟游戏的文档。

corewars 的编译是一个典型的场景。可能会有其他许多种变化形式,包括在 configure 脚本上使用开关来调整要编译到程序中的特性,以及从 Makefile 使用不同的命令来调整编译方式,等等。

由于这个程序不是使用 rpm 来安装的,因此 rpm 数据库中没有相应的条目。如果某个程序在安装后没有按预期运行,大多数 Makefile 都包括了一个卸载参数来删除软件:

make uninstall

务必牢记,使用原始源代码不会在 RPM 数据库中添加任何内容。以这种方式安装的软件是非托管的(unmanaged),因此应该小心进行。

源代码 RPM

当 RPM 被创建时,还有一个称作源代码 RPM 的产物。这是一个与源代码组合在一起的 SPEC 文件,设计它的目的是为了在一个或多个体系结构上生成程序。这对源代码和二进制这两个世界来说是最佳的!对于源代码 RPM,您可以在系统上定制编译软件,但是完成的产品将是一个可安装的 RPM,而不是原始的二进制。以预编译 RPM 的形式可用的大多数包还以 SRPM 的形式可用。这也许是在 Linux 中软件跨平台转移的简单途径。当您在一个不同的平台上成功地重新编译时,可考虑与整个开发社区共享完成的 RPM。







也许源代码更适合您

如果您是 Linux 新手,安装软件的方法与您过去习惯使用的方法不同。然而,RPM 安装方法是优雅的,同时提供了您很快就会欣赏的新能力。

您应该熟悉从控制台使用 rpm 的选项,不过对于日常使用,有一些前端界面选项使得 rpm 更易于管理。您的发行版本提供了这样一个界面,也有其他类似的界面可供使用,比如 Webmin 中的那一个界面。

您并不仅限于使用预编译的 rpm,还可以利用 Linux 的开放源代码性质,直接从源代码编译应用程序。对于成熟的项目,编译通常是很容易的。记住,从源代码安装的代码在 rpm 数据库中没有相应的条目。在使用源代码时,可考虑使用源代码 rpm,它组合了已编译源代码的强大能力和 rpm 的可管理性。



参考资料


关于作者

Chris Walden 是位于德克萨斯州奥斯汀的 IBM Developer Relations Technical Consulting(也称为 dragonslayers )的一名电子商务架构师,该公司为 IBM 商业伙伴提供教育、实现和咨询。他致力于 Linux 相关工作,一有机会就向身边的人宣传 Linux 的种种好处。除了完成他的架构师的职责之外,他还精通 Linux 基础设施服务器的各个领域,包括混合平台用户环境下的文件、打印以及其他应用服务等。Chris 有 10 年的计算机行业经验,从现场支持到 Web 应用开发和顾问,各个领域他都曾涉足。您可以通过 cmwalden@us.ibm.com

没有评论: