Linux:如何在 apt 崩溃时使用 dpkg 修复它

你曾经坏过吗?对于经验丰富的 Linux 专业人士来说,无意中破坏 apt 是很常见的(大约每半年一次)。如果您知道 dpkg 中的一些命令,通常可以更轻松地解决问题!找出方法。
什么是 apt 和 dpkg?
如果您使用的是基于 Debian 的发行版,例如 Ubuntu 或 Mint,您的计算机会使用 apt 来处理包。 Apt 代表 Advanced Packaging Tool,它允许您安装、卸载、清除和管理 Debian 软件包。
除了 apt
(在命令行中使用)之外,您的计算机可能还有更高级别/总体的基于桌面的包管理器,它只使用 apt
,或者可能是 dpkg
,在后台。
Debian 的包管理器 dpkg
是在基于 Debian 的安装上管理包的替代方法。它比 apt
级别低得多,给了你更多的自由,但也带来了更高的破坏风险。
这就是为什么(除非您是经验丰富的 DevOps 工程师)我建议您始终使用 apt
,并在遇到问题时立即使用 dpkg
扩充它.
采取这种循序渐进的方法可以让您两全其美:apt
包管理器的稳定性和易用性,以及 dpkg
Debian 包管理器的功能和粒度,一旦你需要它。
例如,假设您有一个刚刚安装的包,它以某种方式最终破坏了 apt
。或者,也许软件包安装意外中断。
不管是什么原因,apt
现在被认为是损坏的,并且您已经尝试过 sudo apt update --fix-missing
和 sudo apt install --fix -broken
无济于事。如果是这样,那么……
欢迎来到 dpkg
当您的 apt
损坏时,就没有乐趣了。如果它真的坏了,那就更没意思了。即使有人知道他们在做什么,有时也需要一定的艺术水平,而且绝对是技巧,才能修复损坏的包装系统。
“艺术”一词非常适用,因为您在执行各种故障排除步骤时会有一种感觉或感觉——尤其是如果您经常这样做的话——在重启过程中是否会出现问题。
风险始终是打包系统严重损坏,如果您重新启动,您的 Linux 实例可能不会再次出现,并且可能需要进一步且可能更复杂的故障排除。
我想在这一点上声明,所有这一切都可以通过执行一些简单的命令轻松避免——但遗憾的是,事实并非如此。事实上,您知道的越多,修复起来就越容易,您就越有信心弄清楚您是否已准备好进行系统重启。
这是我们来到 dpkg
的地方。 dpkg
程序允许我们对所有已安装的软件包进行更精细的控制,虽然出现问题的风险更大,但也有更多的力量可以完全按照我们想要的方式更改系统。让我们开始吧。
如果您总体上对 Linux 感兴趣,您可能还想阅读我们的 Bash 自动化和脚本编写系列(三部分)。
基本 dpkg 用法
我们可以通过简单地执行 dpkg -l
来查看当前系统上的包。由于输出可能非常冗长(尽管通常是分页的),您可以使用 grep
来限制结果。
dpkg -l | head -n5 && dpkg -l | grep 'gnome-calculator'
dpkg -l | grep 'gnome-calculator'

