tarball的管理与建议

源自:http://hi.baidu.com/ilovejoy/blog/item/a4d2e63d8a3b74e33d6d9787.html

Tarball的管理与建议:
       好了! 在我们知道了原始码的相关资讯之后,再来要了解的自然就是如何使用具有原始码的Tarball 来建立一个属于自己的套件啰! 从前面几个小节的说明当中,我们晓得其实Tarball的安装是可以跨平台的 , 因为C语言的程式码在各个平台上面是可以共通的 ,只是需要的编译器可能并不相同而已。 例如Linux 上面用gcc 而Windows 上面也有相关的C 编译器啊~所以呢,同样的一组原始码,既可以在Mandrake Linux 上面编译,也可以在Red Hat Linux 上面编译,当然,也可以在大部分的Unix 平台上面编译成功的! 所以啰, Tarball 原始码程式应该可以在大部分的环境底下安装成功的! 举例来说,鸟哥在上面几个小节所提供的C 程式是在Red Hat 9 上面测试编译的,那么您可以下载之后在自己的Linux 环境下测试看看,我想,每个人应该都可以顺利的编译成功的才是! 因为C 的语法是没有不一样的啊! ^_^

      如果万一没有编译成功怎么办? 很简单啊,透过修改小部分的程式码( 通常是因为很小部分的异动而已)就可以进行跨平台的移植了! 也就是说,刚刚我们在Linux底下写的程式『 理论上,是可以在Windows上面编译的 ! 』这就是原始码的好处啦! 所以说,如果朋友们想要学习程式语言的话,鸟哥个人是比较建议学习『 具有跨平台能力的程式语言 』,例如C就是很不错的一个!

_________________

_______________________
使用原始码管理套件所需要的基础套件

        从原始码的说明我们晓得要制作一个binary执行档需要很多咚咚的呢! 这包括底下这些基础的套件:
• gcc或cc等C语言编译器( compiler ) :
       这是一定要的啦! 要将原始码编译成为可执行的binary才行,所以当然就需要编译器啰! 在Linux上面用的当然就是GNU发展的gcc这个超好用的免费的C编译器啦! 并且,很多在Linux平台上面发展的套件的原始码,原本就是以gcc为底来设计的呢。
 
• make及autoconfig等套件 :

       一般来说,以Tarball 方式释出的套件当中,为了简化编译的行程,通常都是配合前几个小节提到的make 这个指令来依据目标档案的相依性而进行编译。 但是我们也知道说make 需要makefile 这个档案的规则,那由于不同的系统里面可能具有的基础套件环境并不相同,所以就需要侦测使用者的作业环境,好自行建立一个makefile 档案。 这个自行侦测的小程式也必须要藉由autoconfig 这个相关的套件来辅助才行。


• 需要Kernel提供的Library以及相关的Include档案 :

       从前面的原始码编译过程,我们晓得函式库( library )的重要性,同时也晓得有include 档案的存在。 很多的套件在发展的时候都是直接取用系统核心提供的函式库与include 档案的,这样才可以与这个作业系统相容啊! 尤其是在『 驱动程式方面的套件 』,例如网路卡、音效卡、USB等驱动程式在安装的时候,常常是需要核心提供的相关资讯的。 在Red Hat的系统当中,这个核心相关的功能通常都是被包含在kernel-source或kernel-header这些套件名称当中,所以记得要安装这些套件喔!


Tarball安装的基本步骤

       我们提过以Tarball方式释出的套件是需要重新编译可执行的binary file的。 而Tarball是以tar这个指令来打包与压缩的档案,所以啦,当然就需要先将Tarball解压缩,然后到原始码所在的目录下进行makefile的 建立,再以make来进行编译与安装的动作啊! 所以整个安装的基础动作大多是这样的:
