我遇到过一个问题,某个特定版本的包需要另一个特定版本的包,但是 Apt-Get 选择了依赖项的较新版本,然后失败。
我在使用 Puppet Lab 的 MCollective 和 Nginx Mainline PPA 以及其他可能的软件包时遇到过这种情况,所以我的问题是关于 Apt-Get 依赖关系解析的一般方法,但我将使用 Nginx 作为我的示例。
我有一个包镜像(使用 Aptly 构建),其中包含 nginx-full 包的 v1.7.5 及其所有依赖项以及较新的 v1.7.6 包及其所有依赖项。
如果我执行,apt-get install nginx-full=1.7.5-1+trusty1
则安装将失败并显示以下消息:
The following packages have unmet dependencies:
nginx-full : Depends: nginx-common (= 1.7.5-1+trusty1) but 1.7.6-1+trusty1 is to be installed
但是,如果我执行,apt-get install nginx-full=1.7.5-1+trusty1 nginx-common=1.7.5-1+trusty1
安装就会成功。
当我在镜像上同时拥有 1.7.5 和 1.7.6 版本的 nginx-common 包,并且 nginx-full 包明确指出它需要 1.7.5 版本的 nginx-common,而 nginx-full 是我所请求的包时,为什么 apt-get 仍然选择不兼容的 1.7.6 版本的 nginx-common?
这是安装 1.7.5 后的输出,dpkg -s nginx-full
显示了精确的版本依赖性约束:
Version: 1.7.5-1+trusty1
Depends: nginx-common (= 1.7.5-1+trusty1), libc6 (>= 2.14), ...
在这种情况下,所需的精确版本链很短,因此解决方法很容易,但对我来说至少存在两个问题:
- 其他软件包具有更长的依赖链,这些依赖链很难被发现并附加到 apt-get 命令行。
- 在依赖项的较新版本发布到软件包镜像之前,很容易不会意识到即将发生的问题。
我无法理解的是,为什么依赖关系解析似乎忽略了指定包的确切版本约束。更重要的是,我想知道如何要求 Apt-Get 遵守约束,而不必手动将包元数据复制到我的 apt-get 参数上。
答案1
您所遇到的问题在于它apt
并不apt-get
像您想象的那么聪明。
尝试降级软件包或安装比存储库中最新候选版本更旧的软件包版本时(考虑到您的apt
优先级固定和其他有关存储库优先级的策略),会发生此问题。降级软件包时,您实际上必须指定每个单独的依赖项您要降级到哪个版本,或者在这种情况下您实际想要安装哪个特定版本。
对于和相互依赖的nginx
包,你必须nginx-full
nginx-common
明确告诉 apt 安装指定版本的每个软件包。这是因为被版本号1.7.6-1+trusty1
取代1.7.5-1+trusty1
。因此,由于存在被取代的版本,您必须明确地说“仅安装此特定版本的软件包”,即apt-get install nginx-full=1.7.5-1+trusty1 nginx-common=1.7.5-1+trusty1
与您的问题无关,但当您从apt
固定优先级低于其他版本的存储库进行安装时也会发生这种情况,在这种情况下,您必须手动指定要安装的版本和/或源,即sudo apt-get install nginx-full/trusty-proposed nginx-common/trusty-proposed
尝试从建议的存储库安装软件包和依赖项的一个典型示例,该存储库的apt
优先级比 PPA 或主存储库低得多。