如何防止特定软件包的更新?

由于 bug #693758 的存在,我想要阻止 apt-get upgrade 和 Update Manager 更新 "libgtk2.0-0" 软件包。
如何实现这个目标?

@hhlp:但是这个问题是关于一个从未安装过的软件包。 - Nathan Osman
1@George Edison - 还有一个叫做包保持的功能,它允许你不更新包。所以,保持一个包基本上意味着你告诉包管理器无论如何都保留当前版本。如果最新版本的一个目前正常工作的程序在更新后出现问题,这将非常有用。(你不能保持一个从未安装过的包,还请参考我的问题是一样的)...我刚刚测试了一下 - 看,他说禁用自动更新的包 - hhlp
1由于这个问题是在我们从apt-get迁移到apt之前提出的,值得注意的是apt-mark hold packagename仍然是解决此问题的标准方法。尝试使用apt hold只会报错E: Invalid operation hold - mwfearnley
15个回答

保留

有不同的方法来保留软件包:使用 dpkgaptdselectaptitude 或 Synaptic。

dpkg

将软件包保留:

echo "<package-name> hold" | sudo dpkg --set-selections

解除保留:
echo "<package-name> install" | sudo dpkg --set-selections

显示您所有包裹的状态:
dpkg --get-selections

显示单个包裹的状态:
dpkg --get-selections <package-name>

显示所有暂停的包裹:
dpkg --get-selections | grep "\<hold$"

apt

保留一个包裹:

sudo apt-mark hold <package-name>

取消保留:
sudo apt-mark unhold <package-name>

显示所有暂停的包裹:
sudo apt-mark showhold

dselect

使用dselect,进入[S]elect界面,找到您希望保持当前状态的软件包,然后按下=H键。在退出[S]elect界面后,更改将立即生效。


以下方法有限,因为在aptitude或synaptic中锁定/保持一个软件包不会影响apt-get/apt。
aptitude 保持一个软件包:
sudo aptitude hold <package-name>

取消保留:

sudo aptitude unhold <package-name>

使用Synaptic软件包管理器进行锁定

前往Synaptic软件包管理器(System > Administration > Synaptic Package Manager)。

点击搜索按钮,输入软件包名称。

当您找到该软件包后,选择它并转到Package菜单,然后选择Lock Version

Synaptic menu

那个软件包现在不会在更新管理器中显示,也不会被更新。

