如何列出最小的Debian软件包集合以重新创建已安装的软件包集合?

11
有没有办法让dpkg、apt-get或aptitude生成一个列表,列出需要安装在第二台机器上以复制安装在第一台机器上的软件包?
比如说,如果我已经安装了一个纯净版的Ubuntu服务器,在安装时选择了sshd选项,然后安装了build-essential,我希望输出看起来像这样:
#ubuntu 9.10 server
openssh-sshd
build-essential
据我所知,所有可用的打包工具都会生成一个详细的列表,列出了系统上所有的软件包。 但是我不关心openssh libs、ld、gcc以及sshd和build-essential所依赖的其他软件包,因为当我安装sshd和build-essential时,它们也将被安装。
我只想看到我需要安装的软件包清单,以便在另一台机器上重新创建我的当前软件包集。这是否可能?
4个回答

12

deborphan有点像这样。它会创建一个系统中每个软件包的列表,找出它们彼此之间的依赖关系,并打印出没有任何依赖关系的软件包。默认情况下,它只打印库文件(以便于找到由其他软件包安装但不再需要的库文件,因此得名)。它有大多数你需要做的选项。我运行它的命令如下:

deborphan -anp required --no-show-section

-a 指定所有软件包(而不仅仅是库文件)
-n 忽略“Suggests”或“Recommends”的依赖检查(即仅考虑“Depends”)
-p required 列出所有软件包,无论其优先级如何
--no-show-section 不显示它所在的Debian部分,这只是一项你可能会发现有用的漂亮格式功能。

现在,它可能会错过一些软件包,因为某些软件包存在循环依赖关系。但这种情况相对较少,所以它应该足够接近。


为什么 'deborphan -anp required --no-show-section' 的输出中包含 'gcc',而 'apt-rdepends build-essential' 显示 'build-essential' 依赖于 'gcc'? - fadedbee
它是否显示特定版本的gcc,例如gcc-4.3,还是gcc软件包本身?如果是“gcc”软件包,则可能未安装build-essential。...很抱歉,我没有好的猜测。在我的输出中,我看到了build-essential但没有gcc。 - Eric Warmenhoven

2
dannysauer发布的代码是一个开始。一旦您有了包含依赖关系的软件包列表,您可以使用apt-rdepends找到特定软件包的依赖关系(请参见此页面以获取示例用法和输出)。
操作步骤概述:
  1. 遍历dannysauer代码返回的软件包列表
  2. 对于每个软件包调用apt-rdepends
  3. 删除出现在apt-rdepends输出中的任何软件包

我认为这也是可行的方法,但似乎比deborphan更慢且需要更多工作。使用apt-rdepends解决的问题,deborphan有什么问题吗? - fadedbee
如果我没记错的话,deborphan 只是列出了已安装的没有任何依赖关系的软件包。这可能不是你想要的(请参见 Eric 上面关于 deborphan 可能会漏掉软件包的评论)。如果你遇到问题,我提到了 apt-rdepends,因为你可以从两台机器上获取所有已安装软件包的完整列表,删除两个列表中共同的软件包,并使用 apt-rdepends 检查剩余的软件包,以生成在第二台机器上重新创建当前软件包集所需的最短软件包列表。这也应该很容易编写脚本实现。 - bta

1

所以,你想要列出明确安装的软件包清单(例如 ubuntu-desktop 和 openssh),而不是自动依赖项?我不确定,但我认为这就是 dpkg --get-selections 的作用。所以,你可以执行以下命令:

dpkg --get-selections > file

然后,在另一台电脑上,使用相同的“文件”并运行。
dpkg --set-selections  < file
apt-get dselect-upgrade

我不是完全确定这些命令只是手动选择的软件包,而且我目前离开了任何基于Debian的系统,无法进行验证。 :)


不,看起来它列出了作为依赖项引入的软件包。 在我的机器上,列表包括像g++、g++-4.4、gcc等软件包,我知道这些是由build-essential安装的。 - fadedbee

1
这个怎么样:
#!/bin/bash

packages=$(dpkg --get-selections | grep '[[:space:]]install$' | awk '{print $1}')

for pkg in $packages
do
    nr_lines=$(apt-cache -i rdepends $pkg | wc -l )
    if [ "$nr_lines" = "2" ]
    then
        echo $pkg
    fi
done

它工作得好吗?有什么可以改进的地方吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接