Release-Update auf Ubuntu 14.04 nicht möglich

27

Ich versuche gerade, eine Ubuntu 14.04-Box auf Xenial zu aktualisieren. Ich versuche, Release-Update zu tun, und es schlägt fehl mit Fehlern wie UnicodeDecodeError: 'utf-8' Codec kann Byte 0x96 in Position 382 nicht decodieren: ungültiges Startbyte

Es sieht aus wie ein bekannter Fehler - ich habe das ausprobiert und hatte kein Glück, das fehlerhafte Paket zu finden, und habe meine 2 nicht standardmäßigen package.lst-Dateien für Nodesource- und Veeam-Repositorys deaktiviert / entfernt.

Der Traceback liest so etwas

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) ===

Und in den Protokollen ist nichts wirklich hilfreich. Wie kann ich das Update für Do-Releases zum Laufen bringen?

Geselle Geek
quelle

Antworten:

44

Was Sie dort haben, ist das Upgrade-Skript selbst, das irgendwo über ungültige Daten stolpert. Sie müssen die ungültigen Daten finden und entfernen.

In diesem Fall war es das Paket veeamsnap. Das Entfernen dieses Pakets sollte es beheben. Da dies jedoch für jeden Fall anders ist, beschreibe ich die Schritte, die unternommen wurden, um zu dieser Schlussfolgerung zu gelangen. Es ist ein ziemlich komplizierter Prozess.

Dies ist ein Spaß, weil python3 Strings sollten alle in UTF-8 sein. Was Sie hier haben (im apt_pkgNachhinein entdeckt), ist ein C-Modul ( ), das irgendwie Nicht-UTF-8-Daten in eine Python3-Zeichenfolge einfügt und daher jeden Versuch, die Zeichenfolge zu lesen, unterbricht.

In den unbekannten Debugger gehen wir!

Die beste Möglichkeit zur Diagnose solcher Probleme besteht darin, den Debugger vor der fehlgeschlagenen Zeile anzuhalten. Wenn Sie in Python eine Reihe solcher verschachtelter Aufrufe haben, können Sie eine Debugger-Pause am einfachsten hinzufügen, indem Sie die Datei selbst bearbeiten.

  1. Anhand Ihres Beispiels können wir feststellen, dass der fragliche Fehler in der Dateizeile /tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.py806 liegt. Starten Sie also einen Texteditor und gehen Sie zu dieser Zeile. Der Temp-Pfad ist für jeden Lauf unterschiedlich, stellen Sie also sicher, dass Sie den Pfad aus Ihrer Fehlerausgabe verwenden!

    Screenshot des Editors

  2. Von hier aus können wir zuerst eine einfache Pause in den Debugger einfügen, indem wir inimport pdb; pdb.set_trace(); Zeile 806 direkt vor dem Fehler einfügen . Da dies Python ist, ist der Einzug wichtig!

    Screenshot der Debugging-Anweisung

  3. Jetzt müssen wir das geänderte Programm ausführen. Lauf nicht noch do-release-upgradeeinmal; das wird wahrscheinlich einen neuen herunterladen. Siehe in den Fehlerprotokollen die erste Zeile nach "Ursprüngliche Ausnahme war"? Der mit /tmp/ubuntu-release-upgrader-woadaq_z/xenial? Das ist die, die du laufen willst. Führen Sie diese Datei als root (oder sudo) aus.

    Wenn Sie das ausführen, sollten Sie in den Debugger (pdb) gelangen:

    Screenshot des Debuggers

  4. Von hier aus ermitteln wir, wie viele Pakete es insgesamt gibt. Der einfachste Weg, dies zu tun, ist zu rennen sum(1 for _ in self). Warten Sie einen Moment (dies kann eine Weile dauern) und es wird eine Zahl gedruckt. In diesem Fall war es 76028.

    Nun, da der Fehler in den ersten paar Jahren wahrscheinlich nicht auftritt und wir nicht manuell durch> 75000 Pakete gehen möchten und wir keinen Ausnahmehandler hinzufügen können (weil der Fehler so schlimm ist, dass er Python selbst kaputt macht) Wir brauchen eine Alternative.

  5. Entfernen Sie die in Schritt 4 hinzugefügte Zeile. Bearbeiten Sie den Code, um für jedes Paket eine fortlaufende Nummer auszudrucken. Fügen Sie beispielsweise foo = 0über der Schleife in Zeile 802 und foo += 1; print(foo)in Zeile 807 (direkt vor der fehlerhaften Zeile) hinzu.

    Screenshot des Zahlencodes

  6. Führen Sie den Code mit demselben Befehl wie in Schritt 3 erneut aus. Es wird eine große Liste von Zahlen gedruckt. Lassen Sie es so lange laufen, bis der Fehler erneut ausgegeben wird. Möglicherweise müssen Sie Ihr Fenster vergrößern:

    Screenshot der Zahlenausgabe

    Diese letzte Nummer sollte das Paket sein, auf dem es abgestürzt ist. Notieren Sie sich diese Nummer.

  7. Jetzt, da Sie wissen, welches Paket / welche Nummer den Absturz verursacht, ist es Zeit, die Debugger-Pause mit einer Bedingung hinzuzufügen, die nur für dieses Paket ausgeführt wird. Wenn Sie beispielsweise auf einem Paket abstürzen 72285, fügen Sie if foo == 72285: import pdb; pdb.set_trace()direkt nach der Zeile, die gedruckt wird, Folgendes hinzu foo:

    Screenshot der neuen PDB-Pause

  8. Führen Sie den Code erneut aus. Wenn Sie sich darauf einlassen pdb, sollte es sich um das Paket handeln, das den Absturz verursacht. Sie können den Namen der Variablen eingeben pkg, um ihren Wert auszudrucken, der den Namen des aktuellen Pakets angibt :

    Screenshot des Paketnamens

    Im Allgemeinen wird die Ausgabe gedruckt, wenn der Name einer Variablen eingegeben wird.

  9. Entfernen Sie das fehlerhafte Paket und versuchen Sie das Upgrade erneut (von einem sauberen Do-Release-Upgrade).

