Product SiteDocumentation Site

5.2. 软件包元信息

Debian 软件包不仅仅只是一些待安装的文件的存档,它是一个更大的结构的一部分,它描述与其它 Debian 软件包的关系(依赖、冲突、建议)。它还提供脚本供软件包的生命周期的不同阶段(安装、删除、升级)使用。这些供包管理工具使用的数据不是被打包的软件的一部分,但它们存在于软件包里,被称作“元信息”(关于其它信息的信息)。

5.2.1. 描述:control 文件

该文件使用一个类似电子邮件头(由 RFC 2822 定义)的结构。例如,apt 包的 control 文件看起来是这样的:
$ apt-cache show apt
Package: apt
Version: 0.9.7.9
Installed-Size: 3271
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: manpages-pl (<< 20060617-3~)
Depends: libapt-pkg4.12 (>= 0.9.7.9), libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.6), debian-archive-keyring, gnupg
Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, xz-utils, python-apt
Conflicts: python-apt (<< 0.7.93.2~)
Description-en: commandline package manager
 This package provides commandline tools for searching and
 managing as well as querying information about packages
 as a low-level access to all features of the libapt-pkg library.
 .
 These include:
  * apt-get for retrieval of packages and information about them
    from authenticated sources and for installation, upgrade and
    removal of packages together with their dependencies
  * apt-cache for querying available information about installed
    as well as installable packages
  * apt-cdrom to use removable media as a source for packages
  * apt-config as an interface to the configuration settings
  * apt-key as an interface to manage authentication keys
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, hardware::storage, hardware::storage:cd,
 implemented-in::c++, interface::commandline, network::client,
 protocol::ftp, protocol::http, protocol::ipv6, role::program,
 suite::debian, use::downloading, use::searching,
 works-with::software:package
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_0.9.7.9_amd64.deb
Size: 1253524
MD5sum: 00a128b2eb2b08f4ecee7fe0d7e3c1c4
SHA1: 6a271487ceee6f6d7bc4c47a8a16f49c26e4ca04
SHA256: 3bba3b15fb5ace96df052935d7069e0d21ff1f5b496510ec9d2dc939eefad104

5.2.1.1. 依赖:Depends

The dependencies are defined in the Depends field in the package header. This is a list of conditions to be met for the package to work correctly — this information is used by tools such as apt in order to install the required libraries, in their appropriate versions, that the package to be installed depends on. For each dependency, it is possible to restrict the range of versions that meet that condition. In other words, it is possible to express the fact that we need the package libc6 in a version equal to or greater than “2.3.4” (written “libc6 (>= 2.3.4)”). Version comparison operators are as follows:
  • <<:小于;
  • <=:小于或等于;
  • =: equal to (note that “2.6.1” is not equal to “2.6.1-1”);
  • >=:大于或等于;
  • >>:大于。
In a list of conditions to be met, the comma serves as a separator. It must be interpreted as a logical “and”. In conditions, the vertical bar (“|”) expresses a logical “or” (it is an inclusive “or”, not an exclusive “either/or”). Carrying greater priority than “and”, it can be used as many times as necessary. Thus, the dependency “(A or B) and C” is written A | B, C. In contrast, the expression “A or (B and C)” should be written as “(A or B) and (A or C)”, since the Depends field does not tolerate parentheses that change the order of priorities between the logical operators “or” and “and”. It would thus be written A | B, A | C.
The dependencies system is a good mechanism for guaranteeing the operation of a program, but it has another use with “meta-packages”. These are empty packages that only describe dependencies. They facilitate the installation of a consistent group of programs preselected by the meta-package maintainer; as such, apt-get install meta-package will automatically install all of these programs using the meta-package's dependencies. The gnome, kde-full and linux-image-amd64 packages are examples of meta-packages.

5.2.1.2. 冲突:冲突字段

The Conflicts field indicates when a package cannot be installed simultaneously with another. The most common reasons for this are that both packages include a file of the same name, or provide the same service on the same TCP port, or would hinder each other's operation.
dpkg会拒绝安装一个软件包,当这个软件包和已经安装的软件包触发了一个冲突的时候,除非新的软件包特别指定了“替换”已安装的软件包,在这种情况下dpkg将会用新的软件包来替换掉旧的软件包。apt-get则会一直遵循你的指示:如果你选择安装一个新的软件包,它将自动提供卸载老的软件包,这将会引入一个新的问题。

