21.1 开放源码的软件安装与升级简介

如果鸟哥想要在我的 Linux 服务器上面跑网页服务器 (WWW server) 这项服务,那么我应该要做些什么事呢?当然就一定需要“安装网页服务器的软件”啰!如果鸟哥的服务器上面没有这个软件的话,那当然也就无法启用 WWW 的服务啦!所以啦,想要在你的 Linux 上面进行一些有的没的功能,学会“如何安装软件”是很重要的一个课题!

咦!安装软件有什么难的?在 W 牌的操作系统上面安装软件时,不是只要一直给他按 “下一步”就可以安装妥当了吗?话是这样说没错啦,不过,也由于如此,所以在 Windows 系统上面的软件都是一模一样的,也就是说,你“无法修改该软件的原始程序码”,因此, 万一你想要增加或者减少该软件的某些功能时,大概只能求助于当初发行该软件的厂商了!(这就是所谓的商机吗?)

或许你会说:“唉呦!我不过是一般人,不会用到多余的功能,所以不太可能会更动到程序码的部分吧?” 如果你这么想的话,很抱歉~是有问题的!怎么说呢?像目前网络上面的病毒、黑客软件、臭虫程序等等, 都可能对你的主机上面的某些软件造成影响,导致主机的死机或者是其他数据损毁等等的伤害。 如果你可以借由安全信息单位所提供的修订方式进行修改, 那么你将可以很快速的自行修补好该软件的漏洞,而不必一定要等到软件开发商提供修补的程序包哩!要知道,提早补洞是很重要的一件事。

Tips 并不是软件开发商故意要搞出一个有问题的软件,而是某些程序码当初设计时可能没有考虑周全, 或者是程序码与操作系统的权限设置并不相同,所导致的一些漏洞。当然,也有可能是 cracker 通过某些攻击程序测试到程序的不周全所致。 无论如何,只要有网络存在的一天,可以想像的到,程序的漏洞永远补不完!但能补多少就补多少吧!

这样说可以了解 Linux 的优点了吗?没错!因为 Linux 上面的软件几乎都是经过 GPL 的授权,所以每个软件几乎均提供原始程序码, 并且你可以自行修改该程序码,以符合你个人的需求呢!很棒吧!这就是开放源码的优点啰!不过,到底什么是开放源码? 这些程序码是什么咚咚?又 Linux 上面可以执行的相关软件文件与开放源码之间是如何转换的?不同版本的 Linux 之间能不能使用同一个可执行文件?或者是该可执行文件需要由原始程序码的部分重新进行转换? 这些都是需要厘清观念的。下面我们先就原始程序码与可可执行文件

21.1.1 什么是开放源码、编译器与可可执行文件

在讨论程序码是什么之前,我们先来谈论一下什么是可可执行文件?我们说过,在 Linux 系统上面,一个文件能不能被执行看的是有没有可执行的那个权限 (具有 x permission),不过,Linux 系统上真正认识的可可执行文件其实是二进制文件 ( binary program),例如 /usr/bin/passwd, /bin/touch 这些个文件即为二进制程序码。

或许你会说 shell scripts 不是也可以执行吗?其实 shell scripts 只是利用 shell (例如 bash) 这支程序的功能进行一些判断式,而最终执行的除了 bash 提供的功能外,仍是调用一些已经编译好的二进制程序来执行的呢! 当然啦, bash 本身也是一支二进制程序啊!那么我怎么知道一个文件是否为 binary 呢?还记得我们在 第六章、Linux 文件与目录管理 里面提到的 file 这个指令的功能吗?对啦!用他就是了!我们现在来测试一下:

