Corrigindo dependencias quebradas e pacotes retidos no apt

Corrigindo dependencias quebradas e pacotes retidos no apt

Qual a diferenca entre pacotes retidos e dependencias quebradas?

Conclusao: Sao problemas diferentes. Retido (held) significa que um pacote foi intencionalmente excluido de atualizacoes - nao e um erro. Dependencias quebradas significa que uma dependencia necessaria nao pode ser satisfeita, entao instalacoes ou atualizacoes nao podem ser concluidas. O primeiro e tratado com apt-mark, o segundo com apt --fix-broken install.

As pessoas tendem a agrupar esses dois sintomas como "um problema de dependencia", mas as causas e correcoes diferem.

# (A) retido: uma atualizacao foi simplesmente mantida de lado. Nao e um erro.
$ sudo apt upgrade
The following packages have been kept back:
  linux-generic nvidia-driver-535
# (B) quebrado: uma dependencia nao pode ser satisfeita e a operacao para. Isso e anormal.
$ sudo apt install some-package
The following packages have unmet dependencies:
 some-package : Depends: libfoo (>= 2.0) but 1.8 is to be installed
E: Unable to correct problems, you have held broken packages.

(A) e o apt deliberadamente recusando uma atualizacao; o sistema esta saudavel. (B) e uma incompatibilidade de versao em uma biblioteca necessaria, e se deixado assim vai bloquear outras instalacoes tambem. Identificar qual sintoma voce tem e o primeiro passo.

Premissas (ambiente alvo)

  • SO: Ubuntu / distribuicoes baseadas em Debian (qualquer uma usando apt / dpkg)
  • Voce pode usar sudo
  • (B) e mais comum logo apos adicionar um PPA de terceiros ou um .deb manual

Por que um pacote fica "kept back"?

Conclusao: apt upgrade e conservador - ele nao realiza uma atualizacao que requer remover um pacote existente (ele vai instalar novos pacotes quando necessario para satisfazer dependencias). Entao metapacotes e kernels cuja atualizacao precisa de uma remocao ficam "kept back". As phased updates do Ubuntu tambem retém atualizacoes temporariamente.

Ha duas razoes principais para "kept back" aparecer com apt upgrade.

Razao Pacotes tipicos Como resolver
Atualizacao requer uma remocao Metapacotes / transicionais / kernel apt full-upgrade
Phased updates em andamento Qualquer um (apenas Ubuntu) Aguardar / verificar

Para se manter seguro, apt upgrade vai adicionar novos pacotes quando necessario para satisfazer dependencias, mas nunca remove um pacote que voce ja tem. Se uma atualizacao requer remover um pacote instalado, essa atualizacao e pulada e mantida de lado (kept back). Atualizacoes de metapacotes de kernel podem cair nessa regra.

Para permitir remocoes e atualizar todo o sistema junto, use full-upgrade (dist-upgrade com apt-get).

$ sudo apt full-upgrade

As phased updates do Ubuntu sao distribuidas ao longo de varios dias em vez de todas de uma vez. Se sua maquina ainda nao esta na porcentagem de distribuicao, aquela atualizacao fica mantida de lado. Nesse caso, ela chega por conta propria em alguns dias. Para verificar agora, inspecione o candidato:

$ apt-cache policy <package-name>

Como verificar e liberar pacotes explicitamente retidos?

Conclusao: Alguem (talvez voce) pode ter executado apt-mark hold para fixar intencionalmente um pacote. Liste-os com apt-mark showhold, e libere com apt-mark unhold <pkg> se nao for mais necessario. dpkg --get-selections tambem mostra.

Se um pacote ainda nao atualiza mesmo apos full-upgrade, provavelmente esta retido (pinned). Um hold significa "nao atualize isso", usado para travar uma versao conhecida como boa (kernels, drivers, etc.).

Primeiro, liste os pacotes retidos.

$ apt-mark showhold
nvidia-driver-535
linux-image-generic

Esses nomes estao excluidos de atualizacoes. dpkg mostra a mesma coisa.

$ dpkg --get-selections | grep hold
nvidia-driver-535				hold

Quando o pin nao e mais necessario, libere o hold. Depois disso o pacote volta ao tratamento normal de atualizacoes.

# Liberar o hold
$ sudo apt-mark unhold nvidia-driver-535

# Para fixar em vez disso
$ sudo apt-mark hold nvidia-driver-535

Liberar descuidadamente um hold de um pacote intencionalmente retido (ex.: um driver verificado) pode alterar o comportamento na proxima atualizacao. Nao libere um hold ate saber por que ele existe. Se nao tiver certeza, descubra quem definiu e quando (politica da equipe, um script de provisionamento) primeiro.

Por que dependencias nao satisfeitas acontecem?

Conclusao: unmet dependencies significa que uma versao de dependencia necessaria nao pode ser obtida ou reconciliada. As causas se resumem a repositorios misturados (PPAs, .deb manual), um apt update desatualizado, uma instalacao interrompida ou pinning. A linha Depends: no erro e sua pista direta.

Quando voce encontra unmet dependencies, leia o corpo do erro primeiro. Ele indica qual dependencia, sob qual restricao de versao, nao pode ser satisfeita.

