Debian 管理员手册 5.4. 通过dpkg来操作软件包

站群域名注册整理:dpkg is the base command for handling Debian packages on the system. If you have .deb packages, it is dpkg that allows installation or analysis of their contents. But this program only has a partial view of the Debian universe: it knows what is installed on the system, and whatever it is given on the command line, but knows nothing of the other available packages. As such, it will fail if a dependency is not met. Tools such as apt and aptitude, on the contrary, will create a list of dependencies to install everything as automatically as possible.

说明 dpkg 或 apt?

dpkg 应视为系统工具 (背景) 之一,而 apt 则是较倾向用户的工具,可克服前者的限制。这些工具各有其限制,共同解决特定的作业。

5.4.1. 安装软件包

首先,dpkg 是安装 Debian 已经可用软件包的工具 (因为不需下载任何东西)。我们使用它的 -i 或 --install 选项。

例 5.2. 通过dpkg来安装一个软件包

# dpkg -i man-db_2.8.5-2_amd64.deb

(Reading database ... 14913 files and directories currently installed.)

Preparing to unpack .../man-db_2.8.5-2_amd64.deb ...

Unpacking man-db (2.8.5-2) over (2.8.5-2) ...

Setting up man-db (2.8.5-2) ...

Updating database of manual pages ...

Processing triggers for mime-support (3.62) ...

We can see the different steps performed by dpkg; we know, thus, at what point any error may have occurred. The installation can also be effected in two stages: first unpacking, then configuration. apt takes advantage of this, limiting the number of calls to dpkg (since each call is costly, due to loading of the database in memory, especially the list of already installed files).

例 5.3. 分开解压和配置

# dpkg --unpack man-db_2.8.5-2_amd64.deb

(Reading database ... 14937 files and directories currently installed.)

Preparing to unpack man-db_2.8.5-2_amd64.deb ...

Unpacking man-db (2.8.5-2) over (2.8.5-2) ...

Processing triggers for mime-support (3.62) ...

# dpkg --configure man-db

Setting up man-db (2.8.5-2) ...

Updating database of manual pages ...

有时dpkg在安装软件包的时候会失败并且返回一个错误;如果用户命令dpkg忽略掉这个错误,那么它仅仅会提示一个警告;这也就是我们有一个不同的--force--*选项。dpkg --force-help,或者是dpkg的帮助文档,有一个这些选项的详细清单。最常见的错误是,你迟到会遇到这样一个文件冲突,当一个软件包包含的文件中已经安装了另外一个软件包。:

Unpacking libgdm (from .../libgdm_3.8.3-2_amd64.deb) ...

dpkg: 处理 /var/cache/apt/archives/libgdm_3.8.3-2_amd64.deb (--unpack) 时发生错误:

试图覆写 '/usr/bin/gdmflexiserver',也同时在软件包 gdm3 3.4.1-9 内

在这种情况下,如果你认为文件替换该文件可能不会对系统的稳定性造成重大的风险(通常情况下),你可以使用--force-overwrite选项来告诉dpkg去忽略这个错误并且覆盖该文件。

当然这里有非常多的--force-*选项,只是--force-overwrite使用的非常频繁。这些选项仅存在特殊的情况下,所以最好是不去使用它们以便遵守软件包的管理机制。不要忘了,这些管理规则可以确保你的系统的稳定性和一致性。

注意 使用--force-*的影响

若不小心使用 --force-* 的选项,可能造成 APT 命令家族拒绝运作的困境。在相依性不足或冲突的情况下,使用部分选项后,仍可安装该等软件包。结果就是相依性不足的不一致系统,APT 命令将拒绝运行任何工作,直到系统恢复一致 (通常包括安装遗失的相依软件包或移除问题软件包)。通常出现以下的消息,安装新版 rdesktop 时忽略其对新版 libc6 的相依性:

# apt full-upgrade

[...]

You might want to run 'apt-get -f install' to correct these.

The following packages have unmet dependencies:

rdesktop: Depends: libc6 (>= 2.5) but 2.3.6.ds1-13etch7 is installed

E: Unmet dependencies. Try using -f.