# 先以系统的文件测试看看:
[[email protected] ~]# file /bin/bash
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked 
  (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x7e60e35005254...stripped
# 如果是系统提供的 /etc/init.d/network 呢?
[[email protected] ~]# file /etc/init.d/network
/etc/init.d/network: Bourne-Again shell script, ASCII text executable

看到了吧!如果是 binary 而且是可以执行的时候,他就会显示可执行文件类别 (ELF 64-bit LSB executable), 同时会说明是否使用动态函数库 (shared libs),而如果是一般的 script ,那他就会显示出 text executables 之类的字样!

Tips 事实上,network 的数据显示出 Bourne-Again ... 那一行,是因为你的 scripts 上面第一行有宣告 #!/bin/bash 的缘故,如果你将 script 的第一行拿掉,那么不管 /etc/init.d/network 的权限为何,他其实显示的是 ASCII 文本文件的信息喔!

既然 Linux 操作系统真正认识的其实是 binary program,那么我们是如何做出这样的一支 binary 的程序呢?首先,我们必须要写程序,用什么东西写程序?就是一般的文书处理器啊!鸟哥都喜欢使用 VIM 来进行程序的撰写,写完的程序就是所谓的原始程序码啰! 这个程序码文件其实就是一般的纯文本文件。 在完成这个源代码文件的编写之后,再来就是要将这个文件“编译”成为操作系统看的懂得 binary program 啰!而要编译自然就需要“编译器”来动作, 经过编译器的编译与链接之后,就会产生一支可以执行的 binary program 啰。

举个例子来说,在 Linux 上面最标准的程序语言为 C ,所以我使用 C 的语法进行原始程序码的书写,写完之后,以 Linux 上标准的 C 语言编译器 gcc 这支程序来编译,就可以制作一支可以执行的 binary program 啰。整个的流程有点像这样:

利用 gcc 编译器进行程序的编译流程示意图图21.1.1、利用 gcc 编译器进行程序的编译流程示意图

事实上,在编译的过程当中还会产生所谓的目标文件 (Object file),这些文件是以 *.o 的扩展名样式存在的!至于 C 语言的源代码文件通常以 * .c 作为扩展名。此外,有的时候,我们会在程序当中“引用、调用” 其他的外部副程序,或者是利用其他软件提供的“函数功能”,这个时候,我们就必须要在编译的过程当中, 将该函数库给他加进去,如此一来,编译器就可以将所有的程序码与函数库作一个链接 (Link) 以产生正确的可执行文件啰。

总之,我们可以这么说:

  • 开放源码:就是程序码,写给人类看的程序语言,但机器并不认识,所以无法执行;
  • 编译器:将程序码转译成为机器看的懂得语言,就类似翻译者的角色;
  • 可可执行文件:经过编译器变成二进制程序后,机器看的懂所以可以执行的文件。### 20.1.2 什么是函数库

在前一小节的图21.1.1示意图中,在编译的过程里面有提到函数库这东西。 什么是函数库呢?先举个例子来说:我们的 Linux 系统上通常已经提供一个可以进行身份验证的模块, 就是在 第十三章、Linux 帐号管理与 ACL 权限设置 提到的 PAM 模块。这个 PAM 提供的功能可以让很多的程序在被执行的时候,除了可以验证使用者登陆的信息外, 还可以将身份确认的数据记录在登录文件里面,以方便系统管理员的追踪!

既然有这么好用的功能,那如果我要编写具有身份认证功能的程序时,直接引用该 PAM 的功能就好啦,如此一来,我就不需要重新设计认证机制啰!也就是说,只要在我写的程序码里面,设置去调用 PAM 的函数功能,我的程序就可以利用 Linux 原本就有的身份认证的程序咯!除此之外,其实我们的 Linux 核心也提供了相当多的函数库来给硬件开发者利用喔。

函数库又分为动态与静态函数库,这两个咚咚的分别我们在后面的小节再加以说明。 这里我们以一个简单的流程图,来示意一支有调用外部函数库的程序的执行情况。

程序执行时引用外部动态函数库的示意图图21.1.2、程序执行时引用外部动态函数库的示意图

很简单的示意图啊!^_^!而如果要在程序里面加入引用的函数库,就需要如图 21.1.1 所示, 亦即在编译的过程当中,就需要加入函数库的相关设置啰。 事实上, Linux 的核心提供很多的核心相关函数库与外部参数, 这些核心功能在设计硬件的驱动程序的时候是相当有用的信息,这些核心相关信息大多放置在 /usr/include, /usr/lib, /usr/lib64 里面哩!我们在本章的后续小节再来探讨。反正我们可以简单的这么想:

  • 函数库:就类似副程序的角色,可以被调用来执行的一段功能函数。### 20.1.3 什么是 make 与 configure

事实上,使用类似 gcc 的编译器来进行编译的过程并不简单,因为一套软件并不会仅有一支程序, 而是有一堆程序码文件。所以除了每个主程序与副程序均需要写上一笔编译过程的指令外,还需要写上最终的链接程序。 程序码小的时候还好,如果是类似 WWW 服务器软件 (例如 Apache) ,或者是类似核心的源代码,动则数百 MBytes 的数据量,编译指令会写到疯掉~这个时候,我们就可以使用 make 这个指令的相关功能来进行编译过程的指令简化了!

当执行 make 时,make 会在当时的目录下搜寻 Makefile (or makefile) 这个文本文件,而 Makefile 里面则记录了源代码如何编译的详细信息! make 会自动的判别源代码是否经过变动了,而自动更新可执行文件,是软件工程师相当好用的一个辅助工具呢!

咦!make 是一支程序,会去找 Makefile ,那 Makefile 怎么写? 通常软件开发商都会写一支侦测程序来侦测使用者的作业环境, 以及该作业环境是否有软件开发商所需要的其他功能,该侦测程序侦测完毕后,就会主动的创建这个 Makefile 的规则文件啦!通常这支侦测程序的文件名为 configure 或者是 config 。

咦!那为什么要侦测作业环境呢?在 第一章、Linux是什么与如何学习 当中, 不是曾经提过其实每个 Linux distribution 都使用同样的核心吗?但你得要注意, 不同版本的核心所使用的系统调用可能不相同,而且每个软件所需要的相依的函数库也不相同, 同时,软件开发商不会仅针对 Linux 开发,而是会针对整个 Unix-Like 做开发啊! 所以他也必须要侦测该操作系统平台有没有提供合适的编译器才行!所以当然要侦测环境啊! 一般来说,侦测程序会侦测的数据大约有下面这些:

  • 是否有适合的编译器可以编译本软件的程序码;
  • 是否已经存在本软件所需要的函数库,或其他需要的相依软件;
  • 操作系统平台是否适合本软件,包括 Linux 的核心版本;
  • 核心的表头定义文件 (header include) 是否存在 (驱动程序必须要的侦测)。 至于 make 与 configure 运行流程的相关性,我们可以使用下面的图示来示意一下啊! 下图中,你要进行的任务其实只有两个,一个是执行 configure 来创建 Makefile , 这个步骤一定要成功!成功之后再以 make 来调用所需要的数据来编译即可!非常简单!

通过 configure 与 make 进行编译示意图图21.1.3、通过 configure 与 make 进行编译示意图

由于不同的 Linux distribution 的函数库文件所放置的路径,或者是函数库的文件名订定, 或者是默认安装的编译器,以及核心的版本都不相同,因此理论上,你无法在 CentOS 7.x 上面编译出 binary program 后,还将他拿到 SuSE 上面执行,这个动作通常是不可能成功的! 因为调用的目标函数库位置可能不同 (参考图21.1.2) , 核心版本更不可能相同!所以能够执行的情况是微乎其微!所以同一套软件要在不同的平台上面执行时, 必须要重复编译!所以才需要源代码嘛!了解乎!详细的 make 用法与 Makefile 规则,在后续的小节里面再探讨啰!

20.1.4 什么是 Tarball 的软件

从前面几个小节的说明来看,我们知道所谓的原始程序码,其实就是一些写满了程序码的纯文本。 那我们在 第八章、文件与文件系统的压缩,打包与备份 压缩指令的介绍当中, 也了解了纯文本文件在网络上其实是很浪费带宽的一种文件格式! 所以啦,如果能够将这些源代码通过文件的打包与压缩技术来将文件的数量与容量减小, 不但让使用者容易下载,软件开发商的网站带宽也能够节省很多很多啊!这就是 Tarball 文件的由来啰!

Tips 想一想,一个核心的源代码文件大约要 300~500 MB 以上,如果每个人都去下载这样的一个核心文件, 呵呵!那么网络带宽不被吃的死翘翘才怪呢!

所谓的 Tarball 文件,其实就是将软件的所有源代码文件先以 tar 打包,然后再以压缩技术来压缩,通常最常见的就是以 gzip 来压缩了。因为利用了 tar 与 gzip 的功能,所以 tarball 文件一般的扩展名就会写成 *.tar.gz 或者是简写为 * .tgz 啰!不过,近来由于 bzip2 与 xz 的压缩率较佳,所以 Tarball 渐渐的以 bzip2 及 xz 的压缩技术来取代 gzip 啰!因此文件名也会变成 *.tar.bz2, * .tar.xz 之类的哩。所以说, Tarball 是一个软件包, 你将他解压缩之后,里面的文件通常就会有:

  • 原始程序码文件;
  • 侦测程序文件 (可能是 configure 或 config 等文件名);
  • 本软件的简易说明与安装说明 (INSTALL 或 README)。 其中最重要的是那个 INSTALL 或者是 README 这两个文件,通常你只要能够参考这两个文件, Tarball 软件的安装是很简单的啦!我们在后面的章节会再继续介绍 Tarball 这个玩意儿。

20.1.5 如何安装与升级软件

将源代码作了一个简单的介绍,也知道了系统其实认识的可可执行文件是 binary program 之后,好了,得要聊一聊,那么怎么安装与升级一个 Tarball 的软件?为什么要安装一个新的软件呢?当然是因为我们的主机上面没有该软件啰!那么, 为何要升级呢?原因可能有下面这些:

  • 需要新的功能,但旧有主机的旧版软件并没有,所以需要升级到新版的软件;
  • 旧版本的软件上面可能有资安上的顾虑,所以需要更新到新版的软件;
  • 旧版的软件执行性能不彰,或者执行的能力不能让管理者满足。 在上面的需求当中,尤其需要注意的是第二点,当一个软件有安全上的顾虑时,千万不要怀疑, 赶紧更新软件吧!否则造成网络危机,那可不是闹着玩的!那么更新的方法有哪些呢? 基本上更新的方法可以分为两大类,分别是:
  • 直接以源代码通过编译来安装与升级;
  • 直接以编译好的 binary program 来安装与升级。 上面第一点很简单,就是直接以 Tarball 在自己的机器上面进行侦测、编译、 安装与设置等等动作来升级就是了。不过,这样的动作虽然让使用者在安装过程当中具有很高的弹性, 但毕竟是比较麻烦一点,如果 Linux distribution 厂商能够针对自己的作业平台先进行编译等过程,再将编译好的 binary program 释出的话,那由于我的系统与该 Linux distribution 的环境是相同的,所以他所释出的 binary program 就可以在我的机器上面直接安装啦!省略了侦测与编译等等繁杂的过程呢!

这个预先编译好程序的机制存在于很多 distribution 喔,包括有 Red Hat 系统 (含 Fedora/CentOS 系列) 发展的 RPM 软件管理机制与 yum 线上更新模式; Debian 使用的 dpkg 软件管理机制与 APT 线上更新模式等等。

由于 CentOS 系统是依循标准的 Linux distribution,所以可以使用 Tarball 直接进行编译的安装与升级, 当然也可以使用 RPM 相关的机制来进行安装与升级啰!本章节主要针对 Tarball ,至于 RPM 则留待下个章节再来介绍呢!

好了,那么一个软件的 Tarball 是如何安装的呢?基本流程是这样的啦:

  • 将 Tarball 由厂商的网页下载下来;
  • 将 Tarball 解开,产生很多的源代码文件;
  • 开始以 gcc 进行源代码的编译 (会产生目标文件 object files);
  • 然后以 gcc 进行函数库、主、副程序的链接,以形成主要的 binary file;
  • 将上述的 binary file 以及相关的配置文件安装至自己的主机上面。 上面第 3, 4 步骤当中,我们可以通过 make 这个指令的功能来简化他, 所以整个步骤其实是很简单的啦!只不过你就得需要至少有 gcc 以及 make 这两个软件在你的 Linux 系统里面才行喔! 详细的过程以及需要的软件我们在后面的章节继续来介绍的啦!
下一节:经过上面的介绍之后,你应该比较清楚的知道源代码、编译器、函数库与可执行文件之间的相关性了。 不过,详细的流程可能还是不很清楚,所以,在这里我们以一个简单的程序范例来说明整个编译的过程喔!赶紧进入 Linux 系统,实地的操作一下下面的范例呢!