第一个命令实际上是两个命令的组合(用&&
分隔,字面意思是:只有在第一个命令成功时才执行第二个命令)。
在这两个命令的第一个中,我们获取前五行(使用管道 |
和 head -n5
),然后在第二个命令中,我们寻求列出我们正在搜索的输出。在本例中,我们正在搜索文本 gnome-calculator
。
它下面的辅助行/命令显示了我们通常使用的版本。一旦有人熟悉了 dpkg
输出的语法,通常就不需要前五行了。请注意,第一列(视觉上)指的是 Desired=
,第二列指的是 Status=
,第三列指的是 Err?=
。如果您目视这些线,您会看到它们是如何快速连接的。
由于我们的 gnome-calculator
已成功安装且没有任何当前错误,因此 Err?=
下没有第三列代码。我们还注意到这里 uppercase=bad
写在与第三列相关的简短信息中。如前所述,在我们的例子中,它是空白的。
第一列显示所需状态,第二列显示当前状态。两者分别显示为i
(Install[ed]
和Inst[alled]
,而这个(ii
)是您将(想要)看到的最常见序列。它基本上意味着一切正常,包已安装,没有任何问题
。
另请注意,在括号之间的列描述中,大写字母表示看到的任何可能字母与相关术语之间的联系。例如,考虑 f
如何引用 halF-conf
,注意其中的大写 F
。
现在让我们看一下要比较的另一个输出。这一次,我们将省略前五行,即使没有标题,您也可以更习惯地阅读输出。
dpkg -l | grep 'mintwelcome'

在这里,我们看到了 rc
的有趣结果,其中 ii
曾经是 gnome-calculator
。如果您在上面看到的第一个 Desired=
列描述中搜索 r
,您会看到它代表 Remove[d]
,第二列中的 c
代表 Conf-files
。
啊哈!这个(mintwelcome
,Mint 上的欢迎包)是我们在某个时候卸载的包,但相同的配置文件仍然存在。让我们清除它!
dpkg --purge 'mintwelcome'
sudo dpkg --purge 'mintwelcome'
dpkg -l | grep 'mintwelcome'

请注意,您也可以使用 -P
简写而不是使用 --purge
。
在第一个命令中,我们可以尝试在不使用 sudo
的情况下清除 mintwelcome
。但是,这是行不通的。您需要超级用户/root 级别的权限才能卸载(或安装或清除)包。我们可以使用 sudo
再次运行,我们的包将被清除。
请注意,apt
和 dpkg
都使用术语 purge 来表示我们想要完全清除一个包,而不是仅仅卸载它,这将留下任何配置文件。
确保
我相信您可能会开始欣赏 dpkg
在管理基于 Debian 的发行版(例如 Ubuntu,在本例中为 Mint)上的软件包时可以为您提供的强大功能、控制力和粒度。例如,通过简单地执行以下命令来扫描以前卸载的软件包的配置文件剩余部分会很容易:
dpkg -l | grep '^rc'

在删除任何此类配置文件之前,您需要加倍确保没有安装具有相似名称的包。例如,在这种情况下,我们可以运行:
dpkg -l | grep 'javascript'

请注意我们如何删除 javascript-common
的第二部分以搜索 javascript
。
是否安全移除?你可以看到,强大的力量伴随着巨大的责任而来,这在生活中一如既往。删除与否的决定权在您。在使用 dpkg
时,通常要牢记三件事:
首先,您需要检查、仔细检查和三次检查以确定。例如,在上面的第一个输出中,我们可能已经继续并漫不经心地删除了 javascript-common
而没有检查系统上是否还有任何其他 Javascript 包。
这是最好的行动方案吗?也许吧,但是我们一进行第一次检查,确定性/置信度肯定就下降了,因为系统上肯定还有其他 Javascript 包。
另外,请注意这里确实没有任何损坏。保留这个看似已删除的软件包的配置文件就可以了。 “如果它没坏,就不要修理它”这句古老的格言似乎肯定适用于这种情况。在使用 dpkg
时要牢记这一点。
其次,重要的是要记住 apt
是一个包管理器,它在安装时 记住 包之间的所有连接(即版本和依赖项),卸载或清除软件包。
dpkg
不是这种情况,它更基于包。粒度更细,但破坏事物的风险也更大。如果一个包依赖于另一个包或依赖于一个库,那么肯定有人会通过使用 dpkg
卸载主包来简单地破坏它。
第三,大多数Linux 软件包都有许多 依赖项。因此,不建议简单地使用 dpkg
进行标准包管理,重申我们最初的建议,默认使用 apt
并在它成为时切换到 dpkg
必要的。
要删除/卸载包而不是清除它(即保留配置文件),您可以使用 --remove
(或 -r
)选项到 dpkg
。要验证包,请使用 --verify
(或 -V
)。针对包的 --audit
(或 -C
)选项对包(如果未指定包,则对所有包)进行数据库完整性和一致性检查。
有关更多选项,请参阅从终端执行的 man dpkg
。还有一些特定的、更复杂的命令可用于解决各种打包系统问题。对于这些,通常最好使用您最喜欢的搜索引擎来搜索发生时看到的特定问题或情况。通常,其他人已经遇到过它并记录了细节。如果您有新发现,请花几分钟时间将您的发现记录在某个论坛或相关讨论帖中。
包起来
在本文中,我们开始探索 dpkg
以及它如何帮助我们进行精细的包管理,这与处理包及其所有依赖项的 apt
不同。请记住,在这些复杂的包管理问题调试情况下,能力越大责任越大。
我们还研究了如何遵循更规避风险的方法,同时意识到深入的包管理调试类似于艺术,画家越好,绘画越成功——咳咳,重启。