确信其分析结果的勇敢管理者,可能选择忽略使用 --force-* 选项时发生的相依性问题与冲突。结果是,想要继续使用 apt 或 aptitude 的话,他们必须先编辑 /var/lib/dpkg/status 以删除/修改相依性问题或冲突。

This manipulation is an ugly hack, and should never be used, except in the most extreme case of necessity. Quite frequently, a more fitting solution is to recompile the package that is causing the problem (see 第 15.1 节 “从源码重建安装包”) or use a new version (potentially corrected) from a repository such as the stable-backports one (see 第 6.1.2.4 节 “向后移植到稳定版(Stable Backports)”).

5.4.2. 软件包移除

Invoking dpkg with the -r or --remove option, followed by the name of a package, removes that package. This removal is, however, not complete: all of the configuration files, maintainer scripts, log files (system logs) and other user data handled by the package remain. That way disabling the program is easily done by uninstalling it, and it is still possible to quickly reinstall it with the same configuration. To completely remove everything associated with a package, use the -P or --purge option, followed by the package name.

例 5.4. 移除与清除 debian-cd 软件包

# dpkg -r debian-cd

(Reading database ... 15915 files and directories currently installed.)

Removing debian-cd (3.1.25) ...

# dpkg -P debian-cd

(Reading database ... 15394 files and directories currently installed.)

Purging configuration files for debian-cd (3.1.25) ...

5.4.3. 查询 dpkg 的数据库,并检查 .deb 文件

回到基础 选项的语法

“长” 版 (一个或多个字,前置两个链接号) 与 “短” 版 (一个字母,通常是长版字的第一个字母,前置一个链接号) 软件包都有该等选项。这是 POSIX 标准常见的用法。

做结论前,我们将学习查找内部数据库以获取信息的 dpkg 选项。先给长版的选项再给对应的短版选项 (其参数是一样的) 以 --listfiles 软件包 (或 -L) 为例,列出该软件包安装的文件清单;--search 文件 (或 -S),寻找包括该文件的套性;--status 软件包 (或 -s),显示该软件包的标头;--list (或 -l),显示该系统内软件包清单与安装状态;--contents file.deb (或 -c),列出 Debian 指定软件包清单;--info file.deb (或 -I),列出该软件包的标头。

CAUTION dpkg --search and merged /usr

For various reasons, Debian now installs by default a few top-level directories as symlinks to their counterparts below /usr. For instance, /bin, /sbin and /lib are now symlinks to, respectively, /usr/bin, /usr/sbin and /usr/lib.

While this does provide desirable benefits, it can also be a source of confusion. For example, when you query dpkg which package is owning a given file, it will only be able to answer when you ask for its original path:

$ dpkg --search /bin/mount

mount: /bin/mount

$ dpkg --search /usr/bin/mount

dpkg-query: no path found matching pattern /usr/bin/mount

$ dpkg --search /bin/apt

dpkg-query: no path found matching pattern /bin/apt

$ dpkg --search /usr/bin/apt

apt: /usr/bin/apt

例 5.5. dpkg的各种查询

$ dpkg -L base-passwd

/.

/usr

/usr/sbin

/usr/sbin/update-passwd

/usr/share

/usr/share/base-passwd

/usr/share/base-passwd/group.master

/usr/share/base-passwd/passwd.master

/usr/share/doc

/usr/share/doc/base-passwd

/usr/share/doc/base-passwd/README

/usr/share/doc/base-passwd/changelog.gz

/usr/share/doc/base-passwd/copyright

/usr/share/doc/base-passwd/users-and-groups.html

/usr/share/doc/base-passwd/users-and-groups.txt.gz

/usr/share/doc-base

/usr/share/doc-base/users-and-groups

/usr/share/lintian

/usr/share/lintian/overrides

/usr/share/lintian/overrides/base-passwd

/usr/share/man

/usr/share/man/de

/usr/share/man/de/man8

/usr/share/man/de/man8/update-passwd.8.gz

/usr/share/man/es

/usr/share/man/es/man8

/usr/share/man/es/man8/update-passwd.8.gz

/usr/share/man/fr

/usr/share/man/fr/man8

/usr/share/man/fr/man8/update-passwd.8.gz

/usr/share/man/ja

/usr/share/man/ja/man8