1. 将tarball档案在/usr/local/src目录下解压缩;
2. 进入新建立的目录底下,去查阅INSTALL与README等相关档案内容(很重要的步骤! ) ;
3. 根据INSTALL/README的内容察看并安装好一些相依的套件(非必要);
4. 以自动侦测程式( configure或config )侦测作业环境,并建立Makefile这个档案;
5. 以make这个程式并使用该目录下的Makefile做为他的参数设定档,来进行make (编译或其他)的动作;
6. 以make这个程式,并以Makefile这个参数设定档,依据install这个标的( target )的指定来安装到正确的路径!

       注意到上面的第二个步骤,通常在每个软体在释出的时候,都会附上INSTALL或者是README这种档名的说明档,这些说明档请『 确实详细的 』阅读过一遍,通常这些档案会记录这个软体的安装要 求、 软体的工作项目、与软体的安装参数设定及技巧等,只要仔茠琐\读完这些档案,基本上,要安装好tarball的档案,都不会有什么大问题啰。 至于makefile在制作出来之后,里头会有相当多的标的( target ),最常见的就是install与clean啰! 通常『make clean』代表着将目标档( object file )清除掉,『make』则是将原始码进行编译而已。 注意喔! 编译完成的可执行档与相关的设定档还在原始码所在的目录当中喔! 因此,最后要进行『make install』来将编译完成的所有咚咚都给他安装到正确的路径去,这样就可以使用该套件啦!
 
OK! 我们底下约略提一下大部分的tarball软体之安装的指令下达方式:
1. ./configure :

       这个步骤就是在建立Makefile这的档案啰! 通常程式开发者会写一支scripts来检查您的Linux系统、相关的套件属性等等 ,这个步骤相当的重要,因为未来您的安装资讯都是这一步骤内完成的! 另外,这个步骤的相关资讯应该要参考一下该目录下的README或INSTALL相关的档案 ! ! 基本上,这个步骤完成之后会建立(或修改)一个Makefile ,这就是参数档啦!
 
2. make clean :

      make会读取Makefile中关于clean的工作。 这个步骤不一定会有,但是希望执行一下! 为什么呢? 因为在进行编译的时候,会产生一些*.o的档案,例如有个abc.c的原始码,经过编译后会变成abc.o的档案! 我们称这些档案为object file ,这些档案如果之前已经编译过并留下来的话,那么这次再编译的时候,就不会编译该档案,然而由于我们可能已经修改了部分的参数,因此该档案的编译结果事实 上应该会有所不同! 因此,为了避免前一次留下来的资料可能影响到这次编译的结果,所以通常可以进行一下这个步骤啰!
 
3. make :

        make会依据Makefile当中的预设工作进行编译的行为! 编译的工作主要是进行gcc来将原始码编译成为可以被执行的object file s ,但是这些object files通常还需要一些函式库之类的link 后,才能产生一个完整的执行档! 使用make就是要将原始码编译成为可以被执行的可执行档,而这个可执行档会放置在目前所在的目录之下,尚未被安装到预定安装的目录中;
 
4. make install :

      通常这就是最后的安装步骤了,make会依据Makefile这个档案里面关于install的项目,将上一个步骤所编译完成的资料给他安装到预定的目录中,就完成安装啦!
 
5. 特别留意 :

       请注意,上面的步骤是一步一步来进行的,而 其中只要一个步骤无法成功,那么后续的步骤就完全没有办法进行的! 因此,要确定每一的步骤都是成功的才可以! 举个例子来说,万一今天你在./configure就不成功了,那么就表示Makefile无法被建立起来,要知道,后面的步骤都是根据Makefile 来进行的,既然无法建立Makefile ,后续的步骤当然无法成功啰! 另外,如果在make无法成功的话,那就表示原始档案无法被编译成可执行档,那么make install主要是将编译完成的档案给他安装下去的,既然都没有成功的执行档了,怎么进行安装? 所以啰,要每一个步骤都正确无误才能往下继续做! 此外,如果安装成功,并且是安装在独立的一个目录中,例如/usr/local/packages这个目录中好了,那么您就必需手动的将这个套件的man page给他放到/etc/man. config里面去。


