dpkg 不解依赖图
一句话总结
apt 是决定安装什么的工具,dpkg 是执行既定安装的工具。理解这种分工,就能立刻明白 dpkg -i 为什么会因依赖错误而停止。
为什么需要这些知识
下载一个 .deb 文件并用 dpkg -i 安装,会看到这样的消息。
dpkg: dependency problems prevent configuration of labhub-extra:
labhub-extra depends on labhub-tool (>= 1.2.0); however:
Package labhub-tool is not installed.
dpkg 不知道软件仓库,也不知道应从哪里下载什么。它只会解开给定文件;如果依赖不满足,就把软件包留在“未配置”状态。因此,apt-get -f install(fix broken)会与它配套使用,含义是“让 apt 查看仓库,继续解决 dpkg 留下的未完成状态”。
它是如何运作的
.deb 文件实际上是一个 ar archive,其中包含三个部分。
| 部分 | 内容 |
|---|---|
debian-binary |
格式版本,通常为 2.0 |
control.tar.* |
control 文件、维护脚本(preinst/postinst/prerm/postrm)、conffiles、md5sums |
data.tar.* |
实际要解压到文件系统的文件 |
安装分为 unpack → configure 两个阶段。unpack 负责解开 data,configure 则执行 postinst,完成注册服务等收尾工作。dpkg -l 输出开头的两个字符表示这种状态。
| 标记 | 含义 |
|---|---|
ii |
请求安装 + 安装完成,状态正常 |
iU |
请求安装 + 只完成 unpack,configure 失败 |
rc |
请求删除 + 仅保留配置文件 |
pn |
未安装,已经 purge |
人们经常忽略 rc 状态。“明明删除了,为什么配置还在?”答案就在这里。
dpkg 的查询命令分为三个方向。
dpkg -l # 무엇이 설치돼 있나
dpkg -L coreutils # 이 패키지가 어떤 파일을 깔았나
dpkg -S /usr/bin/ls # 이 파일은 누가 깔았나
dpkg -s coreutils # 이 패키지의 메타데이터는 무엇인가
dpkg-query -W -f='${Package} ${Version}\n'
第三种(-S)在实际工作中最常使用。在陌生服务器上发现不明 binary 时,它能在一秒内区分该文件是由软件包安装,还是有人手动放置。如果 dpkg -S 找不到任何结果,说明该文件不受包管理;这类文件升级时不会消失,也很容易不在备份范围内。
在实际工作中会是什么样
配置文件冲突。 upgrade 过程中出现 Configuration file '/etc/foo.conf' ... What would you like to do? 提示。dpkg 会记住登记在 conffiles 中的文件 md5,因此能判断是否被人工修改。如果在提示中随意选择“package maintainer's version”,手工加入的全部调优都会消失。自动化脚本应通过 -o Dpkg::Options::="--force-confold" 明确指定策略。
配置文件会受到特殊处理
.deb 中登记于 conffiles 的文件,适用与其他文件不同的规则。不了解这些规则,更新后可能遇到配置消失,或相反地发现新配置没有生效,而二者原因相同。
更新时,dpkg 会比较三项内容:软件包最初安装的内容、当前磁盘中的内容,以及新软件包准备安装的内容。
- 如果我们没有修改,就静默替换为新版本。
- 如果我们修改过,但内容与新版本相同,则不作处理。
- 如果我们修改过,而且与新版本也不同,dpkg 会询问如何处理。非交互模式下,会按默认行为保留我们的文件,并把新文件以
.dpkg-dist名称放在旁边。
第三种情况正是问题所在。自动更新时无人看到这个问题,因此,服务会在我们的旧文件缺少新版本所需配置项的状态下继续运行。 它会悄然采用默认值,日后才表现为异常症状。因此,更新后需要检查是否出现 .dpkg-dist、.dpkg-new、.ucf-dist 文件。
rc 状态与配置文件的关系也可由此解释。如前所述,删除软件包后配置仍然存在,是因为 remove 不处理 conffiles,只有 purge 会一并删除。因此,重新安装同一软件包时,旧配置会再次生效,“明明干净重装,为什么还是同样的问题?”就源于此。
最后,如果打算在软件包之外管理配置文件,最好一开始就使用不在 conffiles 中的独立文件。大多数软件包提供 conf.d/ 之类目录,原因就在这里。该目录中的文件不属于软件包,因此更新不会修改,也不会触发三方比较。
下一次实操要做什么
你将使用 dpkg -L/-S/-s 查询系统,并在 fixture 目录中亲手构建 .deb 文件再完成安装。亲自制作软件包,就能确切理解其中包含什么。