/usr/share/man/ja/man8/update-passwd.8.gz

/usr/share/man/man8

/usr/share/man/man8/update-passwd.8.gz

/usr/share/man/pl

/usr/share/man/pl/man8

/usr/share/man/pl/man8/update-passwd.8.gz

/usr/share/man/ru

/usr/share/man/ru/man8

/usr/share/man/ru/man8/update-passwd.8.gz

$ dpkg -S /bin/date

coreutils: /bin/date

$ dpkg -s coreutils

Package: coreutils

Essential: yes

Status: install ok installed

Priority: required

Section: utils

Installed-Size: 15719

Maintainer: Michael Stone

Architecture: amd64

Multi-Arch: foreign

Version: 8.30-3

Pre-Depends: libacl1 (>= 2.2.23), libattr1 (>= 1:2.4.44), libc6 (>= 2.28), libselinux1 (>= 2.1.13)

Description: GNU core utilities

This package contains the basic file, shell and text manipulation

utilities which are expected to exist on every operating system.

.

Specifically, this package includes:

arch base64 basename cat chcon chgrp chmod chown chroot cksum comm cp

csplit cut date dd df dir dircolors dirname du echo env expand expr

factor false flock fmt fold groups head hostid id install join link ln

logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup nproc numfmt

od paste pathchk pinky pr printenv printf ptx pwd readlink realpath rm

rmdir runcon sha*sum seq shred sleep sort split stat stty sum sync tac

tail tee test timeout touch tr true truncate tsort tty uname unexpand

uniq unlink users vdir wc who whoami yes

Homepage: http://gnu.org/software/coreutils

$ dpkg -l 'b*'

Desired=Unknown/Install/Remove/Purge/Hold

| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend

|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)

||/ Name Version Architecture Description

+++-====================-===============-===============-==================================================

un backupninja (no description available)

un backuppc (no description available)

un baobab (no description available)

un base (no description available)

un base-config (no description available)

ii base-files 11 amd64 Debian base system miscellaneous files

ii base-passwd 3.5.46 amd64 Debian base system master password and group files

ii bash 5.0-4 amd64 GNU Bourne Again SHell

[..]

$ dpkg -c /var/cache/apt/archives/gnupg-utils_2.2.12-1_amd64.deb

drwxr-xr-x root/root 0 2018-12-15 02:17 ./

drwxr-xr-x root/root 0 2018-12-15 02:17 ./usr/

drwxr-xr-x root/root 0 2018-12-15 02:17 ./usr/bin/

-rwxr-xr-x root/root 3516 2018-12-15 02:17 ./usr/bin/gpg-zip

-rwxr-xr-x root/root 866256 2018-12-15 02:17 ./usr/bin/gpgcompose

-rwxr-xr-x root/root 30792 2018-12-15 02:17 ./usr/bin/gpgparsemail

-rwxr-xr-x root/root 84432 2018-12-15 02:17 ./usr/bin/gpgsplit

-rwxr-xr-x root/root 154952 2018-12-15 02:17 ./usr/bin/gpgtar

-rwxr-xr-x root/root 166568 2018-12-15 02:17 ./usr/bin/kbxutil

-rwxr-xr-x root/root 1081 2017-08-28 12:22 ./usr/bin/lspgpot

-rwxr-xr-x root/root 2194 2018-11-18 23:37 ./usr/bin/migrate-pubring-from-classic-gpg

-rwxr-xr-x root/root 121576 2018-12-15 02:17 ./usr/bin/symcryptrun

-rwxr-xr-x root/root 18424 2018-12-15 02:17 ./usr/bin/watchgnupg

drwxr-xr-x root/root 0 2018-12-15 02:17 ./usr/sbin/

-rwxr-xr-x root/root 3075 2018-12-15 02:17 ./usr/sbin/addgnupghome

-rwxr-xr-x root/root 2217 2018-12-15 02:17 ./usr/sbin/applygnupgdefaults

drwxr-xr-x root/root 0 2018-12-15 02:17 ./usr/share/

drwxr-xr-x root/root 0 2018-12-15 02:17 ./usr/share/doc/

[...]

$ dpkg -I /var/cache/apt/archives/gnupg-utils_2.2.12-1_amd64.deb

