背景是,普通的英特尔 GPU 驱动程序无法执行我的业余编码和一些游戏所需的各种 OpenGL 扩展。所以我必须安装 xorg-edgers,然后它才能正常工作。然而,上周三左右,xorg-edgers 进行了一次更新 - 包含大量软件包 - 并且它严重崩溃;驱动程序锁定并带走整个计算机;需要硬重置。
那么如何降级——选择 PPA 中代表过去某个时间点的软件包版本,而忽略比该时间点更新的版本?
答案1
在日常工作中使用 xorg-edgers ppa 可能是一个非常糟糕的想法。
确实,它可能会为您提供最新的驱动程序,但您也可能会得到无法正常工作的驱动程序。
删除 PPA并降级它所替换的软件包(因此回到官方存储库中可用的软件包),首先安装 ppa-purge:
sudo apt-get install ppa-purge
然后删除 PPA,优雅地降级为官方软件包:
sudo ppa-purge ppaname
这会将您的软件包降级回官方软件包。
其他在 PPA 中但不在官方存储库中的软件包不会被卸载。你应该手动告诉软件包管理器删除它们,例如使用 apt:
sudo apt-get purge packagename
您可以在 Ubuntu 设置中的“软件源”部分找到 ppa 的名称,并在其启动板页面上查看其提供的软件包列表(或者查看 Synaptic 软件包管理器的“来源”部分(如果已安装))。
答案2
我今天遇到了同样的问题,我注意到大约两周前我安装了系统更新,但仍然启用了 ubuntu-x-swat ppa,它有一个新的 nvidia 驱动程序。旧版本没问题,新版本破坏了我的系统(只是轻微的,我花了一段时间才注意到)。
因此,我查看了 /var/log/apt/history.log,以查找我安装的 nvidia 驱动程序包的先前版本号,然后尝试在 /var/cache/apt/archives 中查找该包,通常您会在该位置找到 apt 下载的所有包,但找不到该包。而且,一旦包被新版本取代,ppa 就不会保留其先前版本的包,因此我也无法从那里获取它。
但是,从以前的软件包版本到新版本的差异都保存在所有版本的 ppa 中,并且与原始 tarball 及其 debian 补丁一起,可以撤消新版本的所有更改并获取以前版本的源代码。
我将简要描述必要的步骤:
转到 ppa,找到最新的软件包版本并下载原始 tarball 和(可选)debian 补丁,就我而言,这些是在该页面上找到的:
https://launchpad.net/~ubuntu-x-swat/+archive/x-updates/+sourcepub/2087970/+listing-archive-extra
原始 tarball 名为:
nvidia-graphics-drivers_290.10.orig.tar.gz
从 tarball 中生成可构建软件包的 Debian 补丁包括:
nvidia-graphics-drivers_290.10-0ubuntu1~lucid~xup1.diff.gz
最好将它们提取到一个新的空目录中,然后将补丁应用到源树
~/nvidia> tar xvzf nvidia-graphics-drivers_290.10.orig.tar.gz [...] ~/nvidia> gzip -d nvidia-graphics-drivers_290.10-0ubuntu1\~lucid\~xup1.diff.gz ~/nvidia> patch -p0 < nvidia-graphics-drivers_290.10-0ubuntu1\~lucid\~xup1.diff [...]
修补时你不应该得到任何被拒绝的块。
在同一个 ppa 页面上,您会在“可用差异”部分下找到上一个软件包版本与您正在查看的版本之间的差异。
对我来说那就是:
diff from 285.05.09-0ubuntu1~lucid~xup1 to 290.10-0ubuntu1~lucid~xup1
下载、提取并反向应用到修补后的原始源:
~/nvidia> gzip -d nvidia-graphics-drivers_285.05.09-0ubuntu1\~lucid\~xup1_290.10-0ubuntu1\~lucid\~xup1.diff.gz ~/nvidia> patch -R -p0 < nvidia-settings_285.05.09-0ubuntu1\~lucid\~xup1_290.10-0ubuntu1\~lucid\~xup1.diff [...]
瞧!现在您应该已经准备好了先前版本的源代码树,可以构建软件包了:
~/nvidia> mv nvidia-settings-290.10/ nvidia-settings-285.05.09 ~/nvidia> cd nvidia-settings-285.05.09/ ~/n/nvidia-settings-285.05.09> dpkg-buildpackage
这将为您提供可以使用 dpkg 安装的先前版本的包:
~/n/nvidia-settings-285.05.09> cd .. ~/nvidia> sudo dpkg -i nvidia-current_285.05.09-0ubuntu1\~lucid\~xup1_amd64.deb [...]
答案3
将来,如果您使用 synaptic(假设您可以启动到 X),您可以通过突出显示要更改的软件包,然后从菜单中选择“强制版本”,从可用版本中进行选择。从那里您应该能够降级。
答案4
[原始海报]
没什么乐趣,我写了一个脚本来计算差异并执行恢复命令;涉及大约 100 个软件包。遗憾的是我的降级失败了,因为许多软件包不再可用 :(
#!/usr/bin/env python
import sys, getopt, os
from datetime import datetime
datefmt = "%Y-%m-%d %H:%M:%S"
dry_run = True
try:
opts,args = getopt.getopt(sys.argv[1:],"y")
if not args:
raise Exception("no date specified")
elif len(args) == 1:
args.append("00:00:00") # default time
elif len(args) != 2:
raise Exception("unexpected arguments")
snapshot = datetime.strptime(" ".join(args),datefmt)
for opt,_ in opts:
if opt == "-y":
dry_run = False
else:
raise Exception("unsupported option %s"%opt)
except Exception as e:
print "error:",e
print "usage:",sys.argv[0],"[flags] YYYY-MM-DD [HH:MM:SS]"
print "flags: -y = for real; don\'t just show it, restore it"
sys.exit(1)
# work out what to do
history = {}
restore = set()
remove = set()
with open("/var/log/dpkg.log","r") as log:
for line in log:
date,time,action,line = line.split(None,3)
when = datetime.strptime("%s %s"%(date,time),datefmt)
package,ver = line.strip().split(None,1)
if when <= snapshot:
if action in ("upgrade","install"):
prev_ver,new_ver = ver.split()
history[package] = new_ver
elif action == "remove":
if package in history:
del history[package]
else:
print "(cannot remove %s)"%line
else:
if action == "install":
remove.add(package)
elif action == "upgrade":
if package in history:
restore.add(package)
elif package not in remove:
print "(cannot revert %s)"%line
elif action == "remove":
if package in history:
restore.add(package)
elif package in remove:
remove.remove(package)
else:
print "(cannot revert %s)"%line
# show what to do
for package in restore:
print "restore",package,history[package]
for package in remove:
print "remove",package
# do it
if not dry_run:
print "======"
def execute(cmd):
print cmd
os.system(cmd)
#execute("apt-get remove "+" ".join(remove))
execute("apt-get install "+" ".join("%s=%s"%(package,history[package]) for package in restore))