http://community.itbbs.cn/showthread.php?t=14363
作者:
杜比环绕声

一、FreeBSD应用软件管理的基本原理:

1、FreeBSD应用系统的组成

FreeBSD应用系统由FreeBSD操作系统和移植(ports)到FreeBSD的各种应用软件组成

FreeBSD操作系统本身,是由内核和基本系统组成,基本系统由系统工具、系统库和文档组成,最小化安装选项安装的是内核、系统工具和系统库,系统工具 提供了完整的系统管理和编译程序程序。而文档和代码以及ports系统是可选安装的。如果完整安装了FreeBSD,简单的说就是安装了内核、系统管理工 具、系统库、编译程序、系统源代码、ports以及man、info、FreeBSD handbook等文档。

为了扩大FreeBSD的应用,FreeBSD移植(port)了大量的自由软件、开源软件。并构建了ports系统,把这些移植的软件汇集到一起,从移 植应用程序本身来说,大都是基于源代码进行修改和调整,以便建立的程序可以运行在FreeBSD系统环境下,所以ports中存放的都是代码修改以及编译 控制,以及FreeBSD的程序管理策略。
2、ports的组成

一个软件的ports,大致由以下几个部分组成:

pkg-descr 应用软件的简单描述
pkg-plist 软件安装的文件列表
distinfo 软件源代码的名称,版本以及校验信息
Makefile 控制软件编译的makefile
files目录 里面包含对源代码进行修改的各种补丁

利用port进行软件安装非常简单,这得益与ports系统的精心设计,大量繁琐的操作都定义在 /usr/ports/mk 目录下的文件当中,诸如一些变量定义,编译选项定义,文件下载地址定义,编译工具定义,以及一些操作的定义等等。具体软件的port中的Makefile 文件,都会继承系统提供的这些定义,而且可以根据需要进行调整。

具体软件port的Makefile还提供了软件运行依赖,建立依赖,以及对源代码编译过程中一些具体的定义。

3、利用ports进行软件安装的过程。

简单来说,可以用下面的指令来完成安装

代码:make install clean


具体的过程是:

根据distinfo文件中的软件源代码文件名,检测 /usr/ports/distfiles 目录下,是否有软件的源代码

如果没有,调用 make fetch 从Makefile文件中定义的下载地址进行下载

下载完成以后,调用 make checksum ,利用 distinfo 文件中的源代码文件的校验信息,校验源代码包的完整性。

如果校验正确,调用 make extract,对源代码进行解压,具体的路径是:

代码:软件port当前路径/work/源代码文件名去掉后面的.gz.bz2/


解压源代码后,调用 make patch ,搜索 files 目录下的补丁文件为源代码打补丁,

打完补丁,根据 Makefile文件中定义的软件运行依赖关系,查找系统中是否安装对应的软件,如果没有安装,会转入相应的软件的ports中进行make install clean 。假设当前应用程序的所有运行依赖都已经安装,ports系统会进入源代码目录,运行里面的configure文件,生成源代码目录下的makefile 文件,然后进行源代码的make过程,对源代码进行编译、连接。

当所有的make过程结束以后。运行ports系统的 make install进行安装。

安装完成以后,利用pkg-descr,pkg-plist的内容在 /var/db/pkg 目录下对这个软件进行注册。标记这个软件已经安装,并详细注册了安装文件列表。

如果软件注册成功,ports系统利用make clean命令,清除软件port当前目录下work子目录信息。如果在编译安装过程中对有依赖关系的软件进行过编译安装,会回溯清理过程。

4、FreeBSD提供的packages软件包


packages,也可以称作编译封装好的应用软件的二进制包,是FreeBSD提供的基于ports系统建立的二进制软件包,这个软件包实际上是 FreeBSD利用硬件资源,利用 ports 系统的 make package 命令建立的。这些package存放在 ftp.freebsd.org 服务器上,可以远程直接下载安装,也可以下载后进行安装。

以freebsd 7.0 release为例,它的二进制软件包网络地址是:

ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-7.0-release/

在这个网络目录下,有两个文件夹要用到,一个是 All ,一个是 Latest,注意第一个字母都是大写。

All目录下的文件,是利用ports建立的二进制软件包,例如 mysql51-server-5.1.22.tbz,软件包名称来自它的ports名,版本号是ports根据软件包源代码版本进行的定义。

Latest目录下的文件,其实是All目录下软件二进制包的软连接,并且省去了版本号,这个目录是 FreeBSD系统网络在线远程安装所要访问的目录,对于 mysql51-server-5.1.22.tbz 的软连接名是 mysql51-server.tbz。这样在远程安装时就省去了输入版本号的麻烦。

这两个目录的建立和维护也是由ports系统自动完成的,无需干预。

二、软件管理的一些细节:

FreeBSD操作系统可以使用ports管理应用软件,也可以利用FreeBSD系统提供的系统管理工具,提供对packages(二进制软件包)的管理维护。