6这也可以防止软件包被安装。在安装devscripts时,会拉取很多推荐的软件包。由于我不需要邮件服务器(postfix),我可以在运行sudo apt-get install devscripts之前运行echo postfix hold | sudo dpkg --set-selections来禁用它的安装。这个保持操作只在此次安装中生效,在安装完成后,选择将被重置。 - Lekensteyn
8值得一提的是,软件包保持有时会破坏升级和补丁,因为它会创建一种情况,使得apt无法计算到依赖关系的合法解决方案。如果软件包foo对libbar有一个== < 或 <= 的依赖关系,那么apt将拒绝升级libbar以及foo。随着时间的推移,这些级联依赖关系可能会阻止大量的更新,包括重要的安全更新。如果发生这种情况,您需要删除保持并允许升级发生,或者重新构建您正在保持的软件包以针对其依赖关系的更新版本。 - Stephanie
2只是一点说明:apt-mark在0.7.25版本(Ubuntu Lucid)中不支持hold - Joril
如何在Muon(Kubuntu的更新管理器)中实现这一点?谢谢您的帮助。此外,该软件包已下载(Chromium的旧版本),因此它在Muon的图形用户界面(至少我所看到的)中并未显示出来,但在更新管理器中是可见的。 - Hans
2我可以确认,在Ubuntu 16.04(Xenial Xerus)中,sudo apt-mark hold/unhold目前是有效的。我保留了一些过时的软件包,然后执行了sudo apt-get dist-upgrade以查看它们是否会被升级,但是这些保留的软件包没有被升级。顺便说一下,你可以同时保留/取消保留多个软件包。例如:sudo apt-mark hold thunar thunar-dbg thunar-data libthunarx-2-0 libthunarx-2-dev。太棒了! - Yuri Sucupira
如果我能给你加2分的话,我会这么做的。你关于如何使用Synaptic告诉apt不要升级X、Y、Z软件包的建议非常有帮助!我还没有测试你其他屏蔽特定软件包的方法,因为Synaptic版本已经完美运行了!谢谢! - Ev-
2有人能在这里解释一下“holding”和“locking”的区别吗? - nutty about natty
1另外,稍微解释一下apt、aptitude、dpkg等是什么,它们的作用是什么,它们之间有什么区别,以及为了阻止特定软件包更新,是否需要运行这些命令中的任何一个或多个,这些都不妨提一下。目前的答案过于简洁,并且假设了太多的背景知识(依我看)。-- 如果您想要了解一些相关的重要背景知识和评论,可以阅读一下这篇文章:https://askubuntu.com/questions/18654/how-to-prevent-updating-of-a-specific-package#comment102573_86229 - nutty about natty
1从Snap市场安装的软件包怎么样? - Amir Fo
使用apt-mark hold命令阻止了我从Ubuntu 19.10升级到20.04:hin@xps:~$ update-manager -d Gtk-Message: 22:22:12.308: Failed to load module "appmenu-gtk-module" 正在检查新的Ubuntu版本 请在升级之前安装所有可用的更新。然而,我已经运行了sudo apt update && sudo apt upgrade - kirk
2只是一条注释:至少现在,“dpkg”,“apt-mark”,“apt”和“aptitude”的保持标记被彼此尊重,甚至Synaptic也有点认可它们:保持的软件包仍然显示为可升级(当然,如果有要升级的内容),你可以手动标记它们进行升级,但在点击“标记所有升级”按钮时它们会被忽略。但是通过Synaptic锁定似乎仍然是“Synaptic专用”。 - DJCrashdummy
1现在越来越多的软件包都推荐安装各种垃圾,所以了解sudo apt install --no-install-recommends the-package-name是很有用的。这样你就不需要使用任何技巧来避免安装不必要的软件包了。 - Mikko Rantalainen
apt-mark hold 选项推荐到这个答案的顶部值得吗?据我所知,那是现在推荐的方法。 - mwfearnley
突触法对我来说并没有起到作用。 - nyxee
使用sudo apt-mark hold命令,你如何将其应用于所有软件包? - Nathan B

我也在寻找同样的东西,经过大量的研究后,我发现使用以下语法可以禁止一个特定版本,但允许下一个更新:
Package: compiz-plugins-main
Pin: version 1:0.9.7.0~bzr19-0ubuntu10.1
Pin-Priority: -1

这个内容要放到/etc/apt/preferences文件中。

15这是一个比无限期阻止更新更好的方法。 - Eero Aaltonen
通过这种方法,我认为有更大的机会防止像Ubuntu One或亚马逊图标这样的Ubuntu“广告软件”在下一个版本升级时重新安装。 - Daniel Alder
这种方法还可以防止Aptitude报告一个软件包是“可升级的”(假设使用的是比仓库中可用的版本更旧的版本)。 - Digger
2@Digger 但是一旦出现了一个比被固定在-1的版本更新的新版本,aptitude将再次报告该软件包可升级。 - soger
使用完后,您可以通过 apt list --upgradable 查看更新的软件包。如果您需要阻止多个软件包,请参考 https://superuser.com/a/678411/316381 或者在 /etc/apt/preferences.d/ 文件夹中创建多个文件。 - Phlogi

将包裹"foo"暂停投递:
echo "foo hold" | dpkg --set-selections

在您的情况下,我们将暂停酒的供应。
sudo -i
echo "wine hold" | dpkg --set-selections

解除保留:
sudo -i
echo "wine install" | dpkg --set-selections

