当前位置: 首页>>技术教程>>正文


linux – 无法在ubuntu 14.04上发布更新

,

问题描述

我目前正在尝试将Ubuntu 14.04盒子升级到Xenial。我正在尝试做发布更新,它失败并出现类似UnicodeDecodeError的错误:’utf-8’编解码器无法解码位置382中的字节0x96:无效的起始字节

看起来像known bug-我已经尝试过了,没有运气找到有问题的软件包,并禁用/删除了我的2个非标准package.lst文件,用于nodesource和veeam存储库。

追溯读取如下内容

Traceback (most recent call last):
  File "/tmp/ubuntu-release-upgrader-woadaq_z/xenial", line 8, in <module>
    sys.exit(main())
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeMain.py", line 242, in main
    if app.run():
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 1876, in run
    return self.fullUpgrade()
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 1757, in fullUpgrade
    if not self.doPostInitialUpdate():
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 943, in doPostInitialUpdate
    self.tasks = self.cache.installedTasks
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.py", line 806, in installedTasks
    for line in pkg._pcache._records.record.split("\n"):
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x96 in position 382: invalid start byte
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/problem_report.py", line 416, in add_to_existing
    self.write(f)
  File "/usr/lib/python3/dist-packages/problem_report.py", line 369, in write
    block = f.read(1048576)
  File "/usr/lib/python3.4/codecs.py", line 319, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

Original exception was:
Traceback (most recent call last):
  File "/tmp/ubuntu-release-upgrader-woadaq_z/xenial", line 8, in <module>
    sys.exit(main())
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeMain.py", line 242, in main
    if app.run():
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 1876, in run
    return self.fullUpgrade()
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 1757, in fullUpgrade
    if not self.doPostInitialUpdate():
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeController.py", line 943, in doPostInitialUpdate
    self.tasks = self.cache.installedTasks
  File "/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.py", line 806, in installedTasks
    for line in pkg._pcache._records.record.split("\n"):
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x96 in position 382: invalid start byte
=== Command terminated with exit status 1 (Mon Apr  3 09:31:21 2017) ===

日志中没有任何真正有用的东西。我如何获得do-release更新才能工作?

最佳方案

您所拥有的就是升级脚本本身会越过某处的无效数据。您需要查找并删除无效数据。

在这种情况下,它是软件包veeamsnap。删除该软件包应将其修复。但是,由于每种情况的情况不同,因此我将描述为得出该结论所采取的步骤。这是一个相当复杂的过程。

这很有趣,因为python3字符串都应该使用UTF-8。您在这里(事后发现)是一个C模块(apt_pkg),以某种方式将非UTF-8数据插入到python3字符串中,因此中断了读取该字符串的所有尝试-注意错误处理程序本身也是如何引发异常的?

我们走进了未知的debugger

诊断此类问题的最佳方法是使调试器在出现故障的线路之前暂停。使用Python,当您进行一系列这样的嵌套调用时,添加调试器暂停的最简单方法是编辑文件本身。

  1. 通过您的示例,我们可以看到问题所在的故障位于文件/tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.py行806中,因此让我们启动一个文本编辑器并转到该行。每次运行的临时路径都不相同,因此请确保使用错误输出中的临时路径!

  2. 从这里开始,我们可以通过在错误之前的第806行插入import pdb; pdb.set_trace();来首先add a simple pause in the debugger。因为这是Python,所以缩进很重要!

  3. 现在我们需要运行修改后的程序。不要再运行do-release-upgrade;可能会下载一个新的。在错误日志中看到“原始异常是”之后的第一行吗?一个与/tmp/ubuntu-release-upgrader-woadaq_z/xenial?那就是您要运行的那个。因此,以root(或sudo)身份运行该文件。运行该命令将使您进入调试器(pdb):

  4. 从这里,我们计算出总共有多少个软件包。 easy way to do that将运行sum(1 for _ in self)。请稍等(这可能需要一段时间),它将打印一个数字。在这个例子中是76028。现在,由于错误可能不会出现在前几个错误中,并且我们不想手动浏览> 75000程序包,也无法添加异常处理程序(因为错误非常严重,会破坏Python本身),我们需要一种替代方法。

  5. 删除在步骤4中添加的行。编辑代码以为每个软件包打印出递增编号。例如,在第802行上的循环上方添加foo = 0,并在第807行上添加foo += 1; print(foo)(就在错误行之前)。

  6. 使用与步骤3中相同的命令再次运行代码。它将打印大量数字。让它继续运行,直到再次打印错误。您可能需要扩大窗口:最后一个数字应该是崩溃的软件包。记下该数字。

  7. 既然您知道哪个程序包/编号导致崩溃,是时候添加调试器暂停并附带条件,该条件只能在该程序包上执行。例如,如果您在软件包72285上崩溃,则在打印foo的行之后添加if foo == 72285: import pdb; pdb.set_trace()

  8. 再次运行代码。现在,当您进入pdb时,它应该在引起崩溃的包装上。您可以键入变量pkg的名称以打印其值,这将告诉您当前包的名称:更一般而言,键入任何变量的名称将打印其输出。

  9. 删除有问题的程序包,然后从干净的do-release-upgrade重新尝试升级。

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/8443.html,未经允许,请勿转载。