1、软件安装

远程软件安装: pkg_add -r 软件包名称 例如:pkg_add -r mysql51-server,pkg_add -r xorg,pkg_add -r kde

系统会自动在上面所说的ftp服务器Latest目录下查找 mysql51-server.tbz,xorg.tbz,kde.tbz,但有一点需要注意,FreeBSD的ftp服务器并不保证ports上容纳的 所有的移植过来的软件都有二进制包,尤其是stable分支,有些是因为软件ports本身有问题无法建立,也有一些软件ports正在修订,还有一些只 允许源代码包发布,协议不允许进行打包。

本地软件安装: pkg_add 软件包文件名 ,用这种方式安装软件包,需要从All目录下载,防止软件安装时搜索特定版本的有依赖关系的软件包。

一个建议:利用pkg_add -r -K 这个命令,它的作用是,远程下载,安装,并且把下载的二进制包保存在 PKGDIR 定义的目录上。PKGDIR 默认的定义是 /usr/ports/packages/

使用ports安装软件的优势

利用ports进行软件安装,如第一部分所说,是利用make install 完成应用软件的安装。

利用ports进行软件安装与package安装相比,最大的优势是软件可定制,表现在在编译源代码时,通过选项定义来完成应用软件特定支持和模块建立的 特定需求。最常用的选项定义方法是在具体的ports目录下运行 make config。make config会显示出一个类似sysinstall风格的对话框,在里面可以显示和操作可选择的编译控制选项。(注意:有的port没有选项定义,运行 make config会显示“无选项”)。

这些ports的配置选项定义保存在/var目录下,可以使用 make showconfig 查看先前设定的配置选项定义。

如果需要对编译器的参数进行调整,可以采取两种方式,一个是在make 时定义特定的参数,如果需要全局改变,可以在make.conf中进行定义。无需改变ports系统本身!


2、已安装软件信息查询

很多时候,用户可能需要知道某个软件都安装了哪些文件,有时也需要查询具体的某个程序,某个库属于哪个软件。这些都可以使用pkg_info这个系统工具来完成。

数据基础是ports或package安装时在 /var/db/pkg 目录下建立的“数据库”(确切的说,我不知道如何称呼它),里面记录着软件名称,版本号,依赖关系,文件列表等等信息。是FreeBSD的软件管理数据中心。

两个应用:

pkg_info -L 软件全称(软件名和版本号,都可以在/var/db/pkg中找到),这个命令会列出这个软件在系统上的完整的文件列表。

pkg_info -W 文件名,文件名是当前路径,如果不是要指定绝对路径,这个命令返回的是当前指定的文件属于哪个应用软件。


3、软件的卸载

FreeBSD系统已安装软件的卸载,对windows用户来说,是个令人费解的事情。FreeBSD ports中的软件,大都来源与开源和自由软件社区,出于unix开发哲学中非常重要的一点——“轮子不该被制造两次”,所以每个程序都会大量的依赖其他 工具或者库的支持,这种事实存在的网状的依赖关系,造就了类unix系统软件管理上一个×××烦,特别是软件卸载。具体表现有两个:

a、完全卸载某个软件和它有依赖关系的软件、库不现实,也不能这样去做。这对热衷windows系统中造就的系统清理概念,以及有软件洁癖的人是无法忍受 的。但这也正是Unix哲学的一个具体体现,一个软件,一个库甚至一些头文件,都可以因为互相的依赖关系成为应用特定的一环。

b、很多时候,当你强制卸载了某个模块时,也会因为交错复杂的依赖关系造成其他软件受到影响,系统不会提示你缺什么软件库,而是告诉你缺少了哪个文件。这 样就会使对软件模块不太了解的用户很迷惑,一个相反的疑惑是我就安装了一个程序,可实际看到的是安装了好多,而卸载时却无法全部清除,这用windows 的惯性思维来想,也有些让人无法接受。

依赖对所有类unix系统来说,都是个问题。如果悉数依赖关系的种类,诸如建立依赖,运行依赖,库依赖等等,这更是一碗意大利面条。

FreeBSD的策略是从ports上就引入“依赖关系”的管理。具体也表现在packages上,都有特定的细节对依赖进行管理。

当你安装软件的时候,它会自动检查依赖,当它卸载软件的时候,会提供这个软件的依赖关系,让用户进行取舍。FreeBSD甚至提供了这样的一条命令。 pkg_delete -a ,卸载系统所有的应用软件,只保留FreeBSD基本系统和用户的配置文件。当然,如果某个程序完全不依赖其他模块或者从不为其他模块所依 赖,pkg_delete 会很利索的删除这个软件。因为它有登记软件安装时文件的详细列表。

说了这么多,其实只是一句话,使用FreeBSD的软件,对这些软件进行管理,就要抛却一些windows上的使用习惯,转而尊重FreeBSD以及所有 类unix的哲学和历史继承。更甚一点的说,在windows上,也是有依赖关系的,想完全删除所有依赖,可能会死的更惨。例如某某某系统文件。

