经验 |
Eric Steven Raymond
Thyrsus Enterprises
esr@thyrsus.com
陶品 taopin@gnuchina.org
梁昌泰 linuxrat@gnuchina.org
Copyright ? 2000 by Eric S. Raymond
Abstract
本文档详细说明了如何发布一个Linux系统下的自由软件项目。依据这些说明,您就可以让用户非常容易的编译并使用您的代码,同时也可以让其他热心的开发人员很容易读懂您的代码并参与到您的项目中来,并优化、改进她。
本文档对与开发者来说应该算作是一本必读教材。即使是有经验的程序员在发布他们的软件时也需要温习一下本文档。另外本文档会定期修订以反映软件发布实践中更好的做法。
--------------------------------------------------------------------------------
Table of Contents
简介
优秀项目─档案─的命名惯例
选择一个好的许可证和版权说明︰理论篇
选择好的许可证和版权︰实践篇
好的开发习惯
制作项目发布包的好经验
好的文档编写惯例
好的沟通方式
好的项目管理经验
本文档的由来
历史上已经有大量的发布开放源码项目的好传统存在,这些惯例使得人们可以更为方便地移植、使用或者直接加入项目的开发。许多这些传统都来源于原来的UNIX世界和早期的Linux社区中﹔还有一些则是最近随着新开发工具和技术的出现(如WWW)才应运而生的。
本文档就是帮助您学习这些惯例的。我们将分主题讲述所有要点。一个好的自由软件开发者应该在发布他的软件之前把这些要点都捋一遍才好。
如何获得本说明更新的版本
本文将每隔一个月在comp.os.linux.answers 新闻组中更新一次。您还可以从互联网上获得这份HOWTO文档的最新版本,具体地址(URL)是: http://www.linuxdoc.org/LDP/HOWTO/Software-Release-Practice.html.
如果您对本文档有什么建议和问题,请尽管给Eric S. Raymond写Email,地址是 。
由于档案维护者的工作量不断增大,许多站点如:Metalab, PSA 和 CPAN 都存在这种情况。因此趋势是许多工作将会由程序来自动完成,而不是全部由人手工去做。
这种情况就使得项目和文档名称规范化工作变得越来越重要,规范的命名可以让程序更容易地识别和获得文档所包含的信息。
用GNU风格的命名习惯,档案名加主版本号.辅版本号.补丁编号
让档案名称符合GNU命名规则是一个礼人利己的事情,GNU的命名规则是:以所有字母都小写的主名称作为前缀,后跟一个破折号,再跟一个版本号,扩展说明,以及其他后缀。
我们举例说明如下:假定您有一个项目叫做“foobar”,现在她的进展状况是第一版、第二次发布、第三补丁。如果她只有一个档案包(可能就是所有的源码), 那么她的名称应该是:
foobar-1.2.3.tar.gz
源代码档案包
foobar.lsm
LSM文件(如果您需要将这个项目提交到Metalab上,则需要这个LSM文件)。
请千万不要把名字起成下面的样子:
foobar123.tar.gz
(这会让人误解为是一个名为“foobar123”的项目)
foobar1.2.3.tar.gz
(这会让人误解为是一个名为“foobar1”项目的第2.3版)
foobar-v1.2.3.tar.gz
(许多处理程序将会把她理解为名为“foobar-v1”的项目)
foo_bar-1.2.3.tar.gz
(下划线读起来即不上口,也不容易让别人输入和记住)
FooBar-1.2.3.tar.gz
除非您乐意被看成是市井小人,否则就不要这么写。因为这种写法同样不易读、输入和记忆。
如果您想对源代码包和二进制包有所区别,或者想区分不同类型的二进制包、由不同编译选项编译出来的二进制包,请在文件名的“扩展说明”部分来表示那些信息,扩展说明紧跟在版本号之后。也就是说您可以这样起名字:
foobar-1.2.3.src.tar.gz
(表示源代码包)
foobar-1.2.3.bin.tar.gz
(表示二进制包,但不确定具体类型)
foobar-1.2.3.bin.ELF.tar.gz
(表示ELF格式的二进制包)
foobar-1.2.3.bin.ELF.static.tar.gz
(表示静态链接库的ELF格式二进制包)
foobar-1.2.3.bin.SPARC.tar.gz
(表示SPACE格式的二进制包)
千万不要使用“foobar-ELF-1.2.3.tar.gz”这种格式的名称,因为处理程序对“-ELF” 这样的中缀将难以解释。
一个好的名称将按顺序包含以下几项:
项目名称前缀
破折号
版本号
点
“src”或“bin”标记(可选)
点或者破折号(建议使用点)
二进制格式和选项(可选)
归档和压缩后缀
有时候也还要尊重一些在局部范围内流行的惯例
在有些个别项目或社区中还存在着与上面命名规则并不完全一致的,同时又是定义的非常好的他们自己的命名规则。比如Apache的模块通常就采用“mod_foo” 那样的命名方式,而且模块名中还会既包含模块的版本号又包含模块可工作的 Apache的版本号。同样,Perl模块在版本号中还有形如浮点数那样的表示方式(如1.303,而不是1.3.3),所以Perl 1.303版的模块Foo:Bar的发行包一般会被命名为Foo-Bar-1.303.tar.gz。(顺便说一句,Perl项目本身在1999年末已经采用了本文前面所介绍的GNU标准命名方法)。
一方面我们要寻找并尊重那些特殊社区和开发者的特殊命名习惯﹔同时对于大部分其他的项目,我们建议大家按照以上的标准命名规则来进行。
尽量找一个独一无二并且又很容易输入的项目名称(前缀)
项目的主名称应该可以通用于整个项目中的其他文件,同时最好她既好读又好写(输入),还容易让人记住。所以建议您在没有充足理由的时候最好不要用下划线,不要使用大写字母或部分的字母大写。那些垃圾字符会污染人类的阅读习惯,干扰人们的搜索顺序,而且这看起来有点象是市井之徒在耍小聪明。
当两个不同的项目使用同样的主名称时就会产生混淆。所以最好在您第一次发布您的项目的时候就能避免这种冲突。有两个网站上的名称统计列表可以帮助您检查是否冲突,他们是Metalab索引文件(http://www.ibiblio.org/pub/Linux)和Freshmeat附录(http://www.freshmeat.net)。另外还有一个好地方是:SourceForge (http://www.sourceforge.net),在这些地方您可以做一点名称检查的工作。
许可证的选择实际上是为您自己选择一个您与其他开发者以及用户之间的社会契约。给软件附加版权说明实际上是使得给您创作的软件和其衍生产品加上许可证的行为合法化。
开源与版权
任何非公共的东西几乎都有版权,有的甚至还有不止一个版权。根据伯尔尼公约(1978年成为了联邦的法律),版权并不必显式地声明。也就是说,即使没有给出版权声明,一部作品的作者仍然是持有版权的。
如何确定谁是某个东西的版权所有者是非常困难的,特别是在软件行业,因为有时候软件是许多人共同编写出来的。这也就是为什么许可证在软件发布中非常重要的原因。通过设定一些指出在何种情况下可以使用的条款,许可证授予用户权利并保证用户免受版权所有者各种行为对他们造成的伤害。
在私有软件领域,许可证条款总是被设计成保护版权所有者。这是一种只给用户少得可怜的权利的做法,然而这种做法却保留尽可能多的合法权利给版权所有者。版权所有人非常关键,而且许可证的逻辑是如此严密以至于那些条款中的技术上精确已经都不重要了。
相反,开源软件领域,则是另一番景象﹔在这里版权是用来保护许可证的。版权所有者唯一的权利就是确保许可证的落实。如果不这样的话,将只有很少的权利得到保留而让用户面临更多的取舍。特别是版权所有者自己也不能对您已经拥有的副本更改任何许可证条款。因此,在开源软件领域,版权所有者的作用要小的多而许可证条款显得更为重要。
通常一个项目的版权所有者就是该项目的首席开发人员或发起组织。项目的首席开发员易人一般就意味着版权所有者发生了变化。不过这并不是一个严格的规则,许多自由软件项目有着多个版权所有人,这种领导模式至今还没有出现任何法律问题。
许多项目选择让自由软件基金会作为版权所有者,理论上来说这样更有利于开源软件受到保护并让专业的律师来处理各种法律问题。
怎样才有资格被称为开源软件
根据许可的目的,我们可以区别许可证赋予您的各种不同权利。复制和再发布 的权利,使用的权利,为个人目的修改的权利, 发布修改后的作品的权利。一个许可证可能会对这些权利加上一些限制或给出一些附加条件。
开源原动力站点(http://www.opensource.org)就是各种对软件“开源”或 “自由”思考的结果。该站点许可证的约束条款包括:
无限制的拷贝权
无限制的使用权
无限制的针对个人使用目的而修改的权利
这些指导方针保证修改后的二进制代码的再发布权﹔这与那些要求可以无障碍的取用软件的发行商的需求相吻合。这个做法使得软件的作者们可以要求修改的原始源代码采取把原有代码加上补丁程序的方式来再发布,这样就保全了作者们的原意同时又可以让他们“审查”其他人对项目的改进工作。
OSD(开放源代码定义)是对“OSI开源软件认证”证书的法律定义,实际上她和人们曾经提出的各种关于“自由软件”的定义一样好。所有标准的许可证协议(如MIT、BSD、Artistic、GPL和LGPL协议)都与该提法一致(然而有时候,比如GPL,有更多的限制条款,在选择这些许可证时请仔细理解)。
值得注意的是有些只允许非商业用途的许可证并没有资格被称为开源许可证,尽管他们标榜自己是“GPL”或者其他典型的许可证。这种许可证对特殊的拥有者,或者对个人和小组有着歧视。他们对通过光盘渠道再发布的做法以及其他商业化的推广开源软件的尝试做出种种限制,从而把事情搞的非常复杂。
本节将告诉您如何将上节介绍的理论转化为实际的行动。
让您自己或者自由软件基金会成为软件的版权所有者
有些情况下,如果您和您的项目背后有一个有法律专家的组织支持,您可能更愿意将版权授予那个组织。
采用遵照开源定义的许可证
开源软件的定义(OSD)是许可证的公共标准。OSD本身并不是一个许可证﹔而是给出了某个许可证要想成为开源许可证所必须包含的一个最小集合。 OSD和其他辅助资源可以从开源原动力站点获得。
如果没有特别的需要,最好不要自搞一套许可证
广为人知的OSD规范许可证有着相对固定的解释惯例。开发人员(甚至用户)已经了解这些许可证的真正内涵,合理的协调了各种风险和所需的代价。因此,在各种的情况下最好采用开源原动力站点上的某一许可证即可。
如果您非要制作您自己的许可证协议,最好将这个许可证提交给开源原动力站点,让他们帮您把把关。这样可以省去日后不少争论和其他开销。如果没有认真考虑过,您很难想象一个在许可证方面发生的争吵所带来的后果是多么糟糕,由于许可证这种神圣盟约是开源软件价值体系中的核心问题,人们多半会在这个问题上反目为仇。
此外,如果某个许可证已经在法庭上经过了考验,将证实这个许可证所建立的解释惯例是重要和合适的。不过截至本文编撰的时候(2000年中期),还没有任何开源许可证有着被支持或者被驳倒地法律案例。一般法庭应该会根据制定许可证的发起组织的期望和实践来解释那些许可证和契约,这几乎是一定的(至少在美国以及其他有着类似法律的英联邦国家是这样)。
本章节主要内容侧重于确保程序的可移植性,这不仅限于各种Linux系统,而且也针对各种UNIX系统。对其他UNIX系统保持可移植性并非是故意卖弄技术或者是遵守黑客的礼节,而是一种保持未来Linux自身发展不分裂的保障手段。
另外,如果其他人正在试图将您的项目移植到其他非Linux系统上,一个可移植性好的项目可以让您最大限度的避开各种烦人的Email质询。
写标准的ANSI C程序或者可移植的脚本程序
要有可移植性和稳定性,您最好只用ANSI C写程序,要不就用某种脚本语言,这样能够保持可移植性的原因是他们底层的实现对于不同平台是一致的。
有资格被成为跨平台的脚本语言包括 Python、Perl、Tcl、Emacs Lisp 和 PHP。普通的老式Shell则不具有好的可移植性﹔因为他们在不同平台上的实现有许多细微的语法差别,而且Shell的外壳环境极易受到用户个性化设置(如alias设置)的干扰。
遵守C程序的可移植惯例
如果您用C写程序,请记住一定要完全遵从ANSI标准──包括函数原型,这样可以帮助您去掉跨平台模块的不一致性。老的K&R编译器已经成为了历史。
另外,不要认为一些GCC特有的特征,比如“-pipe”编译选项以及嵌套函数等,在所有平台上都有效。因为这样的选项会在其他人试图将项目移植到非Linux、非GCC系统上时起作用并被“咬”一口。
使用autoconf/automake/autoheader工具
如果用C写程序,记住一定要用autoconf/automake/autoheader工具来处理各种移植性的问题,用这些工具完成系统配置信息的收集,创建makefile文件。现在许多人在打算编译源码时只希望通过“configure; make”这样简单的命令就可以得到干净利落的编译,事实上大家就是这么干的。
发布前要仔细地检查代码
如果是用C写程序,至少在每次发布之前要记得用 -Wall 编译选项重新编译一遍并去除编译中遇到的任何错误。这么做可以帮助您发现不少没有想到的错误。要是想更彻底的检查,那就用 -pedantic 选项再编译一遍。
如果是用Perl,请使用perl -c(如果可行,有可能还有-T)来检查您的代码。请坚定不移地使用perl -w和"use strict"。(请详见Perl文档。)
发布前要仔细地检查文档和README等文件
文档发布前最好用拼写检查工具查一遍。如果您看起来没有能力拼写正确,而且也不关心文档的错别字,那么其他人很自然地联想到您的代码是否也同样是乱七八糟和粗心大意呢?
这一章节主要介绍您发布的项目应该具有什么样的形式,以方便其他人下载、检索和解压。
确保tar包解压时会创建一个独立的新目录
新手常犯的低级错误是制作了一个解压后把文件和目录直接解压在当前工作目录的tar包,这样做潜在的危险是会把原来已有的同名文件覆盖掉。记住, 千万不要这么干!
而正确的方法是:您的项目的所有档案都是存放在项目所在目录下的标准目录结构中,这样tar包就可以解压在一个特定的目录下而不是当前目录。
这里有一个Makefile文件的技巧示例展示了如何完成打包工作,这里假定您的项目所在目录名称为“foobar”,而SRC变量中是一个包含所有需要发布的文件列表:
foobar-$(VERS).tar.gz:
@ls $(SRC) | sed s:^:foobar-$(VERS)/: >MANIFEST
@(cd ..; ln -s foobar foobar-$(VERS))
(cd ..; tar -czvf foobar/foobar-$(VERS).tar.gz `cat foobar/MANIFEST`)
@(cd ..; rm foobar-$(VERS))
编写README文件
应该有一个名为README或者READ.ME的文件来说明整个源码的结构信息。古老的传统告诉我们,勇猛的探索者在解开您的压缩文件包后的第一件事情就是找出README文件来阅读。
README文件中最好应该包括如下信息:
整个项目的简介
项目的WWW站点所在的URL(如果有的话)
指出开发者编译整个项目所在的系统环境,并指出项目可能潜在的移植性问题
重要文件和子目录的结构信息
编译/安装步骤说明,或者指明这些信息所在的文件名(通常是INSTALL文件)
项目主持人和参与者的名单列表,或者指出这些信息所在的文件(通常是CREDITS文件)
最近关于本项目的一些进展情况和新闻,或者指出包含此信息的文件(通常是NEWS文件)
遵照标准文件命名规则
“勇猛的探索者”要想阅读README文件,他们就必须首先浏览解压后项目档案所在的根目录下的文件名。这些文件名本身就在向读者传达着许多信息。如果您遵照标准的命名规则就可以给那些探索者有价值得线索以便他们更好的理解您的意图。
这里列出了一些标准文件名称和他们的涵义。当然并不是所有项目发布时都必须包含所有这些文件。
README或READ.ME
整个项目的结构信息说明,第一个需要阅读的文件。
INSTALL
配置、编译和安装该项目的说明信息
CREDITS
本项目所有贡献者的列表
NEWS
本项目最近的一些新闻和进展状况
HISTORY
本项目的历史发展演变记录
COPYING
指出本项目采用的许可证条款(通常采用GNU GPL)
LICENSE
本项目的许可证条款文件
MANIFEST
本项目的所有文件列表
FAQ
关于本项目的纯文本格式的常见问题解答
TAGS
为Emacs或vi准备的tag标记文件
我们可以看出来,全部大写的文件名一般表示该文件是给人阅读的文档,而不是项目的一个组成部分。
编撰一个FAQ文件可以帮您很多忙。如果某个问题经常被其他人问起,就把这个问题列入FAQ文件﹔然后指导用户在向您发文或提交出错报告前首先阅读FAQ文件。一份好的FAQ文件可以给项目维护者减轻好几个数量级的负担。
另外在每次发布时都保留一个HISTORY文件和NEWS文件,并列明时间信息的做法是非常有好处的。在所有其他文件中,这两个文件可以让您在遇到一些专利侵权法律问题时有所准备(虽然这种情况至今还没有发生过,不过最好还是有备无患)。
为项目升级做好准备
只要您打算为您的项目发布新版本,项目就必定处在不断的变化之中。有些变化是不能向前兼容的。因此您必须认真思考安装程序设计上的问题,就是说让同一项目的不同版本的代码安装后可以共存在一个系统中。这个问题对库项目的发布尤为重要,因为您不能指望所有基于这个库的应用程序都会紧跟您的API接口规范的后尘。
Emacs、Python和Qt项目有一套对付这个问题的好办法,就是让目录名中包含版本号。这里有Qt库安装后的目录结构的例子(${ver}是代表版本号的变量):
/usr/lib/qt
/usr/lib/qt-${ver}
/usr/lib/qt-${ver}/bin # moc程序所在目录
/usr/lib/qt-${ver}/lib # .so共享库所在目录
/usr/lib/qt-${ver}/include # 头文件所在目录
这样组织目录结构可以让多个不同版本的档案共存。客户程序可以根据需要选用具有特定版本号的库,因此为了不让这些接口影响客户程序,还是需要付出一些小小代价(制定版本号)的。
提供RPM包
安装可执行文件包(二进制包)的事实标准就是使用RedHat包管理器将可执行文件打包成 rpm 包。许多流行的GNU/Linux发行版都是这么做的,同时也有许多发行版虽然主要不是rpm包格式但是也支持rpm包(除了Debian和 Slackware以外,而且Debian还支持rpm的安装)。
因此一个好的项目除了有tar包的源代码以外,最好也提供直接可安装的rpm 包的下载。
如果您能把您的源代码tar包和Makefile文件中用于生成rpm包的相关信息写入rpm的spec文件中就再好不过了。spec文件是有着".spec"后缀的文件,这就是带 -t 选项的 rpm 命令如何在 tar 包中寻找它的方法。
还有一个要点是,您可以用一个脚本程序自动的从Makefile或version.h 文件中找出版本号,并用这个版本号来生成您的spec文件。
注:如果您还打算提供源码的rpm包,最好用BuildRoot工具来将程序编译到/tmp或者/var/tmp目录中。如果不这么做,在安装过程中执行 make install命令时就会直接将那些源程序直接安装到最终的目录位置下。这样就会导致即使在发生文件覆盖冲突,或者您本意并不想装那个包的时候,安装动作依然被执行。因此安装完成后,文件是被装到了系统中,但是系统的RPM数据库却并没有记录这些信息。这种愚蠢的SRPM安装动作是非常危险的,理应避免。
最重要的文档编写惯例就是多写一些!很多程序员都轻视这些事情。但是下面两个理由可以让您明白您必须去做文档工作:
文档可以指导您的实践。 写文档的最佳时机是在您一行代码还没有编写时就应该开始,此时您需要想想您打算做点什么。您会发现用自然语言思考程序应该完成什么功能可以促使您从更高的层次考虑软件是什么样以及她该如何工作。这种思考可以节省许多以后的时间。
文档是代码的招牌。 许多程序员为他们的程序只提供了少的可怜、内容匮乏、语言差劲的蹩脚文档,这实际上等于向其他人展示说,写这个文档的程序员对潜在用户的需求也同样会粗心大意、马马虎虎。相反,好的文档则会向其他人传达出文档背后的程序员是非常聪明、专业的人。如果有一些类似的项目正在与您的竞争,一定要写出好的文档来,至少不能让潜在用户瞥了两眼您的文档后就立即否定您的项目。
这份文档虽然着眼于文档编写实践,但并不是一份专门介绍如何写出好文档的详细讲义。因此下面我们将重点介绍文档格式和编写工具的选取。
虽然开源社区长期的传统就是拥有强大的文档格式化工具,但是为数众多的文档格式仍然使得整个系统的文档支离破碎,很难用一种统一的方法全局检索和阅读文档。下面我们将先介绍各种流行的文档格式的用途以及他们的优劣,然后再给出一些编写好文档的建议。
现行的一些好的做法
这里将列出一些在开源软件开发群体中流行的一些文档格式。当我们文中提到“展示”标记,就是指那些控制文档显示的标记(如字体)。当我们提到“结构”标记,就是指那些描述文档结构的标记(如段落、强调标记)。当我们提到“索引化”,则是指从众多文档中萃取出可检索的关键字集合的过程,“索引化”可以帮助用户在整个文档中可靠的找出自己感兴趣的资料。
man手册页
这是最普通的文档格式,来源于UNIX系统,是一种原始的“展示”标记格式。 man(1)命令提供了页显示和原始的搜索手段。这种格式不支持图象、超链接和“索引化”功能。不过这种格式转化成Postscript进行打印的效果还不错,就是转成HTML格式不太方便(主要是纯文本)。man 的相关工具在各个Linux 系统中几乎都有。
手册页格式做为命令用法解释或者短小的参考文档还是不错的,对一个有经验的用户这样做可以非常节省内存。那些有着复杂用户界面和很多选项的程序会让系统负载非常重,如果交叉链接太多的文档甚至会让整个系统不堪重负。(Man手册格式不支持超文本链接)。
HTML文档
自从1993-1994年互联网流行起来后,HTML标记格式开始流行,这种标记格式有一定的结构,也便于“展示”,还可通过网络浏览器浏览,对图象和超级链接也有支持。不过自带的“索引化”功能很有限,因此搜索引擎技术得到了大力的发展。这种格式也可以很好的被打印出来,相关的制作工具数不胜数。
HTML标记语言非常灵活,非常适用于各种文档。实际上她太灵活了,甚至可以展示Man手册页格式的信息。不过问题在于她很难自动检索,因为这种格式中太多的标记被用于描述“展示”信息,而鲜有标记描述文档的结构。
Texinfo文档
Texinfo格式是自由软件基金会推荐使用的格式。她是在强大的Tex格式引擎上建立的一套宏。拥有许多结构信息和部分表示信息。可以用Emacs浏览,或者用专门的info程序阅读。这个格式支持超级链接,但是不支持图象﹔无论是打印出来还是在线阅读都可以很好的“索引化”﹔如果您装了某个 Texinfo格式的文档,该文档的信息就被整合到系统的全局目录表中。这种格式还可以很好的被转换为Postscript格式和HTML格式,相关工具在大多数 Linux系统中都是预先安装好的,当然您也可以从自由软件基金会的网站上下载(http://www.gnu.org)。
Texinfo有着很好的设计,非常适合于完全字符编排的书籍和小的在线文档,但是和HTML格式一样,她也是一种两栖格式──既有表示“结构”的标记,又有表示“展示”的标记,“展示”标记给文档进一步处理带来了一些麻烦。
DocBook格式
DocBook是一种强大且精巧的基于SGML(当前XML的前身)的标记格式。和前面几种文档结构不同,这个标记格式只包含“结构”信息,而没有“展示”信息。她可以很好的支持图片和超级链接﹔支持“索引化”﹔很易于转换成HTML格式和便于打印的Postscript格式(而且随着工具功能的增强,打印效果还可进一步提高)。该格式的文档和相关工具可以从DocBook的网站(http://www.docbook.org)下载。
DocBook在处理大而复杂的文档中表现出众﹔她被特意设计成可以支持各种技术文档并可以将他们用不同的输出格式“展示”出来。不过她的回溯功能非常复杂,工具也没有完全发展成熟(虽然进步很快),入门级的文档非常少而且常常写得很混乱。
也许未来会有些更好的做法
2000年7月,世界一些重要的开放源码项目开发组(包括GNOME、KDE、自由软件基金会、Linux文档项目组、开源首创)在加州Monterey举行了高级首脑会议。该次会议的重要议题就是试图建立一套共同的工作惯例和共同的文档交流格式,以便为自由软件制作出更丰富、更统一的文档资源。
具体的来说,会议的目标就是要制定一种文档包的标准,使得当某文档被装入系统中后,文档包就立即被集成到整个系统的搜索数据库中,系统可以通过某种一致的手段查找、搜索各种文档。实际上GNOME和KDE组已经开始在朝这个方向努力了,大家都明白这并非是一种标记语言就可以解决的问题,而需要建立一套结构化的系统体系。
会议签署了一个意向文件,清晰的指出一些关键的开源项目正在着手或者已经采纳使用Docbook格式做为项目文档的首选格式。
与会者最后也决定了采用“Dublin core”元数据格式(一种根据库管理程序开发的与数字资料索引有关地国际标准)做为文档搜索的标准,这个标准的细节正在制定中,因此最终DocBook标记中会添加一些信息用于支持嵌入DocBook文档的Dublin Core元数据。
目标是明确的,基于索引标记和Dublin core元数据可以提高DocBook文档的自动搜索能力,从而使得DocBook的用途如虎添翼。虽然还有一些工作尚未完成,但是它们将会被不断填充进整个体系中。老的基于描述的标记语言文档所剩下的日子已经不多了。(本文档在2000年8月已经有了DocBook格式的版本。)
因此新的开源项目应该注意这种动向,如果现在就采用DocBook格式的文档编写,这可以帮助他们省去以后将文档格式转档的麻烦。
如果除了您自己之外没有人知道您辛苦开发出来的程序,那么您的程序就不会对这个世界带来太大的用处。因此,在互联网上充分的展示您的项目可以帮助您获得用户的支持,还可以找到志同道合的开发人员的参与。下面是一些常用的与其他人沟通的做法。
在c.o.l.a和Freshmeat上公布
在comp.os.linux.announce 新闻组对您的项目发布公告。这个新闻组除了有大量的阅读群外,她也是许多其它站点,比如Freshmeat,公布新消息的地方。
在相关主题新闻组中公布
在USENET中找到一个与您项目密切相关的讨论组,并在那里发布您的项目也是一个极好的方式。需要注意的是只能在与您项目相关的地方公布,并且不要灌水。
比如,当您用Perl写了一个查询IMAP服务器的程序,您可以在comp.mail.imap 新闻组公布。但如果这个程序并非是一个反映Perl最新技术的例子的话,就没有必要把这个消息公布在comp.lang.perl新闻组上了。
另外,您的帖子中应该包含您的项目网站所在的URL地址。
建一个与项目相关的网站
如果您想围绕项目建立一个用户、开发者的网上社区的话,最好应该建一个网站。一个标准的项目网站一般包括如下内容:
项目的特点(为何要有这个项目,谁会对此项目感兴趣)。
下载项目源代码的地方。
指明如何加入项目相关的邮件列表。
一个常见问题解答列表。
HTML格式的项目文档。
与项目相关或竞争的其他项目或网站的链接。
有的项目站点甚至还有指向源码结构树的匿名访问链接(便于跟踪项目进展)。
维护一个项目相关邮件列表
维护一个项目开发专用的邮件列表几乎是必须的,透过这个邮件列表项目的合作开发者可以互相交流并讨论对程序补丁的建议。您最好再建立一个让其他人及时获知项目进展状况的公告邮件列表。
比如您的项目名称为“foo”,那么开发邮件列表就可以命名为 foo-dev 或者 foo-friends,公告邮件列表就可以命名为 foo-announce。
在各大主要项目库站点中发布
在过去的几年中,Metalab集中营(http://www.metalab.unc.edu/pub/Linux)成为了Linux各种软件集散的最重要的站点。
自1999年秋建立以来,SourceForge 也获得了爆炸性的发展。这个站点并非只是一个简单的资料与发行版的汇集之处,虽然很多人都认为就是那样。这个站点更是一个为自由软件项目提供一整套开发环境的虚拟主机,包括针对项目提供硬盘空间、网络访问服务、邮件列表服务、错误跟踪、聊天室、CVS管理等各种服务。
还有其他一些重要的网站是:
Python站点(http://www.python.org) (针对所有用Python写的程序)。
CPAN(http://www.perl.com/),综合Perl资料网。(针对所有用Perl写的程序)。
由于参与者都是志愿加入某一项目的,因此要想组织好一个自由软件项目的实施必然面临许多独特的挑战。这是一个非常大的话题,在这份HOWTO文档里还难以说清。幸运的是,许多有价值的论述已经指出了这其中的关键问题,相信他们会给您带来帮助。
关于基本开发模式的讨论和对“早发布常发布”的集市开发模式的论述请参考《大教堂和集市》一文。
关于心理动机、社群习俗和化解各种冲突的讨论请参阅《开拓智域》一文。
关于开源软件经济学基础和各种商业运作模式的讨论请阅读 《魔法大锅炉》一文。
需要指出的是这些文章并非自由软件开发的终极论断,不过他们都是经过深思熟虑后的思想结晶,还没有其他文章超越了他们的深度(文章的作者非常希望未来某一天有人超越他们)。
这篇文章分析自由软件项目的常用实施工具和方法流程,以及已有的成熟建议,但不是从技术角度介绍软件使用方法(读者可以在“joyfire linux笔记”的其他部分或者joyfire.net找到有关技术的资料)。本文要讨论的更接近法律、文化以及社团传统。我不会探讨常见的自由软件理念和纯粹的哲学问题,这方面已有很多经典作品,例如Eric S. Raymond的五部曲。
这篇文章是提供一些自由软件项目实施的经验和建议,合适的读者应该是已经对自由软件熟悉并感兴趣,认同自由软件理念,希望在这中间做点什么的人。换句话说,不是“Why”和“What”,而是“HOW”。
在航行之前要考虑清楚自己的目标和能力,做好充分的准备,然后,就是勇气和耐心了。Lucky!
1.平台
GNU首先是指GNU项目的各种软件,以及由它们组成的软件环境或者平台,例如linux、bash、gcc等等。
显然,如果新的自由软件可以建立在以前的自由软件的基础上,或者和众多其他自由软件相互支持,那么无疑会增加成功的机会。同时相似的自由软件的环境也有利于宣传和改进。当然,没有必要一定采用哪种环境,但是因为很多系统基本工具本身就不是开源的(open source),所以会出现问题。例如Windows平台下的很多编译工具,API和COM控件,也许是免费的,但是它是专有的,不允许自由修改和二次发布。
举个例子,Win32 API是Windows平台下最基本的API,在一般情况下,它的确是可以无条件使用的。如果你的程序仅仅是应用(Application),那么没有问题,你使用的仅仅是Win32 API的“界面”。但是如果你的程序是一个编译器或者类似的东西,你就必须得到微软的许可,因为严格讲,你已经把Win32重新包装发布了。由于这样的原因,VC的竞争对手,例如著名的编程工具Delphi,要把Win32 API包装到自己的类库,就得支付使用费用,而且无法调用很多Windows操作系统默认的对话框(例如“打开对话框”“存储对话框”“查询对话框”),必须在类库里重新实现一遍,这就是Delphi生成的可执行程序比同类VC的要稍微大几十K的原因。这是微不足道的损失,但是这种专有形式的阻碍可能会对你的软件性能产生障碍。
当然,在MS Windows和其他非自由的平台下同样拥有很多优秀的自由软件。只是这需要你更加小心,避免在技术上或者法律上进入尴尬境地。
2.GPL协议
GNU重要的核心就是GPL协议,它是自由软件的法律基础。接受这个惯例,是标明自己open source的立场的最直接方法。这份文件的作者已经为自由软件体系建立了一套完备逻辑的法律体系,可以使一个自由软件在保证自己“free”(注意,这个词是双关的,即表示自由,又表示免费)的初衷不会被其他人因为私人利益而改变,又可以保护大多数的用户可以不受限制的充分使用,甚至可以通过保护一种游戏规则保护以发布自由软件赚钱的软件商的利益。
这个协议形成的版权系统(copyleft)和普通的私有软件版权协议(copyright)是完全不同的,如果你一但在前人的基础上开发,就必须公开源代码,否则你就失去了使用前人代码的资格,这是递归的过程.至于对程序收费,GPL没有禁止,但是公开代码本身就决定发布者不能把价格定的太高(你的竞争对手可以重新编译你发布的源代码然后比你更低价出售,只要它对自己的修改公开源代码,就不违法)。
现存的linux或者自由软件商业模式都是建立在提供服务上的,也就是替企业制作特别的解决方案,或者为硬件厂商开发特殊的版本。例如为手持设备厂家开发嵌入系统,为工业控制设计工控系统,或者为企业提供咨询服务。这种工作的客户就要求源代码的控制权。MS也对自己的大的特殊客户提供有限的共享代码服务。但是他们的软件对企业级用户限制太多了。
自由软件是一种信仰,更是一种商业潮流,是利益而不是其他使IBM等企业强力支持Linux,因为他们本来就不是靠release赚钱,他们的核心都是对用户的服务。建议阅读Eric S. Raymond五部曲最后的The Magic Cauldron,生动描述了这种商业模式怎样占领几十亿美元的IT市场的。
要说明两点。首先,不只GPL一种自由软件发布协议,很多著名的自由软件,例如Apache、X系统等,都采用自己的独特的自由软件发布协议,当然具体条款的约束是不同的,例如X就很松(允许使用者修改源代码但是不公布,把这变成自己的私有财产),而Apache就比较民主(它的社团通过投票决定下一版本的工作)。其次,不要把自由软件和盗版联系起来,自由软件和私有软件仅仅是两种不同法律体系、世界观和商业模式,Gates和Linus都是值得尊敬的知识英雄(当然,你可以对某人有自己的看法,实际上我也有,但不管怎么说,他的成功不该被贬低,尤其是很多非议夹杂着个人潜意识里的嫉妒)。而盗版,就是剽窃。不管无知之辈如何把盗版和Free相提并论(一般还会加上对MS的种种攻击),盗版不符合Free精神,就好象把偷窃和共产主义并列一样滑稽。
CVS,顾名思义,是个可以用在小组协作环境下的源码版本管理系统。同类的软件有AT&T的SCCS(Source Code Control System),还有PVCS等。在OpenSource项目里CVS用得最为广泛, Linux kernel不使用CVS来维护,但是包括FreeBSD操作系统在内的很多自由软件源码管理都是由它完成的。
现代软件的产生已经不是手工作坊式的了,软件工程、项目管理一类的工具是必然的东西,可是对于自由软件这种通过网络志愿性质的软件开发项目来说,很多教科书里经典的集中开发模式根本不可能使用;另外一方面,这种松散的特点又更加需要一种有效的管理方式,以便达到目的。对此自由软件社团已经建立起了一种特殊的文化传统,同时也就是一种特殊的项目管理方式,这方面具体的内容没有比Eric S. Raymond的《大教堂与集市》更好的说明和分析了,所以我就不必多嘴了,如果又有兴趣而不了解的人,可以自己去看看这篇自由软件历史上最著名的文章。
CVS就是实现这种分散但是有效的“集市性”开发的一个工具,而我在这里仅仅是列出使用它从技术上可以解决的问题。
a、修改同步,防止一名开发人员的修改覆盖其他人的成果。(check out、read only)
b、维护不同的版本。(按 version 查找)
c、可查找历史记录。防止 bug 的再引入。(diff)
CVS 为了解决这个问题,采用的方式是:
当开发人员对源代码进行修改时,修改的内容被登记(check in)到了 CVS 仓库(repository)中。仓库中保存了代码的主控副本,以及历次修改的历史信息。它不保存文件的每个版本,而只是简单的记录发生在每个版本间的不同,节省磁盘空间。它能做到:
a、使开发人员的目录和仓库保持一致。可以把自己的修改提交(commit)给仓库,让仓库更新自己。
b、允许代码派生。可以进行测试,如果失败,可以消除所做的修改,维持原结果。
c、检索任何一个版本。
像前面说的,我不会具体地列出安装方式和使用方法,因为这不是一篇使用手册的文章。你可以到joyfire.net寻找相关的资料。
1. tar和rpm
使用方法我不多说,需要注意一些细节,例如最好在压缩包文件名上带着版本号,确保tar包解压时会创建一个独立的新目录。rpm是越来越常用的方式,尤其是那些对源代码不关心的用户,最好能够花点时间,制作rpm版本。
2. automake
如果用C写程序,要用autoconf/automake/autoheader工具来处理各种移植性的问题,用这些工具完成系统配置信息的收集,创建makefile文件。客户编译源码时只需要按照标准的“configure; make; make install”就可以干净利落编译安装。
至少在每次发布之前要记得用 -Wall 编译选项重新编译一遍并去除编译中遇到的任何错误。这么做可以帮助您发现不少没有想到的错误。要是想更彻底的检查,那就用 -pedantic 选项再编译一遍。
3. vi
是的,是VI,你需要用它编写文档,一般随着压缩包一起会发布以下几个文件。它们具体的内容我想经常使用UNIX或者GNU软件的人不会不知道。也不必非要这么全,但是用户会在第一次使用的时候寻找这些东西。
README
INSTALL
CREDITS
NEWS
HISTORY
COPYING
LICENSE
MANIFEST
FAQ
TAGS
4. Texinfo、man、DocBook文档工具
以上这些文档格式都是linux/unix比较流行的格式,也许还要加上PDF格式。它们的有关工具和用法在一般的linux系统里都带,也可以去http://www.gnu.org和http://www.docbook.org下载。Texinfo和DocBook都支持转化为HTML格式,所以也很容易生成项目网站在线帮助文档。
总之,项目文档应该和项目代码一起成长,而不应该在发布的前一天才被考虑。好的程序员必须能写出优秀的文档。安装手册、用户手册和开发手册是吸引用户、打败竞争对手的最好武器。
每个和你联系的用户都该记录email地址,以便用来保持他对你的项目的兴趣,例如利用群体邮件对新版本进行通告。但是实际上这些用户应该存在两个子集,一个是普通用户列表,另一个是更重要的帮助者。就像《大教堂与集市》里说的,程序发布后,作者会被潮水般“我要怎么做才能帮你”的邮件淹没,但90%名义上的志愿者根本帮不上任何忙。它们的价值甚至连报告BUG的用户都不如。
真正有价值的是发来这样邮件的人:“hi,我下载了你的源代码,发现BUG,这是修改后的补丁”,“刚好,这里有段代码可以增加你软件的功能”。他们才是项目发展的动力,而且很多人会变成你技术上的老师或者生活上的好友,应该和他们建立牢固关系。另外,负责人最后一件应该做的事情,就是在失去维护项目的兴趣或者能力前,找到合适的接替者。你认为最合适的人选会在哪里呢?
由上面的建议可以看出,用户反馈并不总是有用的,太多的要求会超出作者的能力范围之外,不切实际的许诺和幻想也都是由此而来。很多失败的案例里,卤莽虚荣地宣布没有把握的宏伟幻想,或者妄想一天之内就建立完美的志愿者团队100%负责软件各部分,最终都导致浮精疲力尽却一无所获。像做生活中任何事情一样,应该谨慎冷静地思考后再开始,然后保持低调、坚韧和适度乐观,在软件和团队没有完全成熟前,确保自己能掌握一切。
有人总结说,项目启动以后只需要做三件事:说“YES”、说“NO”、把新代码加入新版本,其中说“NO”更多。有些时候选择纯粹是就一种选择,没有理由,但是解释和仲裁必须让对方信服,这就是累人的地方。
项目开始之前应该了解同类项目的情况,也许你应该加入别人的项目而不是自己重新开始。freshmeat.net、slashdot.org、sourceforge.net、Python站点(http://www.python.org)、CPAN(http://www.perl.com/)。这样的站点都是很好的资源查询和信息发布站点。还可以使用搜索引擎,用Free、Open source、GNU、GPL这一类的关键字搜索,只要你找到一个,跟着就可以链接到一串。
如果你的确有欲望去追求比这更高(比如说为了名誉或者信心),那么在编程以后必须推广自己的作品。例如在comp.os.linux.announce 新闻组发布公告。这个新闻组除了有大量的阅读群外,也是许多其它站点,比如Freshmeat,公布新消息的地方。或者在USENET中找到一个与项目密切相关的讨论组,并在那里发布您的项目也是一个极好的方式。另外,您的帖子中应该包含您的项目网站所在的URL地址。
在一定的时机以后,建立自己的站点、邮件列表和讨论区,以便发布有关的消息,收集BUG,让用户下载最新的代码,这都是必要的。一个典型的自由软件项目站点包括:
·项目介绍
·下载源代码,甚至还有源码结构树的访问链接。
·HTML格式的FAQ和其他项目文档。
·各种相关链接。
·建立让普通用户获知项目进展的公告邮件列表,并在首页指明如何加入项目相关的邮件列表。
·建立项目开发专用的邮件列表,透过它合作开发者可以互相交流并讨论对程序补丁的建议。
建立自己的项目站点的时候,一定要明确自己的目的。不要搞成大杂烩。应该学习kernel.org,他的原则是:简洁,再简洁,甚至用一张页面就搞定一切。可是谁都得承认,它大概是网络中最重要的站点(至少是技术站点)之一,统计显示,访问次数最多的是Microsoft。
姓名:利启诚 | 网名:Mephisto | 毕业:清华大学电子工程系 |
曾任水木清华BBS中Linux版斑竹,历届Linux版斑竹中编程水平最高深之人物。曾经仅花费3天时间实现自TurboLinux中文版TurboLinux 6.0开始使用的Unicon显示部分(输入法部分由马军老师实现),比起蓝点 Linux的置入内核当中的zhcon更为安全;在极短时间内与智能启动管理器(SmartBootManager)作者苏哲合作,实现了光驱引导模块,此为全球第一个可以实现光驱引导的自由软件之启动管理器;参与InterMezo等国际项目,取得很好效果。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:何锐 | 网名:raner | 毕业:清华大学计算机科学系 |
CCE的作者,被誉为清华大学“9#绝对Linux第一人”。曾任水木清华BBS斑竹,于1998年年中制作出2CDs的RedHat 5.1(带中文工具和Motif2.0以及许多中文文档),风行全国,流入盗版市场后脱销,国内第三梯队的Linux爱好者大多从这一套盘起步。其改写的CCE-0.10/0.11/0.3x终端中文环境被众多中文Linux发行套件不同程度所包含,更是为众多简体中文版的Linux使用者所青睐。台湾出品的繁体版jmce则是自CCE-0.32所修改。使用FrameBuffer实现中文显示的技术构想从目前所得到的资料来看,为何锐第一个提出(此据可查询水木清华BBS中的Linux板精华区有关于CCE的部分)。目前何锐在美国Duke大学攻读计算机科学硕士学位,CCE-0.3x的维护工作交由上海交通大学图书馆的李亮先生管理。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:谢东翰 | http://xcin.linux.org.tw |
XCIN中文平台的作者,XCIN是台湾非常流行的Linux中文平台。大陆的Linux发行版本很多中文平台就是从XCIN发展来的,并借鉴和改进了XCIN,比如蓝点Linux的CXWIN。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:李亮 | 网名:holly | 毕业:上海交通大学 | http://programmer.lib.sjtu.edu.cn |
CCE现任维护人员。对于CCE的分析、改写和维护起到了很大作用。另外还编写了若干Apache的模块,满足了某些特定要求。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:谢华刚 | 网名:vertex | 毕业:中科院计算所硕士 | http://www.lids.org |
为国际项目LIDS(Linux入侵检测系统)创始人。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:章文嵩 | http://www.linuxvirtualserver.org |
系国际项目LVS(Linux虚拟服务器)创始人。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:郑原忠 | 网名:小虫 | http://cle.linux.org.tw/CLE/ |
台湾著名的CLE-中文Linux延伸套件的领军人物。台湾很多繁体中文Linux套件使用了CLE,例如XLinux、Caldera OpenLinux、Linpus Linux等。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:方汉 | 网名:dfbb |
曾任水木清华BBS中Linux板斑竹,为中文Linux的标准化规范贡献了巨大力量。在北京拓林思公司(TurboLinux北京公司)任职期间,所主持开发的TurboLinux中文版系列被认为是最好的中文Linux版本之一。 他和陈向阳合写的《Linux实用大全》一书,该书是国内较早的一本系统、全面、专业地介绍了Linux方方面面的知识,影响了一大批知识青年,带动了大家投身Linux事业的热情。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:于明俭 | http://yumingjian.home.china.com | http://go18.163.com/~yumingjian/ |
Chinput汉字输入服务器软件项目的创始人。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:邓煜、李凌、廖生苗 | 网名:devin、hahalee、samuel | http://www.openunix.org |
三剑客为蓝点Linux创始人,其首先实现(并非首先提出)的自内核使用FrameBuffer特性显示中文的技术开创了一个时代,为广大中文Linux爱好者提供了最好的中文Linux发行套件之一。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:李振春 | 网名:shi | http://freepy.yeah.net |
系自由拼音的作者。目前CCE-0.3x系列和Unicon系列以及Chinput系列所使用的智能拼音输入法模块皆直接来源于李振春先生的FreePY算法。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:苏哲 | 网名:suzhe | http://suzhe.gnuchina.org |
水木清华Linux版斑竹,为国际项目SmartBootManager(智能启动管理器)原创者。曾多次撰稿宣传自由软件和Linux,并为社区贡献三个自由软件。其所创始之SBM据传将成为两个重要中文发行套件的默认系统启动管理器。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名:霍东灵 | 网名:Foka | 毕业: |
Debian中文化工程的领导。 |
01010101010101010101010101010101010101010101010101010101010101010101010101010101
姓名: | 网名:zixia | 毕业:清华大学 |
著名站点zixia.net的站长,也是AKA的资深成员,曾经是Chinaren.net和Tom.com.cn的root |
制作Linux发布的目的是为了在系统中能够快速,正确地建立Linux系统环境。制作Linux发布的主要工作是决定各种软件的去留,因为有了RPM(RedHat Package Manager)包对其提供优良的管理能力,所以以目前比较成熟的RedHat 7.1(Linux Kernel Version 2.4.2-12)Linux发布程序作为蓝本,以RPM包作为基本的制定单元,以需求为原则对其进行取舍,得到适合实际需要的Linux系统。
由此,项目自然而然的以分析RedHat Linux的光盘安装系统为起点,在掌握了其结构和行为的基础上,在包一级(结构部分)和代码一级(行为部分)进行修改,同时建立相应的测试环境,以便对修改进行及时的规范。
2.项目分步骤实施细节
2.1对Linux光盘安装系统的分析
●结构部分
在安装光盘中,主要的目录结构和文件大致如下:
images/ 此目录下包含了制作启动盘的映像文件(文件后缀img),
其中boot.img是当安装介质为CD-ROM时负责引导系统的映像文件
bootnet.img是当安装介质为FTP,NFS等时负责引导系统的映像文件
driver.img是由一些特殊设备驱动程序模块组成的映像文件,在当前内核不支持这些设备的情况下,提供了对它们进行访问的一种方法
其中,boot.img映像文件中主要包含以下文件:
boot.img
|----vmlinuz Linux内核
|----ldlinux.sys 引导Linux的系统文件
|----syslinux.cfg Linux内核引导参数配置文件
|----initrd.img 内存虚拟文件系统映像文件
|----*.msg文件 引导时的各种提示信息文件
其中,initrd.img为Linux ext2文件系统,构成如下:
initrd.img
|----/bin
|----/dev
|----/etc
|----/module
|----/sbin ------ loader
安装程序装载器
|----/tmp
|----/var
可执行文件/sbin/loader的任务是判断安装介质的有效性,并从中执行安装程序。
其实正是boot.img,在系统启动时被执行,经解析之后在内存建立起了Linux内核,并根据配置文件syslinux.cfg装载虚拟文件系统,形成了完整的Linux System,为后续的工作提供了必要的操作系统环境。Boot.img映像的文件系统类型为msdos,而其中的initrd.img映像的文件系统类型必为Linux系统自己的ext2,所以对于它们的解析操作是不同的,具体请参考附录A 。
RedHat/ 此目录是RedHat Linux发布的核心目录,主要的目录结构都在这里,其中
RPMS/ 包含了RedHat Linux发布的主要部分,即以RPM包的形式将Linux系统中的二进制可执行文件,配置文件,文档等等组织在一起,形成能完成一定功能的比较独立的软件包(文件后缀rpm)。这个目录就是把这些软件包都集合在一起,形成了RedHat Linux发布。
base/ 包含了在安装过程中要用到的描述组织结构和安装行为的所有文件,其中comps,hdlist和hdlist2是描述RPM包组织结构的文件。
comps 此文件把各个RPM包按一定的原则组织成若干组,即components,这样在安装过程中就不必对每一个包做出取舍,而以组为单位。comps文件为简单文本格式,它的结构如下所示:
4 表示RPM包的版本号,当前为4
1 base { }
base是此component名,{…}中是此component中所包含的RPM包
的名称列表,1表示在安装中默认为选中,即默认安装。
0 –hide IDS sensor{
snort
libpcap
}
表示IDS sensor组中包含有snort和lipcap这两个RPM包。0表示
这个组在安装中默认为不选中即默认不安装,并且由—hide指出
不在用户界面上显示此组。
hdlist和hdlist2 这两个文件维护从RPM包名到真实包文件名的映射过程,例如从snort这个RPM包名到真实包文件名snort-1.8.1-1.1.2.i386.rpm的映射。这两个文件是用特殊的程序生成的,无法用简单的方法察看其中的内容和结构。具体的生成方法请参考附录D。
stage2.img , hdstg1.img , hdstg2.img , netstg1.img 和netstg2.img 是描述安装行为的映像文件,其中
stage2.img 是当安装介质为CD-ROM时的安装程序映像文件
hdstg1.img 是当安装介质为HardDisk时的安装程序映像文件
hdstg2.img 是当安装介质为HardDisk时的安装程序映像文件
netstg1.img 是当安装介质为FTP,NFS时的安装程序映像文件
netstg2.img 是当安装介质为FTP,NFS时的安装程序映像文件
这里主要讨论stage2.img的内容
stage2.img
|----/etc
|----/modules
|----/proc
|----/usr----/bin----anaconda
安装程序主执行文件
|
|------/lib-----/anaconda
安装程序脚本文件目录
| |----/installclasses
| |----/iw
| |----/texttw
| |----*.py
|
|------/share---/anaconda
安装程序资源文件目录
| |----/help
| |----/pixmaps
如上所示,stage2.img映像文件中的主要部分是安装程序anaconda,它的主执行体是/usr/bin下的anaconda,由其调用的大量例程分布在/usr/lib/anaconda下,而安装过程中要用到的资源文件分布在/usr/share/anaconda下。stage2.img 的解析方法请参考附录B。
●行为部分
RedHat 7.1的安装程序被命名为anaconda。如前所述,当boot.img所代表的启动介质被系统引导之后,在内存中就建立了一个完整的Linux系统(包括Linux内核和一个内存虚拟文件系统),之后便执行文件系统中存在的loader命令,从适当的介质中执行安装程序(例:安装介质是CD-ROM,就解析CD-ROM上的stage2.img,并从中执行安装程序),即执行anaconda,完成Linux系统的安装任务。
此次利用RedHat 7.1的安装程序源代码的SRPM包形式:anaconda-7.1-5.src.rpm来获得anaconda的源程序,经解包后在/usr/src/redhat/SOURCES/anaconda-7.1形成了源代码树。
anaconda-7.1
|-------------------/bootdisk
启动盘目录
|-------------------/docs
文档目录
|-------------------/help
安装过程帮助系统目录
|-------------------/installclasses
安装类型分类目录
|-------------------/iw
安装各步骤响应目录
|-------------------/loader
安装程序装载器目录
|-------------------/pixmap
图形资源目录
|-------------------/utils
工具目录
|-------------------*.py
各Python脚本文件
分析如下:
anaconda安装程序主要用Python语言写成,它是一种解释性的,面向对象的脚本语言。源文件后缀为.py,也可生成可执行的字节码,后缀为.pyc或.pyo。其中:
installclasses/ 子目录中各文件定义了在安装过程中用户可选择的安装类型,通常由四个文件workstation.py , server.py , laptop.py和custom.py来描述workstation(工作站)安装类型,server(服务器)安装类型,laptop(膝上型电脑)安装类型和custom(自定义)安装类型。每个脚本文件的内部,则是根据自己安装类型的特点对安装步骤,分区策略以及包的取舍做出了不同的方案。
iw/ 子目录中各文件定义了在图形界面安装状态时各步骤对Next(下一步)和Prev(上一步)的响应函数。
loader/ 安装程序装载器的源代码目录,用C语言写成。
pixmap/ 图形资源目录,包括安装过程中使用到的所有位图,图标。
utils/ 安装程序实用工具目录。
anaconda 是安装程序的主执行文件,它建立了Python语言的运行环境,提供了程序的入口点并以模块的方式将各个子系统结合在一起。
gui.py 定义了安装程序图形界面使用的各种窗口类,包括MessageWindow,ProgressWindow,WaitWindow,ExeceptWindow等,和控制这些窗口及图形界面行为的InstallInterface, InstallControlWindow, InstallControlState类。总之,控制gui。
todo.py 定义了安装程序的各种行为函数,它是图形界面背后真正进行各项操作的函数集合。
harddrive.py 定义了当安装介质为硬盘时,系统该如何找到安装程序的光盘映像,并从中执行程序。
安装程序源代码的编译由make和make install组成,完成后在/usr/src/RedHat目录下形成了如下目录结构:
instimage
|------/etc
|------/usr
|------/bin
|------/sbin
|------/lib
| |------/anaconda
| | |------installclasses
| | |------iw
| | |------texttw
| | |------*.py
| |
| |------/anaconda-runtime
| |------/boot/loader
|
|------/share------/anaconda
|------/help
|------/pixmaps
此目录结构基本与stage2.img的文件结构相同。
2.2调试环境的建立:
●对源程序的修改
在分析完安装程序的基本构成之后,就要建立相应的调试环境。建立此环境的目的是为了可以方便地对修改过的安装程序及裁减后的RPM包进行随时的确认。显然,可以选用CD-ROM或本地硬盘作为调试介质,下表比较了两者的差别:
CDROM 硬盘
对应的安装界面 图形界面 菜单界面
对应的映像文件 stage2.img *.iso中的hdstg1.img , hdstg2.img
优点 图形界面,直接使用映像文件stage2.img 随改随调,调试周期短,效率高
缺点 每次改动都要求刻盘,调试效率低 菜单界面,每次调试都要求提供光盘映像文件*.iso,效率上打折扣
在两者各有优缺点的情况下,考虑折衷的方案,即为了首先保证调试的效率,采用硬盘作为调试介质,但对应的映像文件选取stage2.img,这样能达到效率最大化,同时调试界面采取图形方式。采用此方案时,须修改源代码,以达到预期的效果。
从前面对安装系统的分析,可以看出在initrd.img中的/sbin/loader程序负责判断安装介质的有效性,并从中执行安装程序。所以要首先修改它的源代码文件loader.c,从中找出硬盘安装时默认读出光盘映像文件*.iso的函数setupIsoImages,并注释掉其中在硬盘目录中寻找映像文件*.iso的相关操作,具体对应Line 582 至 Line590行中包含sprintf和if(){}循环的语句,以避免打开子目录,并在其后加入mountLoopback("/tmp/hdimage/RedHat/base/stage2.img","/mnt/runtime", "loop0");一句以便实现直接使用stage2.img的目的,并注释掉其后从errno=0开始的代码,经过整个while循环到closedir(dir),但保留umount(“/tmp/hdimage”);注释掉if(!net) return NULL;一句。以上操作目的是防止程序读出光盘映像文件*.iso。在loader.c的主函数main()中的结尾部分,注释掉if (!FL_TESTING(flags)) { 和 }的条件判断的两条语句,让程序毫无疑问地执行硬盘上的安装程序。至此,对loader.c修改完毕。
同时还要对Python脚本的一些相关文件进行修改以保证对stage2.img文件的支持。具体的,在harddrive.py的类class HardDriveInstallMethod中,注释掉函数 mountMedia(self, cdNum)中的所有内容并加Pass语句的方法使此函数失效,同样方法处理umountMedia函数,mountDirectory函数和umountDirectory函数,为了保险起见,在其他函数中注释掉有关上面函数的调用。并在类的构造函数(初始化)中的# Go ahead…语句之前加self.tree=”/tmp/hdimage/”语句,并注释掉后面的所有语句。这样做仍然是要保证废弃iso映像转而对stage2.img实现控制。不仅如此,最好还注释掉todo.py中的Line1781至Line1783调用self.method.systemMounted一段,以确保不出差错。接着进行make和make install,重新编译程序,使修改生效,并把新的loader程序从编译的目标目录中copy到boot.img中initrd.img中的相应目录并覆盖旧的loader文件。为了启动时的快速,修改boot.img中的syslinux.cfg文件,去掉启动提示,延时和其他Linux启动选项,修改后的syslinux.cfg文件,请参考附录F
最后,把boot.img做成启动盘,方法请参考附录G。
●建立硬盘介质中的调试目录
在硬盘的Linux分区中建立形如RedHat安装光盘目录结构的调试目录及相关文件,如下所示:
|----/images
| |------boot.img
|
|----/RedHat
|----/base
| |------comps , hdlist , hdlist2,stage2.img
|
|----/RPMS
| |----*.rpm
建立这种目录结构和相关文件的原因是在安装程序中已经以代码的形式确定了它们的命名及结构。其中,对boot.img和stage2.img的相关修改如前所述,而涉及到对comps,hdlist,hdlist2的修改,则需在后续的裁剪过程中确定。
至此,调试环境建立完毕。现在可以用做好的启动盘来引导系统,并且可以从指定的硬盘上测试安装程序和RPM包的正确性。