<!-- Subversion revision of original English document "2113" -->
<!--
   Chinese version: $Revision: 1.2 $
   -->  

<chapt id="pkg_basics">Debian 的包管理系统

<sect id="package">什么是 Debian 包?

<p>软件包一般包括实现一系列命令或特殊功能所必须的所有文件. 有两种类型的 Debian 软件包:

<list>
  <item><em>二进制包</em>, 包含可执行文件, 配置文件, man/info 手册, 版权信息, 以及其它文档. 以一种 Debian 特有的格式分发(详见<ref id="deb-format">), 通常以 '.deb' 作为后缀. 可以使用 Debian 的 <tt>dpkg</tt> 工具解包(安装); 详见联机手册.
  
  <item><em>源代码包</em>, 包括一个描述源代码包的 <tt>.dsc</tt> 文件, 一个包含 gzip-tar 归档压缩格式的未经修改源码的 <tt>.orig.tar.gz</tt> 文件, 一个包含对源代码作Debian特有修改的 <tt>.diff.gz</tt> 文件. 可以使用 <tt>dpkg-source</tt> 打包和解压 debian 源码文档. 详见联机手册.
</list>

<p>软件包体系使用包维护者特制的 "依赖关系(dependencies)" 来安装软件. 这些依赖关系被写在每个包的 <tt>控制(control)</tt> 文件里. 例如: 安装依赖于 <package/binutils/ 软件包的 <package/gcc/ 时,如果没有预先安装 <package/binutils/, 包管理系统 (dpkg) 就会停止安装 <package/gcc/, 并返回需要 <package/binutils/ 的错误信息.(解决这类问题,见<manref name="dpkg" section="8">). 详见<ref id="depends">.


<p>Debian 的打包工具可用于:
<list>
  <item>维护和管理软件包或部分软件包,
  <item>用于大软件包的切割, 如, 需要使用小容量软盘来传输,
  <item>帮助开发者构建软件包, 并且
  <item>帮助用户进行远程(FTP)安装.
</list>

<sect id="deb-format">Debian 软件包的格式?

<p> 一个 Debian "软件包", 或 Debian 归档文件, 包含可执行文件, 库文件, 附属文档. 名字通常以 <tt>.deb</tt> 为后缀.

<p>Debian 二进制软件包内部格式描述见<manref name="deb" section="5">联机手册. 由于这种内部格式会改变的(特别对于&debian; 的主发行版), 所以通常使用 <manref name="dpkg-deb" section="1"> 操作.deb文件.

<sect id="pkgname">为什么 Debian 软件包名字这么长? 

<p> Debian 二进制软件包的命名格式:
&lt;foo&gt;_&lt;版本号&gt;-&lt;Debian修订号&gt;.deb

<p>注意, <tt>foo</tt> 是假定的软件包名. 作为检验, 你可以通过下面的方法之一了解和软件包名称对应的一个 debian 软件包(.deb 文件):
<list>
  <item>检查 Debian FTP 站点下的 "Packages" 文件, 文件中包含对于每个软件包的描述段, 每个描述段的第一个字段就是正式包名.
  <item>使用命令 <tt>dpkg --info foo_VVV-RRR.deb</tt> (这里 VVV 和 RRR 是被查询包的版本和修订版本). 显示的内容中将包含软件包的对应名称.
</list>

<p> <tt>VVV</tt> 是指该软件开发者制定的版本号, 没有什么标准格式, 可能像 "19990513" 和 "1.3.8pre1" 一样有所不同..

<p> <tt>RRR</tt> 是 Debian 的修订版本号, 由 Debian 开发者(或者创建 Debian 包的用户自己)指定, 反映了 Debian 软件包的修正层次, 一个新的修正版通常在 Debian Makefile (<tt>debian/rules</tt>)文件 Debian 控制文件, 安装, 删除脚本(<tt> debian/p* </tt>), 或软件包的配置文件中作了修改.

<!--
<p>The <tt>Arch</tt> component identifies the processor for which
the package was built.  This is commonly <tt>i386</tt>, which refers to
chips compatible to Intel's 386 or later versions.  For other
possibilities see <ref id="dirtree" name="Debian's FTP directory structure">.
-->

