在我们知道了源代码的相关信息之后,再来要了解的自然就是如何使用具有源代码的T arball 来建立一个属于自己的软件。从前面几个小节的说明当中,我们晓得其实 Tarball 的安装是可以跨平台的,因为 C 语言的程序代码在各个平台上面是可以共通的,只是需要的编译程序可能并不相同而已。例如 Linux 在上面就是用 gcc,而 Windows上面也有相关的 C 编译程序。所以呢,同样的一组源代码,既可以在 CentOS Linux 上面编译,也可以在 SuSE Linux上面编译,当然,也可以在大部分的 Unix 平台上面编译成功的。
如果万一没有编译成功怎么办?很简单啊,透过修改小部分的程序代码(通常是很小部分的改动而已)就可以进行跨平台的移植了!也就是说,刚刚我们在 Linux 下写的程序,理论上,是可以在 Windows 上面编译的!这就是源代码的好处。
使用源代码管理软件所需要的基础软件
从源代码的说明我们知道要制作一个 binary program 需要很多东西的,这包括下面这些基础的软件:
- gcc 或 cc 等 C 语言编译程序(compiler);
没有编译程序怎么进行编译的动作?所以 C compiler 是一定要有的。不过 Linux 上面有众多的编译程序,其中当然以 GNU 的 gcc 是首选的自由软件编译程序。事实上很多在 Linux 平台上面发展的软件的源代码,原本就是以 gcc 为基础来设计的呢。
- make 及 autoconfig 等软件;
一般来说,以 Tarball 方式释出的软件当中,为了简化编译的流程,通常都是配合前几个小节提到的 make 这个指令来依据目标文件的相依性而进行编译。但是我们也知道说 make 需要 makefile 这个文件的规则,那由于不同的系统里面可能具有的基础软件环境并不相同,所以就需要侦测用户的作业环境,好自行建立一个 makefile 文件。这个自行侦测的小程序也必须要藉由 autoconfig 这个相关的软件来辅助才行。
- 需要 Kernel 提供的 Library 以及相关的 Include 文件;
从前面的原始码编译过程,我们知道了函式库(library)的重要性,同时也知道了有 include 文件的存在。很多的软件在发展的时候都是直接取用系统核心提供的函式库与 include 文件的,这样才可以与这个操作系统兼容。尤其是在驱动程序方面的模块,如网卡、声卡、USB 等驱动程序在安装的时候,常常是需要核心提供的相关信息的。在 RedHat 的系统当中(包含 Fedora/CentOS 等系列),这个核心相关的功能通常都是被包含在 kernel-source 或 kernel-header 这些软件名称当中,所以记得要安装这些软件喔!
虽然 Tarball 的安装比较简单,如同我们前面几个小节的例子,只要顺着开发商提供的 README 与 INSTALL 文件所载明的步骤来进行,安装是很容易的。但是我们却还是常常会在 BBS 或者是新闻组当中发现这些留言:” 我在执行某个程序的侦测文件时,他都会告诉我没有 gcc 这个软件,这是怎么回事?”还有:“我没有办法使用 make 耶!这是什么问题?”。呵呵~这,就是没有
安装上面提到的那些基础软件啦!
咦!为什么用户不安装这些软件啊?这是因为目前的 Linux distribution 大多已经偏向于桌面计算机的使用(非服务器端),他们希望使用者能够按照厂商自己的需求来安装相关的软件即可,所以通常默认是没有安装 gcc 或者是 make 等软件的。所以啦,如果你希望未来可以自行安装一些以 Tarball 方式释出的软件时,记得请自行挑选想要安装的基础软件哦!例如在 CentOS 或者是 RedHat
当中记得选择 Development Tools 以及 Kernel Source Development 等相关字眼的软件群集呢。
那万一我已经安装好一部 Linux 主机,但是使用的是默认所安装的软件,所以没有 make, gcc 等东东,该如何是好?问题其实不大啦,目前使用最广泛的 CentOS/Fedora 或者是 RedHat 大多是以 RPM 来安装软件的,所以,你只要拿出当初安装 Linux 时的原版光盘,然后以后面会介绍的 RPM 来一个一个的加入到你的 Linux 主机里面就好啦!很简单的。尤其现在又有 yum 这玩意儿,更方便呐!
在 CentOS 当中,如果你已经有网络可以连上 Internet 的话,那么就可以使用后面会谈到的 yum 啰!透过 yum 的软件群组安装功能,你可以这样做:
- 如果是要安装 gcc 等软件开发工具,请使用
yum groupinstall "Development Tools"
; - 若待安装的软件需要图形接口支持,一般还需要
yum groupinstall "X Software Development"
; - 若安装的软件较旧,可能需要
yum groupinstall "Legacy Software Development"
;
Tarball 安装的基本步骤
我们提过以 Tarball 方式释出的软件是需要重新编译可执行的 binary program 的。而 Tarball 是以 tar 这个指令来打包与压缩的文件,所以啦,当然就需要先将 Tarball 解压缩,然后到原始码所在的目录下进行 makefile 的建立,再以 make 来进行编译与安装的动作。所以整个安装的基础动作大多是这样的:
- 获取源代码文件:将 tarball 文件在
/usr/local/src
目录下解压缩; - 查看步骤流程:进入新建立的目录底下,去查阅
INSTALL
与README
等相关文件内容(很重要的步骤!); - 依赖软件安装:根据
INSTALL
/README
的内容查看并安装好一些依赖的软件(非必要); - 创建 makefile:以自动侦测程序(
configure
或config
) 侦测作业环境,并建立Makefile
这个文件; - 编译:执行 make 这个程序以该目录下的
Makefile
作为它的参数配置文件,来进行 make(编译或其他)的动作; - 安装:执行 make 这个程序,并以
Makefile
作为它的参数配置文件,依据install
这个目标(target)的指定来安装到正确的路径。
注意到上面的第二个步骤,通常每个软件在释出的时候,都会附上 INSTALL
或者是 README
这种档名的说明档,这些说明档请详细的阅读一遍, 通常这些文件会记录这个软件的安装要求、软件的工作项目、与软件的安装参数设定及技巧等,只要仔细的读完这些文件,基本上,要安装好 tarball 的软件,都不会有什么大问题。
至于 makefile 在制作出来之后,里头会有相当多的目标(target),最常见的就是 install
与 clean
。通常 make clean
代表着将目标文件(object file)清除掉,make
则是将源代码进行编译。注意哦!编译完成的可执行文件与相关的配置文件还在源代码所在的目录当中!因此,最后要进行 make install
来将编译完成的所有东东都给他安装到正确的路径去,这样就可以使用该软件啦!
OK!下面大概的提一下大部分的 tarball 软件之安装的指令下达方式:
./configure
这个步骤就是在建立 Makefile 这个文件,通常程序开发者会写一个 script 来检查你的 Linux 系统、相关的软件属性等等,这个步骤相当的重要,因为未来你的安装信息都是这一步骤内完成的!另外,这个步骤的相关信息应该要参考一下该目录下的 README 或 INSTALL 相关的文件。make clean
make 会读取 Makefile 中关于 clean 的工作。这个步骤不一定会有,但是希望执行一下,因为他可以去除目标文件,因为谁也不确定源代码里面到底有没有包含上次编译过的目标文件(*.o
) 存在,所以当然还是清除一下比较妥当的。至少等一下新编译出来的执行文件我们可以确定是使用自己的机器所编译完成的嘛!make
make 会依据 Makefile 当中的预设工作进行编译的行为!编译的工作主要是使用 gcc 来将原始码编译成为可以被执行的 object files,但是这些 object files 通常还需要一些函式库之类的 link 后,才能产生一个完整的执行文件!使用 make 就是要将原代码编译成为可以被执行的可执行文件,而这个可执行文件会放置在目前所在的目录之下,尚未被安装到预定安装的目录中。make install
通常这就是最后的安装步骤了,make 会依据 Makefile 这个文件里面关于 install 的项目,将上一个步骤所编译完成的数据给他安装到预定的目录中,就完成安装啦!
一般 Tarball 软件安装的建议事项(如何移除?升级?)
或许你已经发现了,那就是为什么前一个小节里面 Tarball 要在 /usr/local/src
里面解压缩呢?基本上,在默认的情况下,原本的 Linux distribution 释出安装的软件大多是在 /usr
里面的,而用户自行安装的软件则建议放置在 /usr/local
里面。这是考虑到用户管理所安装软件的便利性。
怎么说呢?我们知道几乎每个软件都会提供联机帮助的服务,那就是 info 与 man 的功能。在默认的情况下,man 会去搜寻 /ustr/local/man
里面的说明文件,因此, 如果我们将软件安装在 /ustr/local
下的话,那么安装完成之后,该软件的说明文件就可以被找到了。此外,如果你所管理的主机其实是由多人共同管理的,或者是如同学校里面,一部主机是由学生管理的,但是学生总会毕业吧?所以需要进行交接,如果大家都将软件安装在 /usr/local
下,那么管理上不就显的特别的容易吗?
所以,通常我们会建议大家将自己安装的软件放置在 /usr/local
下,至于源代码文件(Tarball)则建议放置在 /usr/local/src
( src
为 source
的缩写)底下。
再来,让我们先来看一看 Linux distribution 默认的安装软件的路径会用到哪些?我们以 apache 这个软件来说明的话:
/etc/httpd
;/usr/lib
;/usr/bin
;/usr/share/man
;
我们会发现软件的内容大致上是放在 etc
、lib
、bin
、man
等目录当中,分别代表配置文件、函式库、可执行文件、联机帮助文档。好了,那么如果你是以 tarball 来安装软件的话,默认是放在 /usr/local
里面,由于 /usr/local
原本就默认有这几个目录了,所以你的数据就会被放在:
/usr/local/etc
/usr/local/bin
/usr/local/lib
/usr/local/man
但是如果你每个软件都选择在这个默认的路径下安装的话,那么所有的软件的文件都将放置在这四个目录当中,因此,未来再想要升级或移除的时候,就会比较难以追查文件的来源了。而如果你在安装的时候选择的是单独的目录,例如将 apache 安装在 /usr/local/apache
当中,那么你的文件目录就会变成:
/usr/local/apache/etc
/usr/local/apache/bin
/usr/local/apache/lib
/usr/local/apache/man
单一软件的文件都在同一个目录之下,那么要移除该软件就简单的多了!只要将该目录移除即可视为该软件已经被移除。以上面为例,我想要移除 apache 只要执行 rm -rf /usr/local/apache
就算移除这个软件啦!当然,实际安装的时候还是得视该软件的 Makefile 里头的 install 信息才能知道到底他的安装情况为何的。
这个方式虽然有利于软件的移除,但不知道你有没有发现,我们在执行某些指令的时候,与该指令是否在 PATH
这个环境变量所记录的路径有关,以上面为例,我的 /usr/local/apache/bin
肯定是不在 PATH
里面的,所以执行 apache 的指令就得要利用绝对路径了,否则就得将这个 /usr/local/apache/bin
加入 PATH
里面。另外,那个 /usr/local/apache/man
也需要加入 man page
搜寻的路径当中。
除此之外,Tarball 在升级的时候也是挺困扰的,怎么说呢?我们还是以 apache 来说明好了。WWW 服务器为了考虑互动性,所以通常会将 PHP+MySQL+Apache 一起安装起来,如此的话,那么每个软件在安装的时候都有一定的顺序与程序!因为他们三者之间具有相关性,所以安装时必需要同时考虑到他们的函式库与相关的编译参数。
假设今天我只要升级 PHP 呢?有的时候因为只有涉及动态函式库的升级,那么我只要升级 PHP 即可!其他的部分或许影响不大。但是如果今天 PHP 需要重新编译的模块比较多,那么可能会连带的连 Apache 这个程序也需要重新编译过才行!真是有点头痛的!没办法啦!使用 tarball 确实有它的优点,但是在这方面,确实也有一定的伤脑筋程度。
由于 Tarball 在升级与安装上面具有这些特色,亦即 Tarball 在卸载上面具有比较高的难度(如果你没有好好规划的话~),所以,为了方便 Tarball 的管理,通常鸟哥会这样建议使用者:
- 最好将 tarball 的原始数据解压缩到
/ustr/local/src
当中; - 安装时,最好安装到
/usr/local
这个默认路径下; - 考虑未来的卸载步骤,最好可以将每个软件单独的安装在
/usr/local
下; - 把安装到单独目录的软件的 man page 加入 man path 搜寻范围中:
如果你安装的软件安装到
/usr/local/software/
,那么 man page 搜寻的设定中,可能就得要在/etc/man_db.conf
内的40~50
行左右处,写入如下的一行:MANPATH_MAP /usr/local/software/bin /usr/local/software/man
这样才可以使用 man 来查询该软件的文档了。
时至今日,老实说,真的不太需要有 tarball 的安装了! CentOS/Fedora 有个 RPM 补遗计划,就是俗称的 EPEL 计划,相关网址:https://fedoraproject org/wiki/EPEL。一般学界会用到的软件都在里头~除非你要用的软件是专属软件(要钱的)或者是比较冷门的软件,否则都有好心的网友帮我们打包好了啦~
一个简单的范例、利用 ntp 来示范
读万卷书不如行万里路啊!所以当然我们就来测试看看,看你是否真的了解了如何利用 Tarball 来安装软件呢?我们利用时间服务器(network time protocol)ntp 这个软件来测试安装看看。先请到 http://www.ntp.org/downloads.html 这个网站去下载文件下载最新版本的文件即可。或者直接到鸟哥的网站下载释出的稳定版本:
http://linux.vbird.org/linux_basic/0520source/ntp-4.2.8p3.tar.gz
假设我对这个软件的要求是这样的:
- 假设
ntp-4.*.*.tar.gz
这个文件放置在/root
这个目录下; - 原代码文件请解开在
/usr/local/src
底下; - 安装到
/usr/local/ntp
这个目录中;
那么你可以依照底下的步骤来安装测试看看。
解压缩下载的 tarball,并参阅 README
/INSTALL
文件:
[root@localhost ~]# wget http://linux.vbird.org/linux_basic/0520source/ntp-4.2.8p3.tar.gz
[root@localhost ~]# cd /usr/local/src/
[root@localhost src]# tar -zxf /root/ntp-4.2.8p3.tar.gz
[root@localhost src]# cd ntp-4.2.8p3/
[root@localhost ntp-4.2.8p3]# less INSTALL
检查 configure 支持参数,并实际建置 makefile 规则文件:
[root@localhost ntp-4.2.8p3]# ./configure --help | less
[root@localhost ntp-4.2.8p3]# ./configure --prefix=/usr/local/ntp --enable-all-clocks --enable-parse clocks
一般来说 configure
设定参数较重要的就是 --prefix=/path
了,--prefix
后面接的路径就是这个软件未来要安装到那个目录去?如果你没有指定 --prefix=/path
这个参数,通常预设参数就是 /usr/local
,至于其他的参数意义就得要参考 ./configure --help
了。这个动作完成之后会产生 makefile
或 Makefile
这个文件。当然啦,这个侦测检查的过程会显示在屏幕上,特别留意关于 gcc 的检查,还有最重要的是最后需要成功的建立起 Makefile
才行!
最后开始编译与安装:
[root@localhost ntp-4.2.8p3]# make clean; make
[root@localhost ntp-4.2.8p3]# make check
[root@localhost ntp-4.2.8p3]# make install
就这么简单,你完成了吗?完成之后到 /usr/local/ntp
你发现了什么?
利用 patch 更新原始码
我们在本章一开始介绍了为何需要进行软件的升级,这是很重要的!那假如是以 Tarball 来进行某个软件的安装,那么是否当要升级这个软件时,就得要下载这个软件的完整全新的 Tarball 呢?
事实上,当我们发现一些软件的漏洞,通常是某一段程序代码写的不好所致。因此,所谓的更新原始码,常常是只需要更改部分文件的小部分内容而己。既然如此的话,那么我们是否可以就那些被更改的文件来进行修改就可以?也就是说,旧版本到新版本间没有更动过的文件就不要理他,仅处理有修订过的文件部分即可。
这有什么好处呢?首先,没有更改过的文件的目标文件(object file)根本就不需要重新编译,而且有更改过的文件又可以利用 make 来自动 update(更新),如此一来,我们原先的设定(makefile 文件里面的规则)将不需要重新改写或侦测!可以节省很多宝贵的时间呢~
从上面的说明当中,我们可以发现,如果可以将旧版的源代码数据改写成新版的版本,那么就能直接编译了,而不需要将全部的新版Tarball 重新下载一次呢!节省了带宽与时间。那么如何改写源代码呢?难道要我们一个文件一个文件去参考然后修订吗?当然没有这么没人性!
有一个比对文件的指令,那就是 diff
,这个指令可以将两个文件之间的差异性列出来。那我们也知道新旧版本的文件之间,其实只有修改一些程序代码而已,那么我们可以通过 diff
比对出新旧版本之间的文字差异,然后再以相关的指令来将旧版的文件更新吗?当然可以啦!那就是 patch 这个指令!很多的软件开发商在更新了源代码之后,几乎都会释出所谓的 patch file,也就是直接将源代码 update 的一个方式。
这里我们来举个案例解释一下好了。假设我们之前计算三角函数的程序(main)历经多次改版,0.1 版仅会简单的输出,0.2 版的输出就会含有角度值,因此这两个版本的内容不相同。如下所示,两个文件的意义为:
- http://linux.vbird.org/linux_basic/0520source/main-0.1.tgz:main 的 0.1 版;
- http://linux.vbird.org/linux_basic/0520source/main_0.1_to_0.2.patch:main 由 0.1 升级到 0.2 的 patch file;
请您先下载这两个文件,并且解压缩到你的 /root
底下。你会发现系统产生一个名为 main-0.1
的目录。该目录内含有五个文件,就是刚刚的程序加上一个 Makefile 的规则文件。你可以到该目录下去看看 Makefile 的内容,在这一版当中含有 main
与 clean
两个目标功能而已。至于 0.2 版则加入了 install
与 uninstall
的规则设定。接下来,请看一下我们的做法:
测试旧版程序的功能:
[root@localhost ~]# tar zxf main-0.1.tgz
[root@localhost ~]# cd main-0.1
[root@localhost main-0.1]# make clean main
[root@localhost main-0.1]# ./main
version 0.1
Please input your name: zze
Please enter the degree angle (ex> 90): 45
Hi, Dear zze, nice to meet you.
The Sin is: 0.71
The Cos is: 0.71
与之前的结果非常类似,只是将 Makefile
直接给你了!但如果你下达 make install
时,系统会告知没有 install 的 target,而且版本是 0.1 也告知了。那么如何更新到 0.2 版呢?这个 patch 文件就要派上用场了!这个文件的内容大致如下:
查看 patch file 内容:
diff -Naur main-0.1/cos_value.c main-0.2/cos_value.c
--- main-0.1/cos_value.c 2015-09-04 14:46:59.200444001 +0800
+++ main-0.2/cos_value.c 2015-09-04 14:47:10.215444000 +0800
@@ -7,5 +7,5 @@
{
float value;
...
上面有一些以 diff
开头的行,那代表使用 diff
去比较时,被比较的两个文件所在路径,这个路径非常的重要哦!因为 patch
的基本语法如下:
patch -p<数字> < <patch_file>
特别留意那个 -p<数字>
,那是与 patch_file 里面列出的文件名有关的信息。假如在 patch_file 第一行的文件名是这样写的:
/home/guest/example/expatch.old
那么当下达 patch -p0 < patch_file
时,则更新的文件是 /home/guest/example/expatch.old
,如果是 patch -pl < patch_file
,则更新的文件为 home/guest/example/expatch.old
,如果 patch -p4 < patch_ file
则更新 expatch.old
,也就是说,-px
那个 x
代表拿掉 x
个斜线的意思!这样可以理解了吗?好了,根据刚刚上面的信息,我们可以发现比较的文件是在 main-0.1/xxx
与 main-0.2/xxx
,所以说,如果你是在 main-0.1
底下,并且想要处理更新时,就得要拿掉一个目录,因为 main-0.1
下并没有 main-0.2
的目录存在,因此使用的是 -p1
才对!
所以:
更新源代码文件:
[root@localhost main-0.1]# patch -p1 < ../main_0.1_to_0.2.patch
patching file cos_value.c
patching file main.c
patching file Makefile
patching file sin_value.c
请注意,目前所在目录是在
main-0.1
底下!注意与 patch 文件的相对路径。虽然有五个文件,但其实只有四个文件有修改过!上面显示的是有改过的文件!
重新编译并运行程序:
[root@localhost main-0.1]# make clean main
rm -f main main.o haha.o sin_value.o cos_value.o
cc -c -o main.o main.c
cc -c -o haha.o haha.c
cc -c -o sin_value.o sin_value.c
cc -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
[root@localhost main-0.1]# ./main
version 0.2
Please input your name: zze
Please enter the degree angle (ex> 90): 45
Hi, Dear zze, nice to meet you.
The sin(45.000000) is: 0.71
The cos(45.000000) is: 0.71
可以发现,输出的结果中版本变了,输出信息多了括号(角度)喔!
还可将它安装到 /usr/local/bin
以及卸载:
[root@localhost main-0.1]# make install
cp -a main /usr/local/bin
[root@localhost main-0.1]# main
version 0.2
Please input your name: zze
Please enter the degree angle (ex> 90): 45
Hi, Dear zze, nice to meet you.
The sin(45.000000) is: 0.71
The cos(45.000000) is: 0.71
[root@localhost main-0.1]# make uninstall
rm -f /usr/local/bin/main
很有趣的练习吧!所以你只要下载 patch file 就能够对你的软件源代码更新了!只不过更新了源代码并不代表软件的更新,你还是需要将该软件进行编译后,才会是最终正确的软件。因为 patch 的功能主要仅只是更新源代码文件而已!切记切记!此外,如果你 patch 出现错误呢?没关系的,我们的 patch 操作是可以回滚的!通过 patch-R < ./main_0.1_to_0.2.patch
就可以还原啦!很有趣吧~
评论区