FreeBSD的ports机制和package工具都提供了软件卸载功能

ports可以使用 make deinstall 进行反安装,packages使用pkg_delete进行卸载

需要注意一点的是,利用ports反安装,要注意ports软件和对应系统安装软件的版本号问题,ports的更新可能会带来很多问题,所以不推荐ports的反安装机制。建议使用 pkg_delete

pkg_delete 系统安装的软件登记名,这个删除会检查依赖,如果有依赖上的盘根错节,会进行提示!这些提示对进一步删除软件是不错的依据。

pkg_delete -f 系统安装的软件登记名, 这是强制删除,系统会删除指定模块的文件,但所有的依赖都不会进行操作,运行结束后会反馈可能出现的问题

pkg_delete -a 应用软件卸载的终极武器,犹如电影《西游记》中至尊宝的一句台词,”一刀斩下,哇,整个世界清净了“。。。。


4、进一步说“依赖”及软件打包

(depend)依赖,与windows下某个软件需要”运行库“支持比较类似。在FreeBSD和其他类unix系统中,“依赖”相比windows系 统要更复杂一些。使用过ports编译安装软件的人都有这样的经历,在实施编译一个软件包之前,系统都会进行一些检查,如果检测到缺少的组件,会嵌套的先 编译那些软件包。这其中就是“依赖”在起作用。

在FreeBSD中,一个软件包的依赖主要有两个

a、建立依赖:建立依赖指的是,这个软件包在编译时要用到的软件包列表,也就是软件包编译时需要的那些支持组件。例如编译kde,需要Qt的建立依赖,诸如此类!

b、运行依赖:一个软件包的运行依赖指的是软件包正常工作必须的软件环境,在FreeBSD上,就是一些软件包的集合。

FreeBSD的ports系统,把一个软件包的每个依赖都抽象成为一个具体的ports,例如编译Xorg需要的imake,kde需要的Qt,这些依 赖大多数定义在这个软件包的port上的Makefile文件当中,一个成熟、稳定的软件包port,它的所有依赖都已经由port的维护者定义好了。借 助于庞大的port组成的ports系统。一个FreeBSD用户在用ports编译某个软件时,无需为它的那些依赖操心费神。只要网络是通 的,ports系统可以全部搞定。

但这种省心,是建立在ports系统一致性基础上的,如果单独升级了某个port,而依赖没有升级到一致的版本,错误会千奇百怪。而且有一点需要注意,就 是ports系统是不断变化升级的,变化过程中有可能会出现各种各样的问题。解决这些问题最直接的方法是更新ports到最新版。间接一些的方法,可以给 ports维护者发邮件,抱怨一下自己遇到的错误,如果你遇到问题并且自己解决了,可以把解决办法提交到FreeBSD的ports维护者那 里,FreeBSD鼓励这样做!

ports系统中常用到的查看依赖关系的方法:

进入到某个你需要查看依赖关系的port,例如 /usr/ports/devel/qt4

代码:make build-depends-list #列出当前port的建立依赖

make run-depends-list #列出当前port的运行依赖

make all-depends-list #类出当前ports的所有依赖


package如何解决“依赖关系”:

上面提到过,package是利用ports生成的,为了解决packages方式安装的“依赖”问题,FreeBSD在.tbz的封包机制上,加入了“ 依赖”的软件包列表。观察一个.tbz软件包的组成可以很容易发现,在.tbz软件包内有“+CONTENTS”文件,这个文件的内容就是 这个软件的依赖的定义,还有诸如一些安装时校验软件包的校验信息,以及一些其他信息!当用户使用pkg_add 安装package时,系统会根据这个文件的内容首先对依赖进行检测和安装,当所有依赖安装就绪之后,才安装当前软件!这是一个基本保证,但这些都可以灵 活定制。

FreeBSD本身提供了打包工具,pkg_create,ports中的package也是利用了这个工具程序。相比较来说,使用ports打包不需记住相当多的参数,所以相对容易。

利用ports系统进行打包的方法:

进入到需要打包软件的port

代码:make package #单个软件打包

make package-recursive #打包当前目录的软件,并且打包与这个软件有依赖关系的软件包

make package-depends-list # 查看与当前软件包有依赖关系的package列表

actual-package-depends # 查看与当前包有依赖关系的package列表,与上面的命令不同的是,它的包列表是基于已经安装的


注意:用上面命令进行打包 时,推荐建立 /usr/ports/packages 目录,ports系统在打包时会检测这个目录是否存在,如果存在,ports系统会在这个目录下建立 All、Latest以及ports各个分类目录,All目录下是实体文件,其他目录的文件都是连接到All目录下的文件。文件树结构和 ftp.freebsd.org服务器上的packages目录的组成是一样的。 如果ports系统没有检测到 /usr/ports/packages 这个目录,所建立的package包只能保存在相应port的目录下!