ไม่สามารถทำการอัพเดทได้ใน Ubuntu 14.04


27

ฉันกำลังพยายามอัพเกรด ubuntu 14.04 กล่องเป็น xenial ฉันพยายามที่จะทำการอัพเดทและความล้มเหลวของข้อผิดพลาดเช่น UnicodeDecodeError: ตัวแปลงสัญญาณ 'utf-8' ไม่สามารถถอดรหัสไบต์ 0x96 ในตำแหน่ง 382: ไบต์เริ่มต้นไม่ถูกต้อง

ดูเหมือนว่าเป็นข้อผิดพลาดที่รู้จักกัน - ฉันได้ลองแล้วและไม่มีโชคในการค้นหาแพ็คเกจที่ละเมิดและปิดใช้งาน / ลบไฟล์ package.lst ที่ไม่ได้มาตรฐาน 2 ไฟล์ของฉันสำหรับที่เก็บ 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.pyบรรทัดของไฟล์806 ดังนั้นเราจะเริ่มโปรแกรมแก้ไขข้อความและไปที่บรรทัดนั้น เส้นทาง temp จะแตกต่างกันสำหรับการวิ่งแต่ละครั้งดังนั้นตรวจสอบให้แน่ใจว่าคุณใช้เส้นทางนั้นจากผลลัพธ์ข้อผิดพลาด!

    สกรีนช็อตของโปรแกรมแก้ไข

  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. ลบแพ็กเกจที่ละเมิดและลองอัพเกรดอีกครั้ง (จาก clean-do-release-upgrade)


7
นี่เป็นบทนำที่ดีมากและอ่อนโยนมากสำหรับ gdb ซึ่งสามารถใช้งานกับระดับความเชี่ยวชาญที่แตกต่างกันโดยผู้ใช้ทุกคน +1 จากฉันและรุ่งโรจน์ และ BTW คุณอาจเพิ่มการพิมพ์pkgในดีบักเกอร์ที่จะพิมพ์ค่าของตัวแปรของชื่อเดียวกันตามที่กำหนดไว้ในบรรทัด 803 ในคำอื่น ๆpkgไม่ได้เป็นคำสั่งดีบักเกอร์ ไชโย
MariusMatutiae

@MariusMatutiae แก้ไขแล้ว และมันคือ pdb;) (อันที่จริงแล้วมันมีจุดประสงค์ที่เฉพาะเจาะจงมากขึ้นสำหรับการแก้ปัญหาในระดับนี้ แต่ก็ดีที่คุณคิดว่ามันง่ายที่จะทำตามคำแนะนำทั่วไป)
Bob

เมื่อต้องการแก้ไขปัญหานี้โดยเฉพาะอย่างยิ่งมันจะง่ายกว่าหรือไม่ที่จะเพิ่มบรรทัดลงในสคริปต์ที่พิมพ์สิ่งใดก็ตามที่ข้อความดีบั๊กต้องการพิมพ์สำหรับระเบียนแพคเกจที่ไม่มีอยู่จริง (มีข้อความ Log.debug ด้านบนอยู่ด้านบน) หรือสิ่งนี้ถือว่าตัวแปร pkg อาจไม่สามารถพิมพ์ได้ทั้งหมดเนื่องจากข้อบกพร่องและดีบักหลามสามารถพิมพ์อะไรได้เลย?
ก่อให้เกิด UnderflowsEverywhere

หากเรายังมีบล็อกผู้ใช้ขั้นสูงนี่จะเป็นการเพิ่มที่ยอดเยี่ยม!
Canadian Luke ติดตั้ง MONICA ใหม่

@CausingUnderflowsEverywhere ตามทฤษฎีแล้วใช่ ในทางปฏิบัติข้อเสนอแนะที่คล้ายกันจากรายงานข้อผิดพลาดที่เชื่อมโยงดูเหมือนจะไม่ทำงาน (ฉันไม่แน่ใจว่าทำไมเพียงแค่จากสิ่งที่ OP บอกฉัน) และฉันลงเอยด้วยการโต้ตอบในกรณีที่มีสิ่งอื่นที่ทำให้เกิดความผิดพลาด - เช่นไม่ รู้ว่าในกรณีนี้มันเป็นrecordคุณสมบัติของตัวเองที่ไม่สามารถอ่านได้
Bob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.