如何查找已安装的 Debian 软件包列表而不包含其依赖项?

如何查找已安装的 Debian 软件包列表而不包含其依赖项?

我试图比较两个 debian 11 系统(服务器 1 和服务器 2)、一个 debian 9 和一个 11 系统(服务器 3 和服务器 2),并确保它们具有相同的软件包。我打算使用 ansible 安装缺少的软件包。

我在看Debian 在哪里存储已安装软件包的列表?但它不显示 apt 软件包版本,也显示依赖项。我只需要 system1 上安装的带有版本号的 debian 软件包,这样我就可以在 system2 上进行比较并安装缺少的软件包。

答案1

apt-mark showmanual

将列出所有手动安装的软件包,IE显式安装的软件包,而不是作为依赖项拉入(并保持安装)的软件包。

要获取相应的版本,请使用

dpkg-query -W $(apt-mark showmanual)

但是,您无法使用它来可靠地将包选择从一个系统复制到另一个系统,因为依赖性计算将在不同的时间点产生不同的结果(随着包依赖性的发展)。这意味着,apt与几个月或几年前相比,现在要求安装一组软件包不会在系统上产生完全相同的结果 - 它可能产生相同的结果,特别是如果两个系统都是使用相同的 Debian 基本版本安装的,但您不能依赖它来这样做。

还要注意,依赖特定版本并不是那么有用:apt只能安装存储库中当前可用的任何版本,因此除非您在“源”系统上保留了包含版本的存储库,否则知道那里安装了哪些版本不会提供有关目标的可操作信息。也可以看看为什么以前版本的 Debian 软件包会在软件包存储库中消失? (与版本控制系统配置高度相关)

您确实应该使用中描述的方法之一如何将已安装的软件包选择从一个 Debian 系统复制到另一个 Debian 系统? (Debian 喘息)— 本质上,用于dpkg --get-selections列出所有包“选择”,然后dpkg --set-selectionsapt-get dselect-upgrade它们应用到目标系统上。

答案2

基本的方法是:

dpkg -l | awk '/^ii/ {print $2}'

它返回所有已安装软件包的列表(这就是 ^ii 的用途)。

这不包括版本号,但无论如何您都无法根据版本号进行安装,因为这些版本号可能在正在使用的存储库的软件包池中发生了变化。

我不清楚为什么你认为你需要版本号,因为你只能在运行 apt-get update 后才能实际安装 apt 中的版本,并且由于两个系统都是 Debian 11,因此它们将具有相同的版本池中的软件包数量,除非他们使用第 3 方存储库或其他东西。

您可以为每个系统生成一个列表,然后仅安装未出现在目标计算机列表中的软件包。

当我使用脚本进行类似的操作时,我会使其更加健壮,因此我会根据源系统列表测试目标系统上是否安装了软件包,并且仅在不存在的情况下安装,但您必须在循环,因为如果由于某种原因该包在目标系统的存储库中不可用,那么整个事情都会失败,除非您一一执行它们。

明确的方法是生成两个列表,创建一个小的差异列表,不在目标系统上的包,然后循环遍历该小列表并一一安装它们。循环会解决孤立的问题,因为安装只会失败,并且它将继续执行列表中的下一个。

Bash 比较两个列表找到缺失的项目

其中有一个如何仅与 Bash 比较列表的示例,但它比您想要的要复杂一些。

像这样的事情,我认为你最好使用完整的脚本来完成这项工作,我个人会用 Perl 来做,但它可以是你喜欢用于此类事情的任何东西。

创造孤儿

另一个问题是,这将逐一安装缺少的软件包,其中可能包括各种依赖项,但也可能包括您不想要的孤立软件包。

例如,如果系统经历了多次升级到下一个 Debian 稳定版本,则可能会出现孤立软件包,这可能会留下无法删除的孤立软件包。

这种方法的主要缺点是您实际上不想安装软件包的依赖项,因为这些软件包可能会更改或获得新版本,那么它们将被孤立,但不会被 apt autoremove 删除,因为您已经明确安装了它们,因此它们是标记为显式安装,而不是引入的依赖项。这会更频繁地命中 lib 包,但它也可能会命中其他在安装时引入各种包的东西。

您可以使用更多脚本来解决这个问题,但这会变得很复杂,因此如果目标只是匹配软件包,只需将它们一一安装,直到完成。它确实稍微扰乱了安装,增加了一些混乱,但这是实现这一点的简单方法。

谨慎推荐!

请注意,执行此操作时使用 --no-install-recommends 非常重要,否则您最终会陷入真正的混乱。由于这个原因,我总是将我的系统配置为永远不会安装推荐。 Recommends 可以轻松地以菊花链方式连接到真正失控的东西,我在网上看到了一些示例,其中在不使用 --no-install-recommends 时安装单个小型 CLI 程序,由于菊花链,它试图拉入数百兆字节的包问题。

例如,在 /etc/apt/apt.conf.d/ 中有一些文件,例如 80basics,您可以在其中添加以下行:

APT::Install-Recommends "0";
APT::Install-Suggests "0";
APT::AutoRemove::SuggestsImportant "false";
APT::AutoRemove::RecommendsImportant "false";

我从未见过任何我想要自动安装推荐或建议的情况。

可能是更好的方法来做到这一点

我猜想有更好的方法来做到这一点,因为这是同步系统的标准问题,也许某些本机 Debian 工具或某些第 3 方工具可以做到这一点,如果这样的事情没有发生,我会感到惊讶不存在,虽然我不知道。

答案3

另一个dpkg答案的变体是:

dpkg-query -W

它输出包名称和包版本的排序列表。每行都有包名称、制表符和包版本字符串。您可以添加一个 glob 表达式(用单引号)作为选项的参数,以-W将列表减少到匹配的包名称(例如,名称中dpkg-query -W '*apt*'包含的包),或者您可以通过管道将输出传递到or或来过滤行,或将输出重定向到文件并使用文本编辑器读取它。aptgrepawksedcat

相关内容