________________________________________
一般Tarball套件安装的建议事项(如何移除?升级? )
       或许您已经发现了也说不定,那就是为什么前一个小节里面, Tarball要在/usr/local/src里面解压缩呢 ? 呵呵! 基本上,在预设的情况下,原本的Linux distribution 释出安装的套件大多是在/usr 里面的,而使用者自行安装的套件则建议放置在/usr/local 里面。 这是考量到管理使用者所安装套件的便利性。 怎么说呢? 我们晓得几乎每个套件都会提供线上说明的服务,那就是info 与man 的功能。 在预设的情况下, man 会去搜寻/usr/local/man 里面的说明文件,因此,如果我们将套件安装在/usr/local 底下的话,那么自然安装完成之后,该套件的说明文件就可以被找到了。 此外,如果您所管理的主机其实是由多人共同管理的,或者是如同学校里面,一部主机是由学生管理的,但是学生总会毕业吧? 所以需要进行交接,如果大家都将套件安装在/usr/local 底下,那么管理上不就显的特别的容易吗? ! 所以啰,通常我们会建议大家将自己安装的套件放置在/usr/local 下,至于原始码( Tarball )则建议放置在/usr/local/src( src 为source 的缩写)底下啊。

       再来,让我们先来看一看Linux distribution 预设的安装套件的路径会用到哪些? 我们以apache 这个软体来说明的话( apache 是WWW 伺服器软体,详细的资料请参考伺服器架设篇。您的系统不见得有装这个套件):
• /etc/httpd
• /usr/lib
• /usr/bin
• /usr/share/man
我们会发现套件的内容大致上是摆在etc, lib, man, bin等目录当中,分别代表『 设定档、函式库、执行档、线上说明档 』。 好了,那么你是以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 资讯才能知道到底他的安装情况为何的。 因为例如sendmail的安装就很麻烦......这个方式虽然有利于套件的移除,但不晓得您有没有发现,我们在执行某些指令的时候,与该指令是否在 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的管理,通常我们会这样建议使用者:
1. 最好将tarball的原始资料解压缩到/usr/local/src当中;
2. 安装时,最好安装到/usr/local这个预设路径下;
3. 考虑未来的反安装步骤,最好可以将每个套件单独的安装在/usr/local底下,例如安装rp-pppoe-2.6.tar.gz时,则可以指定该套件 需要安装于/usr/local/ rp-pppoe当中,如此一来,该套件会将所有的资料都写入/usr/local/rp-pppoe当中,因此,未来如果要移除该套件,只要将该目录删 除即可视为成功的移除了

4. 不过单独安装某个套件在某一特定路径下的作法,会导致当有man page的时候,使用预设的MANPATH会找不到相关的说明档案内容。 这个时候就必须要将man page的路径加到/etc/man.config档案中了! 否则使用man也查询不到指令的使用方法的。 以上面的例子为例,如果是安装了/usr/local/rp-pppoe当中,通常man page会放在/usr/local/rp-pppoe/man当中,所以,您就必需要在/etc/man .config里面差不多40~50行左右的地方,加入底下这一行:
MANPATH /usr/local/rp-pppoe/man

      这样就可以使用man来查询资料啰!

一个简单的范例、利用ntp来示范
       读万卷书不如行万里路啊! 所以当然我们就来给他测试看看,看您是否真的了解了如何利用Tarball 来安装软体呢? ! 我们利用时间伺服器ntp-4.1.2 这个套件来测试安装看看。 先请到http://www.ntp.org/downloads.html 这个目录去下载档案,( 您也可以下载比较新的档案来测试的啦! )或者直接到鸟哥的网站下载:
http://linux.vbird.org/download/books/basic/source_code/ntp-4.1.2.tar.gz

假设我对这个套件的要求是这样的:
• 假设ntp-4.1.2.tar.gz 这个档案放置在/root 这个目录下;
• 原始码请解开在/usr/local/src 底下;
• 我要安装到/usr/local/ntp 这个目录中;

       那么您可以依照底下的步骤来安装测试看看( 如果可以的话,请您不要参考底下的文件资料,先自行安装过一遍这个软体,然后再来对照一下鸟哥的步骤喔! )。


# 1.解压缩,并阅读一下ntp底下的README与INSTALL:
[root@test root]# cd /usr/local/src

