
在 Ubuntu 或 Debian 上使用 apt 安装软件时,包管理器会在后台悄悄调用 dpkg 来完成实际工作。dpkg 是底层工具,负责解包并安装 .deb 文件、维护软件包数据库,并处理卸载与清除。当你手头有一个不在仓库中的本地 .deb 文件、需要查询某个软件包安装了哪些文件,或想找出系统中某个文件属于哪个软件包时,直接掌握 dpkg 的用法非常有用。
语法
dpkg [OPTIONS] COMMAND [ARGUMENTS]
安装、卸载、清除和配置操作需要 sudo 权限,因为它们会修改系统目录和软件包数据库。而查询类命令,如 dpkg -l、dpkg -L、dpkg -S 和 dpkg -s,通常无需 root 权限即可运行。
开始前无需安装任何东西。dpkg 在每个基于 Debian 的发行版中都标记为 Essential: yes 且 Priority: required,这意味着它随基础系统一同提供,且 apt 不允许你卸载它。如果下面的命令提示找不到,你几乎肯定使用的是采用其他包管理器(如 rpm 或 pacman)的发行版。
安装软件包
要安装本地的 .deb 文件:
sudo dpkg -i package.deb
dpkg 解包归档、运行维护者脚本,并将软件包登记到数据库中。如果软件包存在未满足的依赖,安装会在配置完成前停止,下一节将介绍如何处理。
当多个文件相互依赖时,可一次性传入多个文件,因为 dpkg 会先全部解包,再统一配置:
sudo dpkg -i *.deb
若只想解包而不运行配置步骤,可使用 sudo dpkg --unpack myapp.deb,之后再使用 sudo dpkg --configure myapp 配置。
对于大多数本地 .deb 安装,apt install ./package.deb 更方便,因为它能在同一步骤中解析依赖。当你确实需要底层包操作时,才使用 dpkg -i。
解决依赖错误
dpkg 只安装你交给它的那个文件。它不会查看仓库,也不会下载任何东西,因此存在未满足依赖的软件包会中途停止:
dpkg: dependency problems prevent configuration of myapp: myapp depends on libfoo1 (>= 1.2.0); however: Package libfoo1 is not installed. dpkg: error processing package myapp (--install): dependency problems - leaving unconfigured Errors were encountered while processing: myapp
请仔细阅读,因为软件包并未被移除。文件已解包、软件包已登记,但配置步骤从未运行。在你完成之前,apt 会拒绝处理任何其他事务。
解决方法是让 apt 补上 dpkg 无法提供的部分:
sudo apt install -f
apt 读取未配置的软件包,从你的仓库拉取缺失的依赖,然后重新运行失败的那一步配置。sudo apt --fix-broken install 是同一命令的完整写法。
你也可以在最初就通过 apt 安装该文件,从而在任何解包操作之前先解析依赖:
sudo apt install ./myapp.deb
./ 前缀很重要。没有它,apt 会把 myapp.deb 当作要在仓库中查找的软件包名。关于修复软件包状态的更多内容,请参阅 APT 与 dpkg 锁错误 指南。
卸载软件包
要卸载软件包但保留其配置文件:
sudo dpkg -r package-name
要同时卸载软件包并删除其配置文件(彻底清除):
sudo dpkg -P package-name
当你想要干净地移除且不留任何配置残留,或计划以全新配置重新安装时,使用 -P。这些命令对应的 apt 写法,请参阅 在 Ubuntu 上卸载软件包 指南。
重新安装软件包
当某个二进制文件被意外删除、配置文件被改坏,或软件包看起来已损坏时,重新安装很有用。dpkg 没有专门的重装标志,因为它并不需要。将一个已安装软件包指向 -i,会把它再次解包到现有文件之上:
sudo dpkg -i myapp.deb
当你磁盘上仍保留着 .deb 时,这种方式有效。对于来自仓库的软件包,可让 apt 获取相同版本并交给 dpkg:
sudo apt install --reinstall nginx
这两条命令默认都不会恢复被删除的、由软件包管理的配置文件。dpkg 将缺失的文件视为有意为之,并保留其缺失状态。要恢复 /etc/nginx/nginx.conf,需重新安装拥有它的 nginx-common 软件包,并加上 confmiss 强制选项:
sudo apt install --reinstall -o Dpkg::Options::
=
"--force-confmiss"
nginx-common
列出已安装软件包
要列出记录在 dpkg 状态数据库中的软件包及其版本和状态:
dpkg -l
输出很宽。每个软件包行以三列状态开头:期望操作、当前软件包状态、错误状态。列表中可能包含带有残留配置文件的已卸载软件包,以及处于不完整状态的软件包,而不仅仅是完全安装的软件包。正常的已安装状态显示为 ii,其后依次是软件包名、版本、架构和描述:
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 +++-==============-====================-============-================================= ii curl 8.5.0-2ubuntu10.13 amd64 command line tool for transferring data ii nginx 1.24.0-2ubuntu7.18 amd64 small, powerful, scalable web/proxy server
第一个 i 表示软件包被选为安装,第二个 i 表示它已安装并配置完成。按名称过滤以缩小输出:
dpkg -l
'nginx*'
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 +++-==============-====================-============-================================= ii nginx 1.24.0-2ubuntu7.18 amd64 small, powerful, scalable web/proxy server ii nginx-common 1.24.0-2ubuntu7.18 all small, powerful, scalable web/proxy server - common files
更多过滤、排序和导出该列表的方法,请参阅 在 Debian 上列出已安装软件包 指南。
列出软件包安装的文件
要查看某个软件包在系统中安装的所有文件:
dpkg -L nginx
/. /usr /usr/sbin /usr/sbin/nginx /usr/share /usr/share/doc /usr/share/doc/nginx /usr/share/doc/nginx/changelog.Debian.gz /usr/share/doc/nginx/copyright /usr/share/man /usr/share/man/man8 /usr/share/man/man8/nginx.8.gz
注意该列表包含二进制文件、更新日志和手册页,但不含配置文件。Debian 软件包经常拆分,nginx 软件包只提供服务器本身,配置则位于单独的软件包中。下面的过滤展示了 nginx-common 中的几个主要配置文件:
dpkg -L nginx-common
|
grep -E
'^/etc/nginx/(fastcgi\.conf|mime\.types|nginx\.conf|sites-available/default)$'
/etc/nginx/fastcgi.conf /etc/nginx/mime.types /etc/nginx/nginx.conf /etc/nginx/sites-available/default
这种拆分正是值得使用 dpkg -L 的原因。当你预期某个文件而软件包未列出它时,通常是一个 -common、-data 或 -doc 配套软件包拥有它。
查找文件所属的软件包
要识别安装某个特定文件的软件包:
dpkg -S /usr/sbin/nginx
nginx: /usr/sbin/nginx
你也可以按模式搜索:
dpkg -S
'*/bin/curl'
curl: /usr/bin/curl
显示软件包详情
要打印已安装软件的完整元数据,包括版本、依赖和描述:
dpkg -s nginx
Package: nginx Status: install ok installed Priority: optional Section: httpd Installed-Size: 1323 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> Architecture: amd64 Version: 1.24.0-2ubuntu7.18 Depends: libc6 (>= 2.34), libssl3t64 (>= 3.0.0), nginx-common (= 1.24.0-2ubuntu7.18) ...
Status 行是首先要读取的字段。install ok installed 表示该软件包已完全安装并配置完成。你卸载但未清除的软件包会显示 deinstall ok config-files,这表示配置文件仍在磁盘上。Installed-Size 以千字节为单位报告。
在不安装的情况下检查 .deb 文件
要在安装前读取 .deb 文件的元数据:
dpkg --info package.deb
new Debian package, version 2.0.
size 1234567 bytes: control archive=2048 bytes.
...
Package: myapp
Version: 2.1.0
Architecture: amd64
...
要列出该软件包将安装的文件,而无需真正安装它:
dpkg --contents package.deb
在不安装的情况下解包
要将 .deb 文件的内容解包到某个目录以供检查:
dpkg -x package.deb /tmp/extracted
目录结构映射了文件在真实系统上的安装位置。
导出与恢复软件包选择状态
要导出 dpkg 的软件包选择状态(便于复制一套系统):
dpkg --get-selections > installed-packages.txt
该文件可包含 install、hold、deinstall 和 purge 状态。在另一台机器上恢复之前,需先将 APT 的软件包元数据复制到 dpkg 的可用软件包数据库中,这样 --set-selections 才能识别尚未安装的软件包:
apt-cache dumpavail
|
sudo dpkg --merge-avail
sudo dpkg --set-selections < installed-packages.txt
在应用前预览将要发生的软件包变更:
sudo apt-get --simulate dselect-upgrade
如果提议的变更正确,应用它们:
sudo apt-get dselect-upgrade
重新配置已安装的软件包
某些软件包在安装时会运行交互式设置。要再次运行该设置:
sudo dpkg-reconfigure package-name
这通常用于重新配置 tzdata(时区变更)、keyboard-configuration 或 locales。
修复损坏的软件包状态
在修复之前,先运行审计以查看哪些软件包处于异常状态:
dpkg -C
The following packages are only half configured, probably due to problems configuring them the first time. The configuration should be retried using dpkg --configure <package> or the configure menu option in dselect: myapp My application
没有输出表示一切正常。
如果系统更新或手动操作导致软件包处于半安装或半配置状态,运行:
sudo dpkg --configure -a
这会处理所有挂起的软件包配置步骤。如果仍有依赖问题,接着运行 sudo apt install -f。
故障排查
dpkg 报告依赖问题:dpkg 会安装你提供的软件包文件,但不会下载缺失的依赖。运行 sudo apt install -f 安装所需软件包并完成挂起的配置。
软件包操作被中断:如果更新或安装在配置完成前停止,运行 sudo dpkg --configure -a。这会恢复挂起的软件包配置脚本。
dpkg 报告错误退出状态 1:失败的是维护者脚本,而非 dpkg 本身。错误上方的那一行会指出软件包和脚本名称,通常是 post-installation script subprocess returned error exit status 1。运行 sudo dpkg --configure -a 重试,并查看失败正上方的输出来找出真正原因——通常是某个服务无法启动或依赖缺失。
dpkg 无法获取锁:另一个包操作正持有数据库锁。请等待它完成,而不是删除锁文件。请参阅 修复 APT 与 dpkg 锁错误 指南。
dpkg 找不到软件包:请使用已安装的软件包名,而非 .deb 文件名。运行 dpkg -l 'pattern*' 查找匹配的已安装软件包,然后将该软件包名用于 dpkg -L、dpkg -s 或 sudo dpkg -r 等命令。
快速参考
如需可打印的快速参考,请参阅 dpkg 速查表。
| 命令 | 说明 |
|---|---|
dpkg -i pkg.deb | 安装本地 .deb 文件 |
dpkg -r package | 卸载软件包(保留配置) |
dpkg -P package | 彻底清除软件包及其配置 |
dpkg --unpack pkg.deb | 仅解包不配置 |
dpkg -l | 列出软件包状态记录 |
dpkg -l 'pattern*' | 过滤软件包状态记录 |
dpkg -L package | 列出软件包安装的文件 |
dpkg -S /path/to/file | 查找文件所属的软件包 |
dpkg -s package | 显示软件包状态与详情 |
dpkg --info pkg.deb | 检查 .deb 文件 |
dpkg --contents pkg.deb | 列出 .deb 中的文件 |
dpkg -x pkg.deb /dir | 不安装解包 .deb |
dpkg --get-selections | 导出软件包选择状态 |
dpkg-reconfigure package | 重新运行软件包配置 |
dpkg -C | 审计损坏状态的软件包 |
dpkg --configure -a | 修复不完整的安装 |
常见问题
dpkg 与 apt 有什么区别?dpkg 处理本地的 .deb 文件和本地软件包数据库。它不了解仓库,也不会解析依赖。apt 是前端,它与仓库通信、计算依赖树、下载所需内容,然后调用 dpkg 完成实际安装。
我需要先安装 dpkg 吗?不需要。dpkg 是每个基于 Debian 的发行版中的基础软件包,因此它已在系统上,且 apt 拒绝卸载它。运行 dpkg --version 确认你拥有的版本。
dpkg -i 是升级软件包还是安装第二份副本?它会就地替换已安装的版本。Debian 打包规则每个架构只允许一个软件包版本,因此 dpkg 将提供的版本解包到现有版本之上并运行软件包维护者脚本。如果文件包含较旧版本,dpkg 会打印降级警告并默认继续,但它不会检查降级是否会破坏另一个软件包的依赖。APT 也能在显式指定旧版本时降级软件包,例如 sudo apt install package-name=version。
dpkg -l 输出中的 ii 是什么意思?第一个字母是你要求的(期望)状态,第二个字母是软件包的实际状态,因此 ii 表示你要求安装它,且它已安装并配置完成。rc 是另一个常见组合:软件包已卸载,但其配置文件仍在磁盘上。第二个字母为大写(如 iU 或 iF)表示软件包已解包或半配置,需要运行 sudo dpkg --configure -a。
结论
dpkg 是基于 Debian 系统上软件包管理的基础。对于日常从仓库安装和更新,apt 是更好的工具,因为它会自动解析依赖。当你需要安装磁盘上的 .deb 文件、审计某个软件包安装了什么,或诊断损坏的软件包状态时,直接动用 dpkg。