<sect id="controlfile">Debian 的控制文件是什么?

<p>关于控制文件的详细内容参见 Debian 打包手册, 第 4 章, <ref id="debiandocs">.

<p>下边是一个 Debian 软件包 hello 的简单配置文件的主要内容:
<example>
包名: hello
优先级: optional
类别: devel
安装大小: 45
维护者: Adam Heath &lt;doogie@debian.org&gt;
平台: i386
版本: 1.3-16
依赖: libc6 (>= 2.1)
描述: The classic greeting, and a good example
 The GNU hello program produces a familiar, friendly greeting.  It
<!-- XXX below 'non-programmers' were better, but this is a verbatim copy -->
 allows nonprogrammers to use a classic computer science tool which
 would otherwise be unavailable to them.
 .
 Seriously, though: this is an example of how to do a Debian package.
 It is the Debian version of the GNU Project's `hello world' program
 (which is itself an example for the GNU Project).
</example>

<p>包名(Packahe)字段给出软件包的名称, 这是软件包工具用以识别这个包的名称, 通常(单不是必须)和这个 Debian 软件包的名称的第一个字符串相似.

<p>版本(Version)字段给出上游开发者的版本号和修正版本号,详见<ref id="pkgname">. <!-- XXX missing name -->

<p>平台(Architecture)字段指定这个二进制包的编译硬件平台.

<p>依赖(Depends)字段给出所依赖的包的列表.

<p>安装大小(Installed-Size)字段说明安装这个包所需磁盘空间, 用于安装前端显示是否有足够的空间安装此程序..

<p>类别(Section)行给出此包在Debian FTP上的存储位置,上存储此包的目录名(详见<ref id="dirtree">).

<p>优先级(Priority), 对应安装来说的重要程度, 象 dselect 和 console-apt 一类的半智能软件可以据此对软件安装分类,详见 <ref id="priority">.

<p>维护者(Maintainer)字段给出当前维护此包负责人的电子信箱..

<p>描述(Description)字段此软件包的简要说明.

<p> 更多内容参阅 Debian 打包手册, 第4章, "控制文件及其字段".

<sect id="conffile">Debian 的配置文件

<p>配置文件(Conffiles)是一个配置文件列表(通常在 <tt>/etc</tt> 下), 软件升级时不会被覆盖, 以确保所含文件的本地配置不会被破坏, 使得可以在系统运行状态下升级.

<p>运行:
  <example>dpkg --status package</example>
查看 "Conffiles" 段来确定升级时哪些文件被保护.

<sect id="maintscripts">Debian 的 preinst, postinst, prerm, 和 postrm 脚本?

<p>这些是软件包安装前后自动运行的可执行脚本. 统称为<tt>控制文件</tt>, 是 Deian 软件包的"控制"部分..

<p>它们是:
<taglist>
<tag/preinst/
  <item>Debian软件包(".deb")解压前执行的脚本, 为正在被升级的包停止相关服务,直到升级或安装完成.(成功后执行 'postinst' 脚本).

<tag/postinst/
  <item>主要完成软件包(".deb")安装完成后所需的配置工作. 通常, postinst 脚本要求用户输入, 和/或警告用户如果接受默认值, 应该记得按要求返回重新配置这个软件. 一个软件包安装或升级完成后, postinst 脚本驱动命令, 启动或重起相应的服务.

<tag/prerm/
  <item>停止一个软件包的相关进程, 要卸载软件包的相关文件前执行.T.

<tag/postrm/
  <item>修改相关文件或连接, 和/或卸载软件包所创建的文件(见 <ref id="virtual">.)
</taglist>

<p>当前的所有配置文件都可在 <tt>/var/lib/dpkg/info</tt> 目录下找到, 与 <tt>foo</tt> 软件包相关的命名以 "foo" 开头,以 "preinst", "postinst", 等为扩展.这个目录下的 <tt>foo.list</tt> 文件列出了软件包安装的所有文件.(注意这些文件的位置是dpkg确定的；可能会因Debina版本而异)

<sect id="priority">包的优先级?