new Debian package, version 2.0.

size 857408 bytes: control archive=1844 bytes.

1564 bytes, 32 lines control

1804 bytes, 28 lines md5sums

Package: gnupg-utils

Source: gnupg2

Version: 2.2.12-1

Architecture: amd64

Maintainer: Debian GnuPG Maintainers

Installed-Size: 1845

Depends: libassuan0 (>= 2.0.1), libbz2-1.0, libc6 (>= 2.25), libgcrypt20 (>= 1.8.0), libgpg-error0 (>= 1.26-2~), libksba8 (>= 1.3.4), libreadline7 (>= 6.0), zlib1g (>= 1:1.1.4)

Recommends: gpg, gpg-agent, gpgconf, gpgsm

Breaks: gnupg (<< 2.1.21-4), gnupg-agent (<< 2.1.21-4)

Replaces: gnupg (<< 2.1.21-4), gnupg-agent (<< 2.1.21-4)

Section: utils

Priority: optional

Multi-Arch: foreign

Homepage: https://www.gnupg.org/

Description: GNU privacy guard - utility programs

GnuPG is GNU's tool for secure communication and data storage.

.

This package contains several useful utilities for manipulating

OpenPGP data and other related cryptographic elements. It includes:

.

* addgnupghome -- create .gnupg home directories

* applygnupgdefaults -- run gpgconf --apply-defaults for all users

* gpgcompose -- an experimental tool for constructing arbitrary

sequences of OpenPGP packets (e.g. for testing)

* gpgparsemail -- parse an e-mail message into annotated format

* gpgsplit -- split a sequence of OpenPGP packets into files

* gpgtar -- encrypt or sign files in an archive

* kbxutil -- list, export, import Keybox data

* lspgpot -- convert PGP ownertrust values to GnuPG

* migrate-pubring-from-classic-gpg -- use only "modern" formats

* symcryptrun -- use simple symmetric encryption tool in GnuPG framework

* watchgnupg -- watch socket-based logs

[..]

更进一步 版本的对比

因为 dpkg 是处理 Debian 软件包的程序,它也能够逻辑地比较版本编号。所以有 --compare-versions 选项,以外部程序使用它 (尤其是被 dpkg 本身运行的配置脚本)。这个选项需要三个参数:版本编号、比较操作数、以及第二个版本编号。可能的操作数为 lt (小于)、le (大于或等于)、eq (等于)、ne (不等于)、ge (大于或等于)、以及 gt (大于)。若比较结果正确,dpkg 送回 0 (成功);若不正确,则送回 0 以外的数值 (表示失败)。

$ dpkg --compare-versions 1.2-3 gt 1.1-4

$ echo $?

0

$ dpkg --compare-versions 1.2-3 lt 1.1-4

$ echo $?

1

$ dpkg --compare-versions 2.6.0pre3-1 lt 2.6.0-1

$ echo $?

1

注意前例最后一个比较的失败:dpkg、pre,表示为预发布版,没有特别的意义,此程序以比较数字版本 (a < b < c ...) 相同的方式比较字顺版本。所以,“0pre3” 大于 “0”。我们以毛毛虫 “~” 表示该软件包的预发布版:

$ dpkg --compare-versions 2.6.0~pre3-1 lt 2.6.0-1

$ echo $?

0

5.4.4. dpkg的日志文件

dpkg 把所有的交易记录存在名为 /var/log/dpkg.log 的日志档。这个日志档的内容颇为详尽且啰唆,记录软件包被 dpkg 处理的每个进程。追踪 dpkg 的每个作为之外,日志档还保留系统发展的记录:可以覆查每个软件包的安装与移除步骤,对于了解最近的变动极有帮助。此外,还记录所有的版本,可以交互检查 changelog.Debian.gz 的内容,查看有问题的软件包或在线的错误报告。

5.4.5. 多架构支持

所有的 Debian 包在它们的管控信息中都有一个架构 字段。该字段可包含:“全部“(对与架构无关的包),或者它的目标架构名称(如“amd64”, “armhf”,…)。对于后者,默认情况下,dpkg将只能接受安装与主机架构匹配的软件包,主机架构可通过dpkg --print-architecture来获得。