3请注意,当软件包处于停止状态时,您可以通过使用apt-get install wine=1.2.3命令安装指定版本。处于停止状态时,apt-get (dist-)upgrade命令无法更改该软件包。 - rcoup
如果你手动升级到新版本时,没有像你所描述的那样去除旧版本的保留状态,那么旧版本会被保留在缓存中,以便你可以返回使用它吗? - cxrodgers
3@cxrodgers 本地缓存(通常为/var/cache/apt/archives)与保留、升级等操作无关,因此您下载的所有版本都会保存在那里,直到您运行apt-get [auto]clean命令。 - rcoup

使用sudo apt-get install synaptic命令安装synaptic
使用gksudo synaptic命令运行,并在搜索框中找到您想要锁定的软件包,例如:gedit

enter image description here

从菜单中选择锁定版本

enter image description here

这就是全部了,在锁定时安装的版本将会在升级过程中保持安装状态。

11请看:“Lock版本不像听起来那么聪明。它应该按照字面意思执行,锁定版本...但它只在Synaptic内部锁定。任何其他执行软件包升级(即:Update Manager、apt-get、aptitude等)的工具都会忽略此操作。这可能是有缺陷的行为,所以我希望随着时间的推移会被修复。”来自http://askubuntu.com/questions/9607/what-does-lock-version-do。目前状况如何?如果在Synaptic中被锁定了某些内容,其他软件包管理器会“尊重”这个锁吗? - user25656
2截至版本0.75.13,仍然没有解决 :( aptitude也有同样的问题。 - syockit
截至0.84.3版本(2021年1月),它仍然不使用apt-mark。 - Force

阻止软件包安装被称为“软件包保持”,非常简单:
echo package_name hold | dpkg --set-selections
其中*package_name*是您想要阻止安装的软件包的名称。
注意:上述命令假设具有root权限。换句话说,在运行之前,您可能需要键入sudo su。

完美,这个就是答案。谢谢你。 - asoundmove
s/sudo su/sudo -s/g(或者sudo -i)进行翻译。 (-i会提供一个登录 shell,-s则不会)。 - derobert

自从一段时间以来,apt-get已被apt取代,所以例如我想阻止Firefox更新到56以上的版本,因为很多附加组件,比如"Tab Groups"在新的Firefox 57中不再起作用(参见"WebExtensions Update")。
可以使用一个命令来保留多个软件包并使用通配符。

防止Firefox更新

sudo apt-mark hold firefox firefox-locale-*

如果您决定稍后取消保留它们,那将是命令:

sudo apt-mark unhold firefox firefox-locale-*


我知道你可以在Synaptic中冻结特定软件包的版本,但我不能百分之百确定这是否会影响apt-get,但它肯定会停止更新管理器。
要冻结一个软件包,请在Synaptic中选择它,然后打开软件包菜单并选择冻结版本。
希望这对你有所帮助。
编辑:这个问题16668处理了类似的情况。

关于Ubuntu 16.04,补充一下@soger的评论。

默认情况下,Ubuntu 16.04没有现有的/etc/apt/preferences文件。如果你目前没有这个文件,只需创建一个新文件,并按照@soger上面描述的方式填写一个段落,以排除给定软件包及其依赖项的更新。

之后,运行apt update,就可以了。:0)

例如,我有一个嵌入式Intel显卡和一张NVidia显卡的Ubuntu 16.04.5 LTS服务器。只使用了NVidia显卡。服务器还使用CUDA驱动程序。我遇到了一个问题,apt一直坚持要求更新

va-driver-all

(Intel驱动程序),但它无法确定要安装的版本。这让我抓狂,而且我也不需要Intel驱动程序。我将这段文字输入到了preferences文件中,并刷新了apt,问题解决了。

Package: va-driver-all
Pin: release *
Pin-Priority: -1

查看错误 #75332#158981#72806
总结是在 apt-get / aptitude 级别上保持不会触发 dpkg 中的保持状态(特别是参见 bug 72806),而 update-manager 从 dpkg 读取状态。
解决方法是以 root 用户身份运行: echo "package hold" | dpkg --set-selections