<p>每个软件包都有一个维护者指定的<em>优先级</em>, 用于包管理系统. 这些优先级是:

<list>
  <item><strong>必须的(Required)</strong>: 系统运转所必须的软件包.
    <p>包括修复系统缺陷所必须的所有工具. 不能删除这些软件包, 否则系统可能会崩溃, 且甚至有可能无法用 dpkg 恢复. 仅有这类包的系统是不可用的, 但是它为系统管理员启动系统安装其它软件提供足够的功能.
  <item><strong>重要的(Important)</strong>: 在任何类 Unix 系统上均安装有该级别软件包.
    <p>没有这类包, 其它的包无法在系统上正常运转或使用, Emacs , X11 , TeX 等大型应用程序<em>不</em>在此列. 此类包构成基本系统.
  <item><strong>一般的(Standard)</strong>: Linux 系统里的一般软件包, 构成小型字符系统.
    <p>这是用户什么也不选也会默认安装的软件包. 不包括大型软件, 但是 Emacs(与其说它是一个应用软件,不如说它是基础构件)一小部分 TeX 和 LaTeX(不支持X)除外.
  <item><strong>可选的(Optional)</strong>: 软件包包含了所有的你想要安装的文件, 如果你一开始不知道它是什么. 或者没有特殊的需要.
    <p>这包括 X11, 所有的 TeX 和许多应用程序.
  <item><strong>额外的(Extra)</strong>: 这类包不是与其它高优先级的软件冲突, 只有知道它的用途才可能对你有用, 就是因为特别的原因而不能进入"可选"优先级.
</list>

<sect id="virtual">什么是虚拟包?

<p>是指一组具有近似功能的软件的统称, 例如 <tt>tin</tt> 和 <tt>trn</tt> 都是新闻阅读程序, 为系统中其它需要新闻阅读的程序提供支持. 因此可以说它们都提供了"<tt>新闻阅读(news-reader)</tt>"的虚拟包.

<p>同样, <tt>smail</tt> 和 <tt>sendmail</tt> 都提供了邮件传输代理的功能. 因此说它们提供了"邮件传输代理(mail transport agent)"的虚拟包,两者安装都可以满足其它程序对于"<tt>邮件传输代理(mail transport agent)</tt>"虚拟包的需求.

<p>Debian 提供这样一种, 如果系统中提供同一虚拟包的软件了安装了多个, 系统管理员可以指定一个为首选. 相关的命令是 <tt>update-alternatives</tt>, 更多描述详见<ref id="diverse">.

<sect id="depends">包的关联

<p>Debian 的软件包管理系统有一套包"依赖性"概念, 用以标示(一个标志符号)系统中程序 A 对于现存程序 B 的依赖程度:
<list>
  <item>软件包 A <em>depends</em> 软件包 B, 指运行 A 必须安装 B, 某些情况下 A 不仅依赖于 B, 还依赖于它的版本. 这种情况通常有最低版限制, A 更依赖于 B 的最新版而不是特定版.
  <item>软件包 A <em>recommends</em> 软件包 B, 如果软件维护者认为用户更喜欢 B 提供功能支持的 A.
  <item>软件包 A <em>suggests</em> 软件包 B, 如果 B 的某些软件与 A 的功能有关(通常是增强).
  <item>软件包 A 与软件包 B <em>conflicts</em> 指如果系统中有 B 则 A 不能运行. 通常是因为 A 包含了 B 中文件的改进而出现冲突, "Conflicts" "replaces" 经常同时出现.
  <item>软件包 A <em>replaces</em> 软件包 B, 指 A 安装时, B 中的文件会被 A 的删除和覆盖.
  <item>软件包 A <em>provides</em> 软件包 B, 指 A 会提供 B 所有的功能和文件, 这种机制为那些磁盘空间受限用户提供了一个方法, 即只安装 A 中需要的部分.
</list>

<p>以上条目的更详细信息参阅打包手册和策略手册

<sect id="pre-depends">Pre-Depends 什么意思?