该限制确保用户不会因为错误架构编译的二进制文件而挂掉。一切都很完美,除了(某些)计算机可以运行多架构的二进制文件,或者以本地方式(“amd64“系统可运行”i386“二进制文件)运行,或者以模拟器运行。

5.4.5.1. 启用多架构

dpkg的多架构支持允许用户定义可安装于当前系统的“异质架构” 。这可以方便的通过 dpkg --add-architecture完成,如下例。有一相应的 dpkg --remove-architecture 以放弃对异质架构的支持,但仅可用于未余留该架构软件包的情况。

# dpkg --print-architecture

amd64

# dpkg --print-foreign-architectures

# dpkg -i gcc-8-base_8.3.0-6_armhf.deb

dpkg: error processing archive gcc-8-base_8.3.0-6_armhf.deb (--install):

package architecture (armhf) does not match system (amd64)

Errors were encountered while processing:

gcc-8-base_8.3.0-6_armhf.deb

# dpkg --add-architecture armhf

# dpkg --add-architecture armel

# dpkg --print-foreign-architectures

armhf

armel

# dpkg -i gcc-8-base_8.3.0-6_armhf.deb

(Reading database ... 14319 files and directories currently installed.)

Preparing to unpack gcc-8-base_8.3.0-6_armhf.deb ...

Unpacking gcc-8-base:armhf (8.3.0-6) ...

Setting up gcc-8-base:armhf (8.3.0-6) ...

# dpkg --remove-architecture armhf

dpkg: error: cannot remove architecture 'armhf' currently in use by the database

# dpkg --remove-architecture armel

# dpkg --print-foreign-architectures

armhf

备注 APT 的多架构支持

APT will automatically detect when dpkg has been configured to support foreign architectures and will start downloading the corresponding Packages files during its update process.

异质软件包可通过 apt install 软件包: 架构安装。

实例 在 amd64 架构上使用专有 i386 二进制文件

There are multiple use cases for multi-arch, but the most popular ones are the possibility to execute (sometimes proprietary) 32 bit binaries (i386) on 64 bit systems (amd64), and the possibility to cross-compile software for a platform or an architecture different from the host one.

5.4.5.2. 多架构相关的变更

To make multi-arch actually useful and usable, libraries had to be repackaged and moved to an architecture-specific directory so that multiple copies (targeting different architectures) can be installed alongside. Such updated packages contain the “Multi-Arch: same” header field to tell the packaging system that the various architectures of the package can be safely co-installed (and that those packages can only satisfy dependencies of packages of the same architecture). The most important libraries have been converted since the introduction of multi-arch in Debian 7 Wheezy, but there are many libraries that will likely never be converted unless someone specifically requests it (through a bug report for example).

$ dpkg -s gcc-8-base

dpkg-query: error: --status needs a valid package name but 'gcc-8-base' is not: ambiguous package name 'gcc-8-base' with more than one installed instance

Use --help for help about querying packages.

$ dpkg -s gcc-8-base:amd64 gcc-8-base:armhf | grep ^Multi

Multi-Arch: same

Multi-Arch: same

$ dpkg -L libgcc1:amd64 |grep .so

/lib/x86_64-linux-gnu/libgcc_s.so.1

$ dpkg -S /usr/share/doc/gcc-8-base/copyright

gcc-8-base:amd64, gcc-8-base:armhf: /usr/share/doc/gcc-8-base/copyright

值得注意的是,Multi-Arch: same软件包需具备能够明晰识别架构的名称。它们也能够与相同包的其他实例共享文件;dpkg确保所有的包在共享时具有逐位对应识别的文件。最后但并非最不重要的,一个包的所有实例必须为相同版本。它们必须同时升级。

多架构支持也带来了在依赖处理方式上的一些有趣的挑战。要满足依赖,需要:或者有Multi-Arch: foreign标识的软件包,或者架构上能匹配已声明依赖的软件包(在该依赖方案处理中,架构无关包假定为同样架构,而非主机架构)。通过 软件包 :any语法,依赖可以被弱化,以便允许任意架构能够满足依赖,但异质软件包仅能满足如下依赖:有“ Multi-Arch: allowed ”标识的依赖。