我该如何查找一个软件包来自哪个仓库?

有没有一种方法或命令可以告诉我们一个软件包来自哪个软件源?

4这是模棱两可的。你的意思是:哪些当前启用的存储库提供了具有给定名称的软件包,还是说:用于安装当前已安装软件包的仓库是哪个?(两者都有用。我要找的是后者,而不是前者。) - Reinier Post
2@ReinierPost 如果您知道哪些启用的存储库提供了该软件包,您可以根据每个存储库提供的软件包版本确定使用了哪个版本。如果您不确定安装了哪个版本,请运行dpkg -l <软件包名称> | awk '/^ii/{print $3}' - mchid
7个回答

使用以下命令。它的输出效果更好:
apt-cache policy <Package Name>

对于Ubuntu 16.04及更高版本,有一种更简便的方法来完成这个任务:
apt policy <Package Name>

19这是正确的答案!mac9416的回答中的命令需要繁琐的解释和根据输出进行猜测。有关“apt-cache policy”的更多信息,请参阅http://superuser.com/a/236605/61370。 - pabouk - Ukraine stay strong
3apt-cache policy是很好的,但有时你需要使用apt-cache showpkg来比较软件包的MD5校验和。还可以参考debsums --changed - gavenkoa
这个 policy 选项与 sources.list 相比最有用。 - infinite-etcetera
这应该是被接受的答案!@pabouk 是对的。这个答案比目前被接受的那个更相关于问题。 - Rohan 'HEXcube' Villoth
2根据@pablo-bianchi在他的答案中指出的(https://askubuntu.com/questions/8560/how-do-i-find-out-which-repository-a-package-comes-from/921197#921197),从16.04LTS开始,可以使用更简单的`apt policy <package-name>`命令。一旦14.04LTS于2018年终止支持,可能会编辑此回答以使用更新的命令。 - Rohan 'HEXcube' Villoth
非常感谢您。对我来说,使用以下命令很容易确定我意外安装了哪些多元宇宙软件包(如果有的话)。function manually_installed { comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u) } - DeepDeadpool
抱歉,输出比什么更好?是指被接受的答案吗? - undefined

编辑:

看看SuB的答案。看起来简单一些!

原文:

所需命令:

  • dpkg -s <package> - 允许您查找已安装的版本。 (来源)
  • apt-cache showpkg <package> - 将显示可用软件包的版本列表。对于每个版本,将给出软件包的源,以索引文件名的形式。

如果您想找到当前安装的软件包的源代码,您需要dpkg -s <package>的输出。否则,您可以直接查看apt-cache showpkg <package>输出的最新版本。

示例:

$ dpkg -s liferea
Package: liferea
Status: install ok installed
Priority: optional
Section: web
Installed-Size: 760
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Architecture: i386
Version: 1.6.2-1ubuntu6
...

$ apt-cache showpkg liferea
Package: liferea
Versions: 
1.6.2-1ubuntu6.1 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_lucid-updates_main_binary-i386_Packages)
 Description Language: 
                 File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_lucid-updates_main_binary-i386_Packages
                  MD5: 557b0b803b7ed864e6d14df4b02e3d26

1.6.2-1ubuntu6 (/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_lucid_main_binary-i386_Packages) (/var/lib/dpkg/status)
 Description Language: 
                 File: /var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_lucid_main_binary-i386_Packages
                  MD5: 557b0b803b7ed864e6d14df4b02e3d26
...

从第一条命令中,我可以看到Liferea版本1.6.2-1ubuntu6已安装。从第二条命令中,我可以看到该版本在/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_lucid_main_binary-i386_Packages中列出。
不费太多力气,我可以推断出源行包含archive.ubuntu.com、ubuntu、lucid和main。
果然,我的/etc/apt/sources.list包含以下行。
deb http://archive.ubuntu.com/ubuntu lucid main universe restricted multiverse

1Mac,谢谢你详细的回答!不幸的是,它对我最初的问题——未满足的依赖问题没有帮助 :-( 我正在尝试安装libqt4-opengl,但它显示: 以下软件包有未满足的依赖关系: libqt4-opengl:依赖于libqtcore4 (= 4:4.6.2-0ubuntu5.1),但要安装的版本为4:4.7.0beta1+git20100522-0ubuntu1lucid1ppa1+appmenu20100624 依赖于libqtgui4 (= 4:4.6.2-0ubuntu5.1),但要安装的版本为4:4.7.0beta1+git20100522-0ubuntu1lucid1ppa1+appmenu20100624 - dfme
1从那个上面很难看出问题所在。你应该开一个新的问题,这样你可以提供完整的细节。如果你这么做了,在评论里留下一个链接。 :-) - crenshaw-dev
6apt-cache政策 <软件包名称> - franzlorenzon
apt-cache {showpkg,policy}实际上显示已安装软件包的安装来源,还是只显示在查询时将要安装的位置 - Croad Langshan
1后者。如果我通常使用Ubuntu的trusty软件源,然后临时将utopic添加到我的sources.list中以安装init-system-helpers的1.20ubuntu3版本,然后再次从我的sources.list中删除该存储库,apt-cache showpkg init-system-helpers只会对原始软件包列表进行虚假描述,而apt-cache policy init-system-helpers则只会陈述明显的事实。 - blubberdiblub
这需要一个合适的图形用户界面。记住这些命令并花费大量时间阅读输出是荒谬的。我无法记住所有这些东西。可脚本化的文本界面很棒,但事情不应该止步于此。 - Ryan
@Ryan 这对非技术用户来说并不是一个非常常见的用例。你可以尝试使用 apt policy <软件包名称> 命令来获得更易读的输出。这个命令也很容易记住。 - crenshaw-dev
2这会告诉你要安装/升级的软件包来源,如果你试图这样做的话。它不会告诉你当前安装版本的来源。这可能会有所不同,例如在添加/删除PPA后。 - Reinier Post

