Linux【8】-软件管理-1-1-开放源码的软体安装与升级简介(Tarball)

因为Linux上面的软体几乎都是经过GPL的授权,所以每个软体几乎均提供原始程式码,并且你可以自行修改该程式码,以符合你个人的需求呢!

  • 我们都知道,计算机只能识别机器语言,也就是二进制语言,所以源码包的安装需要一名“翻译官”将“abcd”翻译成二进制语言,这名“翻译官”通常被称为编译器。
  • “编译”指的是从源代码到直接被计算机(或虚拟机)执行的目标代码的翻译过程,编译器的功能就是把源代码翻译为二进制代码,让计算机识别并运.

一、什么是开放源码、编译器与可执行档

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

或许你会说shell scripts不是也可以执行吗?其实shell scripts只是利用shell (例如bash)这支程式的功能进行一些判断式,而最终执行的除了bash提供的功能外,仍是呼叫一些已经编译好的二进位程式来执行的呢!当然啦, bash本身也是一支二进位程式啊!那么我怎么知道一个档案是否为binary呢

#先以系统的档案测试看看: 
[root@study ~]# 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呢?
[root@study ~]# 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之类的字样!

事实上,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啰。整个的流程有点像这样:

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

总之,我们可以这么说:

  • 开放源码:就是程式码,写给人类看的程式语言,但机器并不认识,所以无法执行;
  • 编译器:将程式码转译成为机器看的懂得语言,就类似翻译者的角色;
  • 可执行档:经过编译器变成二进位程式后,机器看的懂所以可以执行的档案。

二、什么是函式库

在前一小节的图21.1.1示意图中,在编译的过程里面有提到函式库这东西。什么是函式库呢?先举个例子来说:我们的Linux系统上通常已经提供一个可以进行身份验证的模组,就是PAM模组。这个PAM提供的功能可以让很多的程式在被执行的时候,除了可以验证使用者登入的资讯外,还可以将身份确认的资料记录在登录档里面,以方便系统管理员的追踪!

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

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

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

  • 函式库:就类似副程式的角色,可以被呼叫来执行的一段功能函数。

三、什么是make 与configure

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

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

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

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

  • 是否有适合的编译器可以编译本软体的程式码;
  • 是否已经存在本软体所需要的函式库,或其他需要的相依软体;
  • 作业系统平台是否适合本软体,包括Linux 的核心版本;
  • 核心的表头定义档(header include) 是否存在(驱动程式必须要的侦测)。

至于make 与configure 运作流程的相关性,我们可以使用底下的图示来示意一下啊!下图中,妳要进行的任务其实只有两个:

  1. 一个是执行configure 来建立Makefile , 这个步骤一定要成功!
  2. 成功之后再以make 来呼叫所需要的资料来编译即可!非常简单!

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

四、什么是Tarball 的软体

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

想一想,一个核心的原始码档案大约要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 这个玩意儿。

五、 如何安装与升级软体

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

  • 需要新的功能,但旧有主机的旧版软体并没有,所以需要升级到新版的软体;
  • 旧版本的软体上面可能有资安上的顾虑,所以需要更新到新版的软体;
  • 旧版的软体执行效能不彰,或者执行的能力不能让管理者满足。

在上面的需求当中,尤其需要注意的是第二点,当一个软体有安全上的顾虑时,千万不要怀疑, 赶紧更新软体吧!否则造成网路危机,那可不是闹着玩的!那么更新的方法有哪些呢?基本上更新的方法可以分为两大类,分别是:

  1. 直接以原始码透过编译来安装与升级;
  2. 直接以编译好的binary program 来安装与升级。

上面第一点很简单,就是直接以Tarball 在自己的机器上面进行侦测、编译、 安装与设定等等动作来升级就是了。不过,这样的动作虽然让使用者在安装过程当中具有很高的弹性, 但毕竟是比较麻烦一点,如果Linux distribution 厂商能够针对自己的作业平台先进行编译等过程,再将编译好的binary program 释出的话,那由于我的系统与该Linux distribution 的环境是相同的,所以他所释出的binary program 就可以在我的机器上面直接安装啦!省略了侦测与编译等等繁杂的过程呢!

这个预先编译好程式的机制存在于很多distribution喔,包括:

  1. 有Red Hat系统(含Fedora/CentOS系列)发展的RPM软体管理机制与yum线上更新模式;
  2. Debian使用的dpkg软体管理机制与APT线上更新模式等等。

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

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

  1. 将Tarball 由厂商的网页下载下来;
  2. 将Tarball 解开,产生很多的原始码档案;
  3. 开始以gcc 进行原始码的编译(会产生目标档object files);
  4. 然后以gcc 进行函式库、主、副程式的连结,以形成主要的binary file;
  5. 将上述的binary file 以及相关的设定档安装至自己的主机上面。

上面第3, 4 步骤当中,我们可以透过make 这个指令的功能来简化他, 所以整个步骤其实是很简单的啦!只不过你就得需要至少有 gcc 以及make 这两个软体在你的Linux 系统里面才行喔!详细的过程以及需要的软体我们在后面的章节继续来介绍的啦!

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn