Tidak dapat melakukan pembaruan rilis di ubuntu 14.04

27

Saat ini saya mencoba untuk memutakhirkan kotak 14,04 ubuntu ke xenial. Saya mencoba untuk melakukan pembaruan rilis, dan gagal dengan kesalahan seperti UnicodeDecodeError: 'utf-8' codec tidak dapat mendekode byte 0x96 di posisi 382: byte awal tidak valid

Sepertinya bug yang dikenal - Saya sudah mencobanya dan tidak beruntung menemukan paket yang menyinggung, dan menonaktifkan / menghapus 2 file package.lst non standar saya untuk repositori nodesource dan veeam.

Traceback membaca sesuatu seperti ini

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

Dan tidak ada yang benar-benar membantu dalam log. Bagaimana cara mendapatkan pembaruan do-release agar berfungsi?

Journeyman Geek
sumber

Jawaban:

44

Apa yang Anda miliki di sana adalah skrip upgrade itu sendiri tersandung data yang tidak valid di suatu tempat. Anda perlu menemukan dan menghapus data yang tidak valid.

Dalam hal ini, itu adalah paket veeamsnap. Menghapus paket itu harus memperbaikinya. Tetapi karena ini berbeda untuk setiap kasus, saya akan menjelaskan langkah-langkah yang diambil untuk mencapai kesimpulan itu. Ini adalah proses yang cukup rumit.

Ini adalah satu yang menyenangkan, karena string python3 harus semua berada dalam UTF-8. Apa yang Anda miliki di sini (ditemukan setelah fakta) adalah modul C ( apt_pkg) yang entah bagaimana memasukkan data non-UTF-8 ke dalam string python3, oleh karena itu memecah setiap upaya membaca string - perhatikan bagaimana penangan kesalahan itu sendiri melemparkan pengecualian juga?

Ke dalam debugger yang tidak dikenal, kita mulai!

Cara terbaik untuk mendiagnosis masalah seperti ini adalah membuat debugger berhenti sebelum jalur yang gagal. Dengan Python, saat Anda memiliki serangkaian panggilan bersarang seperti ini, cara termudah untuk menambahkan jeda debugger adalah mengedit file itu sendiri.

  1. Menggunakan contoh Anda, kita dapat melihat bahwa kegagalan yang dimaksud adalah di /tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.pybaris file 806, jadi mari kita jalankan editor teks dan pergi ke baris itu. Path temp akan berbeda untuk setiap run, jadi pastikan Anda menggunakan yang dari output kesalahan Anda!

    tangkapan layar editor

  2. Dari sini, pertama-tama kita dapat menambahkan jeda sederhana dalam debugger , dengan memasukkan import pdb; pdb.set_trace();on line 806 tepat sebelum kesalahan. Karena ini Python, lekukan itu penting!

    tangkapan layar pernyataan debugging

  3. Sekarang kita perlu menjalankan program yang dimodifikasi. Jangan lari do-release-upgradelagi; yang mungkin akan mengunduh yang baru. Lihat di log kesalahan, baris pertama setelah "Pengecualian asli adalah"? Yang satu dengan /tmp/ubuntu-release-upgrader-woadaq_z/xenial? Itu yang ingin Anda jalankan. Jadi jalankan file itu, sebagai root (atau sudo).

    Menjalankan yang seharusnya membawa Anda ke debugger (pdb):

    tangkapan layar debugger

  4. Dari sini, kami mencari tahu berapa banyak paket yang ada secara total. Cara mudah untuk melakukannya adalah dengan menjalankan sum(1 for _ in self). Tunggu sebentar (ini bisa memakan waktu cukup lama) dan itu akan mencetak nomor. Dalam hal ini, itu 76028.

    Sekarang, karena kesalahan mungkin tidak terjadi pada beberapa yang pertama, dan kami tidak ingin melangkah secara manual> 75000 paket, dan kami tidak dapat menambahkan pengecualian handler (karena kesalahannya sangat buruk sehingga merusak Python itu sendiri) , kita butuh alternatif.

  5. Hapus baris yang ditambahkan pada langkah 4. Edit kode untuk mencetak nomor tambahan untuk setiap paket. Misalnya, tambahkan di foo = 0atas loop pada baris 802 dan foo += 1; print(foo)pada baris 807 (tepat sebelum baris yang salah).

    tangkapan layar kode pencetakan angka

  6. Jalankan kode lagi, menggunakan perintah yang sama seperti pada langkah 3. Ini akan mencetak daftar nomor yang besar. Biarkan terus berjalan sampai mencetak kesalahan lagi. Anda mungkin perlu memperbesar jendela Anda:

    tangkapan layar keluaran angka

    Nomor terakhir itu harus menjadi paket tempat ia jatuh. Catat nomor itu.

  7. Sekarang Anda tahu paket / nomor mana yang menyebabkan crash, sekarang saatnya untuk menambahkan jeda debugger dengan syarat hanya mengeksekusi pada paket itu. Misalnya, jika Anda crash pada paket 72285, tambahkan if foo == 72285: import pdb; pdb.set_trace()tepat setelah baris yang dicetak foo:

    tangkapan layar pdb baru jeda

  8. Jalankan kode lagi. Sekarang ketika Anda masuk ke pdbdalamnya harus pada paket yang menyebabkan crash. Anda bisa mengetikkan nama variabel pkguntuk mencetak nilainya, yang akan memberi tahu Anda nama paket saat ini:

    tangkapan layar nama paket

    Secara lebih umum, mengetikkan nama variabel apa pun akan mencetak hasilnya.

  9. Hapus paket yang menyinggung dan coba upgrade lagi (dari clean-release-upgrade yang bersih).

Bob
sumber
7
Ini adalah pengantar yang sangat bagus, sangat lembut untuk gdb, yang dapat digunakan dengan berbagai tingkat kemampuan oleh hampir semua pengguna. +1 dari saya, dan pujian. Dan, BTW, Anda bisa menambahkan bahwa mengetik pkg di debugger akan mencetak nilai variabel dari nama yang sama, seperti yang didefinisikan pada baris 803. Dengan kata lain, pkg bukan instruksi debugger. Tepuk tangan.
MariusMatutiae
@MariusMatutiae Diedit. Dan ini pdb;) (Ini sebenarnya dimaksudkan lebih khusus untuk menyelesaikan masalah kelas ini, tapi senang Anda mudah mengikuti sebagai pengantar umum.)
Bob
Untuk mengatasi masalah ini khususnya, bukankah akan lebih mudah untuk hanya menambahkan baris ke skrip yang mencetak apa pun yang ingin dicetak pesan debug untuk paket rekaman yang tidak ada? (Ada pesan logging.debug tepat di atas) Atau apakah ini mengasumsikan variabel pkg mungkin tidak dapat dicetak sama sekali karena bug, dan python debugger dapat mencetak apa saja?
Menyebabkan Arus Bawah Di Mana Saja
Jika kita masih memiliki blog Pengguna Super, ini akan menjadi tambahan yang bagus untuk itu!
Luke Kanada REINSTATE MONICA
@CausingUnderflowsEverywhere Secara teori, ya. Dalam praktiknya, saran serupa dari laporan bug yang ditautkan tampaknya tidak bekerja (saya tidak yakin mengapa, hanya dari apa yang OP katakan kepada saya) dan saya akhirnya melakukannya secara interaktif seandainya ada hal lain yang memicu crash - mis. Tidak ketahuilah bahwa dalam hal ini adalah recordproperti itu sendiri yang tidak dapat dibaca.
Bob