apt 在 Ubuntu 16.04+ 上

除了 apt-cache policyshowpkgshow,现在我们有一个更简单、易于记忆的子命令:apt[1] [2](不要与经典的 apt-* 混淆):

apt policy <package> 

或者选择更多信息的替代方法apt show <package>,以"APT-Sources:"开头的行。 描述:该软件包提供了用于搜索、管理和查询有关软件包的信息以及对libapt-pkg库的所有功能进行低级访问的命令行工具。这包括:apt-getapt-cacheapt-cdromapt-configapt-key警告apt没有稳定的CLI界面。在脚本中使用时请谨慎。

apt --help中的基本命令

其他易于记忆的子命令也很简单。

  • apt list – 根据软件包名称列出软件包

  • apt search – 在软件包描述中搜索

  • apt show – 显示软件包详细信息

  • apt update – 更新可用软件包列表

  • apt install – 安装软件包

  • apt remove – 移除软件包

  • apt purge – 移除软件包和配置文件

    移除软件包会删除所有已打包的数据,但通常会保留一些小型(修改过的)用户配置文件,以防误删。如果意外删除的软件包需要重新安装,只需发出安装请求即可恢复其功能。另一方面,您可以通过对已删除的软件包使用purge来清除这些残留文件。请注意,这不会影响存储在您的主目录中的任何数据或配置。

    移除残留软件包

    sudo apt purge $(dpkg -l | grep "^rc" | awk '{print $2}')
    
  • apt upgrade – 通过安装/升级软件包来升级系统

  • apt full-upgrade – 通过移除/安装/升级软件包来升级系统

  • apt edit-sources – 编辑源信息文件


apt policy xxxapt-cache policy xxx看起来完全一样,或许这本应该是个注释。或者至少提到一下,apt show似乎需要使用-a开关来查看其他来源的"额外记录"。 - Xen2050
WARNING: apt does not have a stable CLI interface. Use with caution in scripts. - Reinier Post
@ReinierPost 评论或编辑建议比负评更好 - Pablo Bianchi
1@ReinierPost 这只是一个警告,而不是错误,并且这不是一个脚本。 - mchid

很遗憾,在软件包安装过程中没有记录这些信息。如果软件源列表中仍然存在该软件源,并且该软件源仍然拥有该软件包,您可以做出一个相对准确的猜测。
grep -l PKG /var/lib/apt/lists/*

即使禁用存储库并更新,甚至突触也无法判断。

sudo grep *packagename* /var/lib/apt/lists/* | grep "Filename:"


另一个有用的命令是"apt-cache policy"。它会显示类似这样的内容:
$ apt-cache policy 
Package files: 
 # The default https://wiki.debian.org/DebianStable repository with a priority of 500
 500 https://deb.debian.org/debian stable/main amd64 Packages
     o=Debian,n=stable,l=Debian,c=main,b=amd64
     origin deb.debian.org

 # The repository for Debian https://wiki.debian.org/PointReleases (security and grave bug fixes ~every 2 months)
 500 https://deb.debian.org/debian stable-updates/main amd64 Packages
     release o=Debian,a=oldstable-updates,n=stable-updates,l=Debian,c=main,b=amd64
     origin deb.debian.org

参考: https://wiki.debian.org/AptConfiguration

当从一个Ubuntu版本升级到下一个版本时,我喜欢利用这个机会进行一些春季大扫除。
这是以上答案的结合。
为了生成一个可过滤的列表,显示一个软件包安装在哪个仓库中,我们可以使用apt policy命令并去掉换行符。
dpkg -l | grep "ii" | awk '{print $2}' | xargs -n 1 -IX sh -c "apt policy X 2>/dev/null | tr '\n' ' '" | tee all_packages.txt

然后我们可以检查 all_packages.txt 文件,并过滤出不来自 Ubuntu 软件仓库的软件包。
cat all_packages.txt | grep -v "ubuntu.com"

我们现在可以检查这个列表,决定哪些要删除,哪些要保留。
要仅获取软件包名称,我们可以使用:
cat all_packages.txt | grep -v "ubuntu.com" | sed 's/:.*//g'