5.2.1.3. 不相容性:中断字段

中断字段有一个影响和冲突字段类似,但它具有特殊的意义。它标志着一个包的安装会将另外一个包(或者是特定版本)中断掉。通常而言,两个包之间的不兼容是短暂的,中断关系会特别指出那些不兼容的版本。
dpkg在中断已安装的软件包时会拒绝安装新的软件包,apt-get则会通过更新到新的版本来尝试解决这个问题(这被认为是修复兼容性的方式,因此,包会再次兼容。)。
不向后兼容的更新可能会发生这种情况:如果新版本与旧版本的功能不在另一个程序中做特别规定,这将导致故障。中断字段会防止用户继续运行从而遇到这些问题。

5.2.1.4. 预备好的条目:预备字段

这个字段引入了一个很有意思的“虚拟包”的概念。它有很多的角色,但有两个特别重要。第一个是由使用虚拟包关联到的一个通用的服务(包“预备”了这些服务)。第二个表示一个包完全取代了另外一个,所以它也能满足依赖性要求。因此,可以创建一个替换而不必使用相同的包名称的包。
5.2.1.4.1. 提供一个“服务”
Let us discuss the first case in greater detail with an example: all mail servers, such as postfix or sendmail are said to “provide” the mail-transport-agent virtual package. Thus, any package that needs this service to be functional (e.g. a mailing list manager, such as smartlist or sympa) simply states in its dependencies that it requires a mail-transport-agent instead of specifying a large yet incomplete list of possible solutions (e.g. postfix | sendmail | exim4 | …). Furthermore, it is useless to install two mail servers on the same machine, which is why each of these packages declares a conflict with the mail-transport-agent virtual package. The conflict with itself is ignored by the system, but this technique will prohibit the installation of two mail servers side by side.
5.2.1.4.2. 和另一个软件包的可交互性
The Provides field is again interesting when the content of a package is included in a larger package. For example, the libdigest-md5-perl Perl module was an optional module in Perl 5.6, and has been integrated as standard in Perl 5.8 (and later versions, such as 5.14 present in Wheezy). As such, the package perl has since version 5.8 declared Provides: libdigest-md5-perl so that the dependencies on this package are met if the user has Perl 5.8 (or newer). The libdigest-md5-perl package itself has eventually been deleted, since it no longer had any purpose when old Perl versions were removed.
使用了预备字段来避免中断依赖性关系

图 5.1. 使用了预备字段来避免中断依赖性关系

这个功能非常有用,因为它是永远不可能预料到变化莫测的发展,它不能够调整重命名,或者其他自动替换过的软件,所以它是必要的。
5.2.1.4.3. 现在的缺点
Virtual packages suffer from some limitations, the most significant of which being the absence of a version number. To return to the previous example, a dependency such as Depends: libdigest-md5-perl (>= 1.6), despite the presence of Perl 5.10, will never be considered as satisfied by the packaging system — while in fact it most likely is satisfied. Unaware of this, the package system chooses the least risky option, assuming that the versions do not match.

5.2.1.5. 替换文件:替换字段

替换字段表示该软件包中包含的文件,在另一个软件包中也存在,但该包能够合法和有权的替换掉这些文件。如果没有这个规范,dpkg命令会失败,说明它不能替换掉这些文件的另外一个软件包(事实上,它有可能迫使它这样做,使用强制覆盖选项)。这使得识别潜在的问题和需要维护者在研究此事前,选择是否增加这样的字段。
当软件包名称变更时,或者当一个软件包包含在另外一个的时候,此字段的使用是合理的。这也发生在维护者决定从来自相同的源码包的大量二进制包里分发出文件:一个替换的文件不再属于旧的软件包,只有新的才属于。
如果已安装软件包的所有文件都被替换了,那么该软件包将认为将被删除掉。最后,这个字段会鼓励dpkg命令去删除替换掉有冲突的包。

5.2.2. 配置脚本