[root@test src]# tar -zxvf /root/ntp-4.1.2.tar.gz
#这个步骤会让原始码解开成为/usr/local/src/ntp-4.1.2这个目录

 
# 2.进入原始码所在目录,并且查阅如何安装的技巧

[root@test src]# cd ntp-4.1.2
[root@test ntp-4.1.2]# vi INSTALL (或vi README)
 
# 3.开始设定参数、编译与安装:

[root@test ntp-4.1.2]# ./configure --help | more
#上面这个动作可以察看一下可用的参数!
 
[root@test ntp-4.1.2]# ./configure --prefix=/usr/local/ntp \
> --enable-all-clocks --enable-parse-clocks
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
.....(略)....
configure: creating ./config.status
config.status: creating Makefile
#一般来说configure设定参数较重要的就是那个--prefix=/path了,
# --prefix后面接的路径就是『 这个软体未来要安装到那个目录去 ? 』
#如果您没有指定--prefix=/path这个参数,通常预设参数就是/usr/local
#至于其他的参数意义就得要参考./configure --help了!
#这个动作完成之后会产生makefile或Makefile这个档案
#当然啦,这个侦测检查的过程会显示在萤幕上, 特别留意关于gcc的检查 ,
#还有最重要的是 最后需要成功的建立起Makefile才行 ! (上面最后一行)

 
[root@test ntp-4.1.2]# make clean ; make
[root@test ntp-4.1.2]# make check
[root@test ntp-4.1.2]# make install
#将资料给他安装在/usr/local/ntp底下

 
整个动作就这么简单,您完成了吗? ! 完成之后到/usr/local/ntp您发现了什么? !
__________________

______________________
利用patch更新原始码

        我们在前言里面介绍了为何需要进行套件的升级 ,这是很重要的喔! 那假如我是以Tarball 来进行某个套件的安装,那么是否当我要升级这个套件时,就得要下载这个套件的完整全新的Tarball 呢? 举个例子来说,鸟哥有个讨论区在http://phorum.vbird.org 这 个网址,这个讨论区是以phpBB这个套件来架设的,而鸟哥的讨论区版本为phpbb2.0.1.tar .gz ,目前( 2004/04/10 )最新释出的版本则是phpbb2.0.8.tar.gz 。 那我是否需要下载全新的phpbb2.0.8.tar.gz 这个档案来更新原本的旧程式呢?

       事实上,当我们发现一些套件的漏洞,通常是某一段程式码写的不好所致。 因此,所谓的『更新原始码』常常是只有更改部分档案的小部分内容而已。 既然如此的话,那么我们是否可以就那些被更动的档案来进行修改就可以咯? 也就是说,旧版本到新版本间没有更动过的档案就不要理他,仅将有修订过的档案部分来处理即可。 这有什么好处呢? 首先,没有更动过的档案的目标档( object file )根本就不需要重新编译而且有更动过的档案又可以利用make来自动update (更新), 如此一来,呵呵! 我们原先的设定( makefile 档案里面的规则)将不需要重新改写或侦测! 呵呵! 可以节省很多宝贵的时间呢(例如后续章节会提到的核心的编译! )

       从上面的说明当中,我们可以发现,如果可以将旧版的原始码资料改写成新版的版本,那么就能直接编译了,而不需要将全部的新版Tarball 重新下载一次呢! 可以节省频宽与时间说! 那么如何改写原始码? 难道要我们一个档案一个档案去参考然后修订吗? 当然没有这么没人性! 我们在正规表示法的时候有提到一个比对两个档案的指令,那就是diff ,这个指令可以将『 两个档案之间的差异性列出来 』呢! 那我们也知道新旧版本的档案之间,其实只有修改一些程式而已,那么我们可以透过diff 比对出新旧版本之间的文字差异,然后再以相关的指令来将旧版的档案更新吗? ! 呵呵! 当然可以啦! 那就是patch 这个指令啦! 很多的套件开发商在更新了原始码之后,几乎都会释出所谓的patch file,也就是直接将原始码update 而已的一个方式喔 ! 我们底下以一个简单的范例来说明给您了解喔!

