Неможливо зробити оновлення релізу на ubuntu 14.04


27

На даний момент я намагаюся оновити вікно ubuntu 14.04 до xenial. Я намагаюся зробити оновлення випуску, і його помилка з помилками типу UnicodeDecodeError: 'utf-8' кодек не може розшифрувати байт 0x96 у позиції 382: недійсний стартовий байт

Це схоже на відому помилку - я спробував це, і мені не пощастило знайти ображений пакет, і відключив / видалив свої 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 працювати?

Відповіді:


44

У вас є такий самий скрипт оновлення, який десь стикається з недійсними даними. Потрібно знайти та видалити недійсні дані.

У цьому випадку це був пакет veeamsnap. Видалення цього пакету повинно виправити це. Але оскільки це по-різному для кожного випадку, я опишу кроки, зроблені для досягнення цього висновку. Це досить складний процес.

Це весело, тому що всі струни python3 повинні бути в UTF-8. У вас тут (виявлено після факту) модуль C ( apt_pkg) якось вставляє дані, що не належать до UTF-8, у рядок python3, тому перериваючи кожну спробу читання рядка - зверніть увагу, як сам обробник помилок кинув виняток?

У невідомий налагоджувач ми вирушаємо!

Найкращий спосіб діагностувати подібні проблеми - це змусити налагоджувач зробити паузу перед рядком, який не працює. З Python, коли у вас є ряд вкладених викликів, як це, найпростіший спосіб додати паузу налагодження - це редагувати сам файл.

  1. Використовуючи ваш приклад, ми можемо побачити, що проблема, про яку йдеться, знаходиться у рядку файлів /tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.py806, тому давайте запустимо текстовий редактор і перейдемо до цього рядка. Темп-шлях буде різним для кожного запуску, тому переконайтеся, що ви використовуєте його з виводу помилок!

    скріншот редактора

  2. Звідси ми можемо спочатку додати просту паузу у відладчику , вставивши import pdb; pdb.set_trace();на рядок 806 безпосередньо перед помилкою. Оскільки це Python, відступ важливий!

    скріншот заяви про налагодження

  3. Тепер нам потрібно запустити модифіковану програму. Не бігай do-release-upgradeзнову; це, ймовірно, завантажити новий. Дивіться у журналах помилок перший рядок після "Оригінальним винятком було"? Той, що має /tmp/ubuntu-release-upgrader-woadaq_z/xenial? Це той, який ти хочеш бігти. Тому запустіть цей файл як root (або sudo).

    Запуск, який повинен потрапити до налагоджувача (pdb):

    скріншот налагоджувача

  4. Звідси ми розбираємося, скільки всього пакетів. Простий спосіб зробити це , щоб бігти sum(1 for _ in self). Почекайте трохи (це може зайняти деякий час), і він надрукує номер. У цьому випадку це було 76028.

    Тепер, оскільки помилка, ймовірно, не трапляється в перші кілька днів, і ми не хочемо вручну переходити через> 75000 пакетів, і ми не можемо додати обробник винятків (оскільки помилка настільки сильна, що ламає сам Python) , нам потрібна альтернатива.

  5. Видаліть рядок, доданий на кроці 4. Відредагуйте код, щоб надрукувати приріст числа для кожного пакету. Наприклад, додайте foo = 0вище циклу на лінії 802 та foo += 1; print(foo)на лінії 807 (безпосередньо перед лінією помилки).

    скріншот коду друку номерів

  6. Запустіть код ще раз, використовуючи ту ж команду, що і на кроці 3. Він надрукує великий список номерів. Нехай вона продовжує працювати, поки знову не надрукує помилку. Вам може знадобитися збільшити вікно:

    скріншот виводу номера

    Останнє число повинно бути пакетом, на який він розбився. Зауважте це число.

  7. Тепер, коли ви знаєте, який пакунок / номер викликає збій, настав час додати паузу налагодження з умовою виконувати лише цей пакет. Наприклад, якщо ви збиваєтесь на пакет 72285, додайте if foo == 72285: import pdb; pdb.set_trace()відразу після рядка, який друкує foo:

    скріншот нової паузи pdb

  8. Запустіть код ще раз. Тепер, коли ви потрапите в pdbнього, слід знаходитись на пакеті, що спричиняє збій. Ви можете ввести ім'я змінної, pkgщоб надрукувати її значення, яке повідомить вам ім'я поточного пакета:

    скріншот назви пакета

    Більш загально, введення імені будь-якої змінної друкує її вихід.

  9. Вийміть неприйнятний пакет і повторіть спробу оновлення (з чистого до-реліз-оновлення).


7
Це дуже приємне, дуже ніжне введення в gdb, яке може використовуватися з різним рівнем володіння практично будь-яким користувачем. +1 від мене, і кудо. І, BTW, ви можете просто додати, що набравши pkg у відладчику, буде надруковано значення однойменної змінної, визначеної у рядку 803. Іншими словами, pkg не є інструкцією налагодження. Ура.
MariusMatutiae

@MariusMatutiae Відредаговано. І це pdb;) (Це було насправді призначене більше для конкретного вирішення цього класу проблем, але приємно, що вам легко прослідкувати як загальне вступ.)
Боб

Щоб вирішити цю проблему, чи не було б простіше просто додати рядок до сценарію, який друкує те, що те повідомлення про налагодження хоче надрукувати для запису пакета, який не існує? (Є те, що logging.debug повідомлення праворуч вище) Або це припускає, що змінну pkg взагалі не вдасться надрукувати через помилку, і налагоджувач python може взагалі надрукувати що завгодно?
ПричиняєПотокиПовсюди

Якщо у нас ще є блог Super User, це було б чудовим доповненням до нього!
Канадський Люк ВІДНОВЛЕННЯ МОНИЦИ

@CausingUnderflowsEverywhere Теоретично, так. На практиці подібна пропозиція з пов'язаного звіту про помилку, мабуть, не спрацювала (я не впевнений, чому, саме з того, що мені сказала ОП), і я закінчив це робити інтерактивно, якщо щось інше спричинило аварію - наприклад, не знайте, що в цьому випадку recordне можна було прочитати саме властивість.
Боб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.