The following packages have unmet dependencies:
 packageA : Depends: libbar (>= 3.0) but it is not going to be installed
           Depends: libbaz (= 1.2) but 1.4 is to be installed

Depends: libbar (>= 3.0) but ... significa "libbar 3.0 ou mais novo e necessario, mas nao pode ser instalado / uma versao diferente esta prestes a ser instalada". As causas se dividem em quatro categorias.

Causa Situacao tipica Direcao
Repositorios misturados PPA / .deb manual / releases Ubuntu mistos Remover o PPA / --fix-broken
apt update desatualizado apt nao conhece a nova versao da dependencia apt update, depois tente novamente
Instalacao anterior interrompida Queda de energia / kill encerrou apt no meio dpkg --configure -a
Pinning do apt (prioridades) Uma versao fixada em /etc/apt/preferences Revisar o pin

A primeira domina: um PPA externo ou .deb avulso demanda uma versao de dependencia que conflita com o repositorio oficial. apt-cache policy mostra de qual repositorio uma dependencia vem.

$ apt-cache policy libbar
libbar:
  Installed: 2.8-1
  Candidate: 2.8-1
  Version table:
     3.0-1 500 500 https://ppa.example/ubuntu jammy/main amd64 Packages
 *** 2.8-1 500 500 http://archive.ubuntu.com/ubuntu jammy/main amd64 Packages

Ver de qual repositorio o candidato e a versao necessaria vêm indica se a mistura e a causa.

Como reparar dependencias quebradas?

Conclusao: O padrao e sudo apt --fix-broken install (anteriormente apt-get -f install), que tenta resolver dependencias incompletas. Se uma interrupcao e a causa, execute dpkg --configure -a primeiro. Se os dados do repositorio estao apenas desatualizados, apt update frequentemente resolve.

Repare na ordem de menor impacto. Nao force-remova pacotes de inicio - deixe o apt resolver.

Primeiro atualize as listas, depois tente o reparo automatico.

$ sudo apt update
$ sudo apt --fix-broken install

--fix-broken (-f) detecta pacotes com dependencias quebradas e propoe/aplica as adicoes faltantes ou remocoes desnecessarias. Se um apt anterior parou no meio da operacao, configure os pacotes "descompactados mas nao configurados" primeiro.

$ sudo dpkg --configure -a
$ sudo apt --fix-broken install

Quando o apt propoe remover um pacote, sempre leia o que sera removido. Se a proposta envolve remover pacotes importantes que voce nao esperava, pare antes de responder yes.

O amplamente compartilhado sudo dpkg -i --force-depends *.deb e --force-all ignoram verificacoes de dependencia e instalam mesmo assim - pode passar agora mas quebra pior depois. As opcoes --force-* sao ultimo recurso; corrija a causa raiz (repos misturados, pinning) primeiro.

A sequencia padrao de recuperacao, em ordem:

sudo apt update
sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt full-upgrade

Como obter opcoes de resolucao do aptitude?

Conclusao: Para conflitos complexos que apt --fix-broken install nao consegue resolver, aptitude propoe multiplas solucoes interativamente. Voce pode rejeitar opcoes que nao gosta, entao ele encontra um meio-termo de forma mais flexivel que o apt.

Mesmo quando o apt desiste de um conflito, aptitude percorre solucoes em etapas (o que manter, o que fazer downgrade, etc.). Normalmente nao esta instalado por padrao, entao adicione-o.

$ sudo apt install aptitude
$ sudo aptitude install <package-name>

Quando uma dependencia nao pode ser satisfeita, aptitude oferece solucoes como Accept this solution? [Y/n/q/?]. Pressione n para a proxima opcao, y para aceitar - assim voce escolhe uma solucao com a qual esta confortavel. O controle mais fino sobre o "tudo ou nada" do apt e a vantagem.

Propostas do aptitude tambem podem incluir solucoes "remover uma pilha de pacotes". Sempre revise as remocoes e downgrades de uma solucao proposta antes de aceitar. Aceitar cegamente a primeira opcao nao e melhor do que forcar com o apt.

Checklist quando ainda nao resolve

Conclusao: Diferencie retido de quebrado, e para quebrado aplique "update -> configure -> fix-broken" em ordem. Se voce suspeita de repositorios misturados, remover aquele PPA e reavaliar e o caminho mais curto.

  • [ ] Determinou se o sintoma e "kept back" (retido) ou "unmet dependencies" (quebrado)?
  • [ ] Se kept back, tentou apt full-upgrade (e aguardou se e phased updates)?
  • [ ] Verificou apt-mark showhold para um hold intencional?
  • [ ] Leu a linha Depends: no erro de unmet dependencies?
  • [ ] Tentou sudo apt update -> dpkg --configure -a -> apt --fix-broken install em ordem?
  • [ ] Usou apt-cache policy <dep> para identificar repos misturados (PPA / .deb manual)?
  • [ ] Corrigiu a causa raiz (pinning / mistura) antes de forcar com --force-*?
  • [ ] Revisou solucoes do aptitude para conflitos complexos?

Proximas leituras