假设我们有两个档案,分别是expatch.old 与expatch.new ,他们的内容是这样的:
[guest@test guest]# vi expatch.old
echo "check your postfix's body and header drop settings"
echo "postmap -q - regexp:header_checks < header_checks"
postmap -q - regexp:header_checks < header_checks
echo "postmap -q - regexp:body_checks < body_checks"
postmap -q - regexp:body_checks < body_checks
[guest@test guest]# vi expatch.new
echo "check your postfix's body and header drop settings"
echo "postmap -q - regexp:header_checks < header_checks This's right"
postmap -q - regexp:header_checks < header_checks
echo "postmap -q - regexp:body_checks < body_checks This's right"
postmap -q - regexp:body_checks < body_checks

 
两个档案的不同点在于:
[guest@test guest]# diff expatch.old expatch.new
2c2
< echo "postmap -q - regexp:header_checks < header_checks"
---
> echo "postmap -q - regexp:header_checks < header_checks This's right"
4c4
< echo "postmap -q - regexp:body_checks < body_checks"
---
> echo "postmap -q - regexp:body_checks < body_checks This's right"

 
        上面显示出两个档案的不同点,详细的意义请参考正规表示法那个章节的介绍。 好了,假如我以『 diff -c expatch.old expatch.new 』以及上面显示的资讯,做成一个档案,内容是这样的:
[guest@test guest]# vi expatch.patch
*** expatch.old 2004-04-09 14:22:49.000000000 +0800
--- expatch.new 2004-04-09 14:23:18.000000000 +0800
2c2
< echo "postmap -q - regexp:header_checks < header_checks"
---
> echo "postmap -q - regexp:header_checks < header_checks This's right"
4c4
< echo "postmap -q - regexp:body_checks < body_checks"
---
> echo "postmap -q - regexp:body_checks < body_checks This's right"

 
       注意到,这个档案的第一行显示出旧版本的档名,而第二行则为新版本的档名与时间,第三行以后则是两个档案的差异性。 那么我们将以patch 来进行更新,将expatch.old 更新到expatch.new 看看。 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 -p1 < patch_file』,则更新的档案为『home/guest/ example/expatch.od』,如果『patch -p4 < patch_file』则更新『expatch.old』,也就是说, -pxx那个xx代表『拿掉几个斜线(/)』的意思! 这样可以理解了吗? ! 好了,那么我要开始来更新我的expatch.old 了,可以这样搞定:
[guest@test guest]# patch -p0 < expatch.patch
#注意喔,这个时候我的工作目录底下会存在expatch.old才对!
#然后立刻察看一下,您会发觉, expatch.new与expatch.old变成一模一样的了!

 
很容易了解吧! 上面三个档案您可以在底下的网址取得:
http://linux.vbird.org/download/books/basic/source_code/expatch.tgz

      加油的啦! 另外, 如果您是以patch更新原始码,那么记得,您可能必须要重新编译,并且重新install才算成功更新喔! 并不是patch就好了! 因为patch的功能主要仅只是更新原始码档案而已! 切记切记 !

鸟哥提问题:如果我有一个很旧版的套件,这个套件已经更新到很新的版本,例如核心,那么我可以使用patch file 来更新吗?
这个问题挺有趣的,首先,您必须要确定旧版本与新版本之间『确实有释出patch file 』才行,以kernel 2.2.xx及2.4.xx来说,这两者基本上的架构已经不同了,所以两者间是无法以patch file来更新的。 不过, 2.4.xx与2.4.yy就可以更新了。 不过,因为kernel每次推出的patch档案都仅针对前一个版本而已,所以假设要由kernel 2.4.20升级到2.4.26 ,就必须要使用patch 2.4.21, 2.4.22, 2.4.23, 2.4 .24, 2.4.25, 2.4.26六个档案来『 依序更新 』才行喔! 当然,如果有朋友帮您比对过2.4.20与2.4.26 ,那您自然就可以使用该patch file来直接一次更新啰!


猜你喜欢

转载自hanxuedog.iteye.com/blog/1290448