Product SiteDocumentation Site

5.2. 软件包元信息

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

5.2.1. 描述:control 文件

该文件使用一个类似电子邮件头(由 RFC_2822 定义)的结构。例如,apt 包的 control 文件看起来是这样的:
$ apt-cache show apt
Package: apt
Version: 1.0.9.6
Installed-Size: 3788
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
Depends: libapt-pkg4.12 (>= 1.0.9.6), libc6 (>= 2.15), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.9), debian-archive-keyring, gnupg
Suggests: aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), apt-doc, python-apt
Conflicts: python-apt (<< 0.7.93.2~)
Breaks: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
Description-en: commandline package manager
 该软件包提供了用于
 搜索、管理以及以低层次访问
 libapt-pkg 库的全部功能来查询
 软件包信息的命令行工具。
 .
 它包括:
  * apt-get,用于从已验证的源获取软件包
 和相关信息并对软件包及其依赖进行安
 装、升级和删除
  * apt-cache,用于查询已安装和可安
 装软件包的可用信息
  * apt-cdrom,用于将可移除式介质作为软件包的源
  * apt-config,作为设置配置的一个界面
  * apt-key,作为管理验证密钥的一个界面
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, devel::lang:ruby, hardware::storage,
 hardware::storage:cd, implemented-in::c++, implemented-in::perl,
 implemented-in::ruby, interface::commandline, network::client,
 protocol::ftp, protocol::http, protocol::ipv6, role::program,
 role::shared-lib, scope::application, scope::utility, sound::player,
 suite::debian, use::downloading, use::organizing, use::searching,
 works-with::audio, works-with::software:package, works-with::text
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_1.0.9.6_amd64.deb
Size: 1107560
MD5sum: a325ccb14e69fef2c50da54e035a4df4
SHA1: 635d09fcb600ec12810e3136d51e696bcfa636a6
SHA256: 371a559ce741394b59dbc6460470a9399be5245356a9183bbeea0f89ecaabb03

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 appropriate versions fulfilling the dependencies of the package to be installed. 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.15” (written “libc6 (>= 2.15)”). 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 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 will refuse to install a package if it triggers a conflict with an already installed package, except if the new package specifies that it will “replace” the installed package, in which case dpkg will choose to replace the old package with the new one. apt always follows your instructions: if you choose to install a new package, it will automatically offer to uninstall the package that poses a problem.

5.2.1.3. 不相容性:中断字段

中断字段有一个影响和冲突字段类似,但它具有特殊的意义。它标志着一个包的安装会将另外一个包(或者是特定版本)中断掉。通常而言,两个包之间的不兼容是短暂的,中断关系会特别指出那些不兼容的版本。
dpkg will refuse to install a package that breaks an already installed package, and apt will try to resolve the problem by updating the package that would be broken to a newer version (which is assumed to be fixed and, thus, compatible again).
不向后兼容的更新可能会发生这种情况:如果新版本与旧版本的功能不在另一个程序中做特别规定,这将导致故障。中断字段会防止用户继续运行从而遇到这些问题。

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. A conflict between a package and 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 also 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.20 present in Jessie). 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. Past Limitations
Virtual packages used to suffer from some limitations, the most significant of which was 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, would never be considered as satisfied by the packaging system — while in fact it most likely is satisfied. Unaware of this, the package system chose the least risky option, assuming that the versions do not match.
该限制已经在 dpkg 1.17.11 中解除,在 Jessie 中不再相关。软件包可以给提供依赖的虚拟包指定一个版本,如 Provides: libdigest-md5-perl (= 1.8)

5.2.1.5. 替换文件:替换字段

The Replaces field indicates that the package contains files that are also present in another package, but that the package is legitimately entitled to replace them. Without this specification, dpkg fails, stating that it can not overwrite the files of another package (technically, it is possible to force it to do so with the --force-overwrite option, but that is not considered standard operation). This allows identification of potential problems and requires the maintainer to study the matter prior to choosing whether to add such a field.
当软件包名称变更时,或者当一个软件包包含在另外一个的时候,此字段的使用是合理的。这也发生在维护者决定从来自相同的源码包的大量二进制包里分发出文件:一个替换的文件不再属于旧的软件包,只有新的才属于。
如果已安装软件包的所有文件都被替换了,那么该软件包将认为将被删除掉。最后,这个字段会鼓励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 configure 最近一次配置的版本号 对软件包进行配置。

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 dpkg --verify (which we will study in 第 14.3.3.1 节 “Auditing Packages with dpkg --verify) 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来编辑该文件,并试图重新恢复相关的修改(之前被验证的差异)。