<p>"Pre-Depends" 是一种特别的依赖关系, 很多软件, 不管系统中它的依赖包是否存在, <tt>dpkg</tt> 都会将其(即, <tt>.deb</tt> 文件)解包, 解包通常是指释放出包中的安装文件, 如果系统中不存在<em>依赖</em>的包, <tt>dpkg</tt> 将会拒绝完成安装(执行它的"配置"动作).

<p>但是, 对于某些包, 在依赖性问题解决前, <tt>dpkg</tt> 甚至拒绝解包, 这就称作, 这种包对某些包有 "Pre-depend" 关系. Debian 项目提供这种机制是为了系统由 <tt>a.out</tt> 格式安全升级到 <tt>ELF</tt> 格式, 这种情况对于解包要求非常严格. 对于其它的重要升级这种方法也非常有用, 比如对那些 "required" 级并有 LibC 关联的软件包. 

<p>更多信息,详见 打包手册.

<sect id="pkgstatus">包的状态( <em/unknown/, <em/install/, <em/remove/
  <em/purge/ 和 <em/hold/)?

<p> 这些 "want" 标志位描述了用户打算如何操作一个软件包(既可以使用 <tt>dselect</tt> 的 "Select" 菜单，也可以直接调用<tt>dpkg</tt>).

<p>它们的意思是:
<list>
  <item>unknown  - 用户并没指出他想对软件包进行的操作
  <item>install  - 用户希望对软件包进行安装或升级
  <item>remove   - 用户希望删除软件包, 但不想删除它的配置文件.
  <item>purge    - 用户希望完全删除软件包, 包括配置文件.
  <item>hold     - 用户希望软件包保持现状, 例如, 用户希望保持当前的版本状态.
</list>

<sect id="puttingonhold">如何锁定一个包?

<p>有两种办法锁定软件包, 使用dpkg 或 dselect.

<p>使用dpkg, 仅需要导出软件包选择列表:
  <example>dpkg --get-selections \* > selections.txt</example>
然后编辑 <file/selections.txt/ 文件, 修改你要锁定的包的所在行, 例如 <package/libc6/将:
  <example>libc6                                           install</example>
改为:
  <example>libc6                                           hold</example>
然后存盘再把它导入 dpkg 数据库:
  <example>dpkg --set-selections < selections.txt</example>

<p>使用dselect, 仅需要进入 [S]elect 屏幕, 找到要锁定的(软件)包,按下 `=' 键 (或 `H'). 离开 [S]elect 屏幕后,改动马上生效.

<sect id="sourcepkgs">如何安装一个 source 包?

<p>Debian 源代码包实际上不能"安装", 只是解包到你欲创建二进制包的目录.

<p>大多数二进制软件包的镜像站点都提供源代码包, 如果在你的 APT 的 <manref name="sources.list" section="5"> 文件中写入了相应的 "deb-src" 源, 通过运行<example>apt-get source foo</example> 来下载源代码包

<p>Debian 源代码包提供了所谓的构造-依赖机制, 即源代码包的维护者提供了一个创建包所依赖的包的列表, 创建二进制包前运行

  <example>apt-get build-dep foo</example>

你就知道它的用处了.

<sect id="sourcebuild">如何从源码创建二进制包?

<p>编译源码, 你需要所有的ffoo_*.dsc, foo_*.tar.gz 和 foo_*.diff.gz (注意, 对于由 Debian 开发的软件包, 没有 .diff.gz 文件)(注: 指对于 foo 软件包).

<p>完成后(<ref id="sourcepkgs">), 如果你已经安装了 dpkg-dev (软件)包,运行一下命令:
  <example>dpkg-source -x foo_version-revision.dsc</example>
将释放包到 <tt>foo-version</tt> 目录.

<p>如果仅想编译这个包,进入 <tt>foo-version</tt> 目录, 执行命令

  <example>dpkg-buildpackage -rfakeroot -b</example>

创建包(注意, 需要 <package/fakeroot/ package 软件包), 然后

  <example>dpkg -i ../foo_version-revision_arch.deb</example>

来安装新创建的包.

<sect id="creatingdebs">如何自己制作 Debian 包?

<p>更多细节, 阅读 新维护者指南, 该文档在 <package/maint-guide/ 包中, 或浏览 <url id="http://www.debian.org/doc/devel-manuals#maint-guide">.