Bob
quelle
7
Dies ist eine sehr nette, sehr sanfte Einführung in gdb, die von nahezu jedem Benutzer mit unterschiedlichen Kenntnissen verwendet werden kann. +1 von mir und ein dickes Lob. Übrigens können Sie einfach hinzufügen, dass durch Eingabe von pkg im Debugger der Wert der gleichnamigen Variablen ausgegeben wird , wie in Zeile 803 definiert. Mit anderen Worten, pkg ist keine Debugger-Anweisung. Prost.
MariusMatutiae
@MariusMatutiae Bearbeitet. Und es ist pdb;) (Dies war eigentlich eher dazu gedacht, diese Klasse von Problemen zu lösen, aber es ist schön, dass Sie es einfach finden, als allgemeines Intro zu folgen.)
Bob
Wäre es nicht einfacher, dem Skript eine Zeile hinzuzufügen, die die Debug-Meldung ausgibt, die für einen nicht vorhandenen Paketdatensatz ausgegeben werden soll? (Diese logging.debug-Meldung steht oben) Oder wird davon ausgegangen, dass die pkg-Variable aufgrund des Fehlers möglicherweise überhaupt nicht gedruckt werden kann und der Python-Debugger überhaupt etwas drucken kann?
CausingUnderflowsEverywhere
Wenn wir noch den Super User-Blog haben, wäre dies eine hervorragende Ergänzung!
Kanadier Luke REINSTATE MONICA
@CausingUnderflowsEverywhere Theoretisch ja. In der Praxis hat ein ähnlicher Vorschlag aus dem verknüpften Fehlerbericht anscheinend nicht funktioniert (ich bin mir nicht sicher, warum, genau nach dem, was mir OP gesagt hat), und ich habe ihn interaktiv ausgeführt, falls etwas anderes den Absturz ausgelöst hat - z. B. nicht Ich weiß, dass es in diesem Fall die recordEigenschaft selbst war, die nicht gelesen werden konnte.
Bob