除了控制文件之外,每个Debian软件包可能在control.tar.gz的存档中包含了一些脚本,这些脚本在软件包处理的不同的阶段被dpkg调用。Debian政策描述了一些可能的细节,在可能的情况下,指定脚本调用它们所收到的参数。这些顺序可能比较复杂,因为如果脚本中任何一步出现问题的时候,dpkg进程会通过取消安装或者卸载来尝试恢复到一个令人满意的状态(只要是可能的)。
在一般情况下,preinst脚本会在安装软件包前执行,而postinst会稍候执行。同样,prerm会在移除一个软件包的前和postrm之后。更新软件包相当于是清除掉以前的旧版本并且安装新的软件包。所以在这里我们不可能来详细描述所有的可能的方案,但我们将讨论最常见的两种:安装/更新和移除。

5.2.2.1. 安装和升级

这里告诉你,安装的时候发生了什么(或者是更新)
  1. 对于升级,dpkg会调用old-prerm 升级新版本
  2. 还是对于升级,dpkg执行new-preinst 升级旧版本;对于第一个安装,它会执行new-preinst 安装。它可能会增加旧版本的最后一个参数,如果软件包已经被安装或者是删除了(但没有清除合并掉旧版本,那么这个配置文件会被保留)。
  3. 新的软件包文件被解压。如果文件已经存在,就被会替换,同时会产生一个临时的备份副本。
  4. 对于更新,dpkg执行old-postrm 升级新版本
  5. dpkg更新所有的内部数据(文件爱女列表,配置脚本等),并删除被替换文件的备份。这是一条不归路: ) dpkg将不再具有访问所有元素的需要以此来返回以前的状态。
  6. dpkg will update the configuration files, asking the user to decide if it is unable to automatically manage this task. The details of this procedure are discussed in 第 5.2.3 节 “校验,配置文件列表”.
  7. 最后,dpkg 配置软件包通过执行new-postinst配置最终版本配置

5.2.2.2. 软件包移除

这里是当移除一个软件包的时候发生了什么:
  1. dpkg 回调prerm 移除
  2. dpkg 移除了所有的软件包文件,只剩下了配置文件和配置的脚本。
  3. dpkg executes postrm remove. All of the configuration scripts, except postrm, are removed. If the user has not used the “purge” option, the process stops here.
  4. 对于一个完整的清除包(由dpkg --purgedpkg -P发出的),配置文件也将会被删除,同时一些副本(*.dpkg-tmp,*.dpkg-old,*.dpkg-new)和缓存文件也会被删除掉;dpkg这时会执行postrm purge
The four scripts detailed above are complemented by a config script, provided by packages using debconf to acquire information from the user for configuration. During installation, this script defines in detail the questions asked by debconf. The responses are recorded in the debconf database for future reference. The script is generally executed by apt prior to installing packages one by one in order to group all the questions and ask them all to the user at the beginning of the process. The pre- and post-installation scripts can then use this information to operate according to the user's wishes.

5.2.3. 校验,配置文件列表

In addition to the maintainer scripts and control data already mentioned in the previous sections, the control.tar.gz archive of a Debian package may contain other interesting files. The first, md5sums, contains the MD5 checksums for all of the package's files. Its main advantage is that it allows a tool such as debsums (which we will study in 第 14.3.3.1 节 “审核软件包:debsums 及其限制”) to check if these files have been modified since their installation. Note that when this file doesn't exist, dpkg will generate it dynamically at installation time (and store it in the dpkg database just like other control files).
conffiles lists package files that must be handled as configuration files. Configuration files can be modified by the administrator, and dpkg will try to preserve those changes during a package update.
实际上,在这种情况下,dpkg的行为会尽可能地智能:如果两个版本之间并没有改变标准的配置文件,那么dpkg就什么也不会作。但是,如果文件已经被修改,它会尝试更新此文件。这会产生两种可能的情况:一是管理员没有碰配置文件,在这种情况下dpkg会自动安装新版本;二是文件已经被修改了,在这种情况下dpkg会询问管理员希望使用哪个版本(旧版本或者新的)。为了帮助用户作出选择,dpkg会提供“差异”,这会显示两个版本之间的差异。如果用户选择保留旧的版本,新的将被存储在文件夹的同一个位置并以.dpkg-dist为后缀名的文件中。另外一个可能的操作是由暂时中断的dpkg来编辑该文件,并试图重新恢复相关的修改(之前被验证的差异)。