Não foi possível fazer a atualização da versão no ubuntu 14.04

27

Atualmente, estou tentando atualizar uma caixa do ubuntu 14.04 para o xenial. Estou tentando fazer a atualização de lançamento e está falhando com erros como UnicodeDecodeError: o codec 'utf-8' não pode decodificar o byte 0x96 na posição 382: byte de início inválido

Parece um bug conhecido - tentei isso e não tive sorte em encontrar o pacote incorreto e desabilitei / removi meus 2 arquivos package.lst não padrão para repositórios nodesource e veeam.

O traceback lê algo como isto

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

E não há nada realmente útil nos logs. Como obter a atualização de lançamento para funcionar?

Journeyman Geek
fonte

Respostas:

44

O que você tem lá é o próprio script de atualização que tropeça em dados inválidos em algum lugar. Você precisa encontrar e remover os dados inválidos.

Nesse caso, era o pacote veeamsnap. A remoção desse pacote deve corrigi-lo. Mas, como isso é diferente para cada caso, descreverei as medidas tomadas para chegar a essa conclusão. É um processo bastante complicado.

É divertido, porque as strings python3 devem estar todas em UTF-8. O que você tem aqui (descoberto após o fato) é um módulo C ( apt_pkg) de alguma forma inserindo dados não UTF-8 em uma string python3, interrompendo todas as tentativas de leitura da string - observe como o próprio manipulador de erros também lançou uma exceção?

Para o depurador desconhecido , vamos!

A melhor maneira de diagnosticar problemas como esse é fazer com que o depurador faça uma pausa antes da linha que falhar. Com o Python, quando você tem uma série de chamadas aninhadas como essa, a maneira mais fácil de adicionar uma pausa no depurador é editar o próprio arquivo.

  1. Usando seu exemplo, podemos ver que a falha em questão está na /tmp/ubuntu-release-upgrader-woadaq_z/DistUpgrade/DistUpgradeCache.pylinha 806 do arquivo , então vamos iniciar um editor de texto e ir para essa linha. O caminho temporário será diferente para cada execução, portanto, use o caminho da sua saída de erro!

    captura de tela do editor

  2. A partir daqui, podemos primeiro adicionar uma pausa simples no depurador , inserindo import pdb; pdb.set_trace();a linha 806 imediatamente antes do erro. Porque este é Python, o recuo é importante!

    captura de tela da instrução de depuração

  3. Agora precisamos executar o programa modificado. Não corra do-release-upgradenovamente; provavelmente baixará um novo. Veja nos logs de erro, a primeira linha após "Exceção original foi"? Aquele com /tmp/ubuntu-release-upgrader-woadaq_z/xenial? Esse é o que você deseja executar. Portanto, execute esse arquivo como root (ou sudo).

    Execução que o levará ao depurador (pdb):

    captura de tela do depurador

  4. A partir daqui, descobrimos quantos pacotes existem no total. A maneira mais fácil de fazer isso é executar sum(1 for _ in self). Espere um pouco (isso pode demorar um pouco) e ele imprimirá um número. Nesse caso, foi 76028.

    Agora, como o erro provavelmente não ocorre nos primeiros e não queremos avançar manualmente> 75000 pacotes, e não podemos adicionar um manipulador de exceções (porque o erro é tão ruim que quebra o próprio Python) , precisamos de uma alternativa.

  5. Remova a linha adicionada na etapa 4. Edite o código para imprimir um número crescente para cada pacote. Por exemplo, adicione foo = 0acima do loop na linha 802 e foo += 1; print(foo)na linha 807 (imediatamente antes da linha com erro).

    captura de tela do código de impressão numérica

  6. Run the code again, using the same command as in step 3. It will print a large list of numbers. Let it keep running until it prints the error again. You might need to enlarge your window:

    captura de tela da saída numérica

    Esse último número deve ser o pacote em que ocorreu o erro. Anote esse número.

  7. Agora que você sabe qual pacote / número causa a falha, é hora de adicionar a pausa do depurador com uma condição para ser executada apenas nesse pacote. Por exemplo, se você trava no pacote 72285, adicione if foo == 72285: import pdb; pdb.set_trace()logo após a linha impressa foo:

    captura de tela da nova pausa do pdb

  8. Execute o código novamente. Agora, quando você entrar pdb, deve estar no pacote que causa a falha. Você pode digitar o nome da variável pkgpara imprimir seu valor, que informará o nome do pacote atual:

    captura de tela do nome do pacote

    De maneira mais geral, digitar o nome de qualquer variável imprimirá sua saída.

  9. Remova o pacote incorreto e tente a atualização novamente (em uma atualização limpa do-release-upgrade).

Prumo
fonte
7
Esta é uma introdução muito agradável e gentil ao gdb, que pode ser usada com diferentes níveis de proficiência por qualquer usuário. +1 de mim e parabéns. E, BTW, você pode simplesmente adicionar que digitar pkg no depurador imprimirá o valor da variável com o mesmo nome, conforme definido na linha 803. Em outras palavras, o pkg não é uma instrução do depurador. Felicidades.
MariusMatutiae
@MariusMatutiae Edited. E é APO;) (Isto foi realmente destinado mais para ser específico para resolver este tipo de problema, mas é bom que você achar que é fácil de seguir como uma introdução geral).
Bob
Para resolver esse problema em particular, não seria mais fácil adicionar uma linha ao script que imprime o que a mensagem de depuração deseja imprimir para um registro de pacote que não existe? (Existe essa mensagem logging.debug logo acima) Ou isso pressupõe que a variável pkg pode não ser capaz de ser impressa devido ao erro, e o depurador python pode imprimir alguma coisa?
precisa saber sobre o arquivo
Se ainda tivermos o blog Superusuário, isso seria uma excelente adição!
Canadian Luke REINSTATE MONICA
@CausingUnderflowsEverywhere Em teoria, sim. Na prática, uma sugestão semelhante do relatório de bug vinculado aparentemente não funcionou (não sei por que, apenas pelo que o OP me disse) e acabei fazendo isso de maneira interativa, caso algo mais provocasse a falha - por exemplo, não saiba que, nesse caso, foi a recordprópria propriedade que não pôde ser lida.
Bob