Corrigindo "Could not get lock" no apt/dpkg

Corrigindo "Could not get lock" no apt/dpkg

O que significa "Could not get lock"?

Conclusao: apt e dpkg sao projetados para executar um de cada vez, protegidos por arquivos de lock. Este erro significa que outro processo ja segura o lock. Na maioria das vezes, e uma atualizacao automatica em segundo plano.

Quando voce executa algo como apt install, pode encontrar este erro e parar:

$ sudo apt install nginx
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (apt)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?

apt e dpkg podem executar apenas uma instancia de cada vez para nunca corromper o banco de dados de pacotes. Essa exclusao mutua e aplicada com arquivos de lock: enquanto uma operacao esta em andamento, qualquer outro comando falha ao adquirir o lock e imprime este erro.

Portanto nada esta "quebrado" -- voce foi simplesmente recusado porque algo ja esta na fila. Na maioria dos casos, esperar alguns minutos resolve. Apressar-se para excluir os arquivos de lock e a reacao mais perigosa; o primeiro passo correto e ver quem segura o lock.

Premissas (ambiente alvo)

  • SO: Ubuntu / distribuicoes baseadas em Debian (qualquer uma que use apt / dpkg)
  • Voce pode usar sudo
  • Nao faca rm nos arquivos de lock primeiro (razao explicada abaixo)

Quais arquivos de lock o apt usa?

Conclusao: Nao existe apenas um lock, mas quatro. lock-frontend cobre todo o frontend, lock o banco de dados dpkg, archives/lock downloads, e lists/lock o apt update. O caminho no erro indica em qual estagio travou.

O apt usa arquivos de lock separados para diferentes estagios. O caminho mostrado no erro indica onde esta travado.

Arquivo de lock Funcao Usado durante
/var/lib/dpkg/lock-frontend Todo o frontend apt Quase todas operacoes apt
/var/lib/dpkg/lock O banco de dados dpkg Descompactacao / configuracao
/var/cache/apt/archives/lock Cache de downloads .deb Download de pacotes
/var/lib/apt/lists/lock Listas de pacotes Durante apt update

O apt moderno (Ubuntu 18.04+) adquire lock-frontend primeiro. Se o erro menciona lock-frontend, outro apt / dpkg esta segurando todo o frontend.

Os arquivos de lock sao vazios; a exclusao e aplicada com flock (um lock de arquivo), nao pela existencia do arquivo. "O arquivo existe, entao exclua" e o modelo mental errado. Quando o processo que segura sai, o proximo apt funciona normalmente mesmo que o arquivo ainda esteja la.

Por que o lock nao pode ser adquirido?

Conclusao: 90% das vezes outro processo da familia apt esta executando. Se resume a atualizacoes automaticas, o atualizador grafico, um duplo lancamento ou um crash anterior -- e atualizacoes automaticas dominam.

A causa quase sempre se enquadra em um dos quatro padroes.

Causa Situacao tipica Direcao
Atualizacao automatica em segundo plano Acabou de iniciar / timer apt-daily disparou Esperar
Ferramenta grafica de atualizacao "Software Updater" / packagekit executando Fechar o GUI
apt lancado duas vezes apt deixado executando em outro terminal Esperar terminar
apt anterior travou Terminal fechado no meio da instalacao / queda de energia Comando de recuperacao

O primeiro e de longe o mais comum. O Ubuntu executa apt-daily.service / apt-daily-upgrade.service em timers que disparam logo apos a inicializacao e em horarios aleatorios, executando apt update ou unattended-upgrades em segundo plano. Executar apt install logo apos provisionar um servidor frequentemente colide com estes.

Como encontro o processo que segura o lock?

Conclusao: Comece com lsof ou fuser para encontrar qual processo tem o arquivo de lock aberto. O apt moderno tambem imprime o PID no erro. Sabendo o que e (apt / unattended-upgrades / etc.), a correcao se segue.

O primeiro passo e identificar quem segura o lock. Excluir ou matar vem apenas depois disso.

O apt moderno imprime held by process 1234 (apt) no erro. Quando nao o faz, use lsof.

$ sudo lsof /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/cache/apt/archives/lock
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
unattended 1234 root    5uW  REG    8,1        0  ... /var/lib/dpkg/lock-frontend

O W na coluna FD significa um lock de escrita. Aqui unattended-upgrades esta segurando. Se voce nao tem lsof, fuser tambem funciona.

$ sudo fuser -v /var/lib/dpkg/lock-frontend

Listar processos da familia apt fornece uma visao mais ampla.

$ ps aux | grep -iE 'apt|dpkg|unattended' | grep -v grep
root  1234  ... /usr/bin/python3 /usr/bin/unattended-upgrade

Se quem segura e unattended-upgrade ou apt-daily, uma atualizacao automatica esta executando -- apenas espere. Se e um duplo lancamento manual de apt, finalize a outra sessao.

E se uma atualizacao automatica for a causa?

Conclusao: Atualizacoes automaticas (unattended-upgrades) terminam em poucos minutos, entao esperar e o melhor. Matar o processo deixa a atualizacao parcialmente aplicada. Pare o servico adequadamente apenas se realmente nao puder esperar.

Se lsof mostra unattended-upgrade, esse processo nao e prejudicial -- esta aplicando atualizacoes de seguranca. Geralmente termina em 1-5 minutos e libera o lock por conta propria.

Para acompanhar o progresso, verifique o status.

$ systemctl status unattended-upgrades
$ sudo journalctl -u unattended-upgrades -f

Se nunca terminar, ou voce tiver uma razao real para parar, nao faca kill -9 -- pare adequadamente como servico.

$ sudo systemctl stop unattended-upgrades

kill -9 no meio de uma atualizacao deixa pacotes "descompactados mas nao configurados", o que forca uma recuperacao com dpkg --configure -a depois. Se precisar parar, prefira systemctl stop ou um kill normal (SIGTERM).

Quando e seguro excluir os arquivos de lock?

Conclusao: Excluir arquivos de lock e um ultimo recurso, permitido somente apos confirmar com lsof que nenhum processo os segura. Excluir enquanto um processo esta executando corrompe o banco de dados dpkg.

Voce vera conselhos para "apenas excluir os arquivos de lock". Isso so e valido como passo final apos confirmar que nenhum apt / dpkg esta executando. Excluir enquanto um processo esta ativo e duas instancias apt reescrevem o banco de dados ao mesmo tempo, quebrando o gerenciamento de pacotes.

Primeiro, confirme que nenhum processo tem os locks abertos.

# Sem saida significa que nenhum processo os segura
$ sudo lsof /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/cache/apt/archives/lock /var/lib/apt/lists/lock
$ ps aux | grep -iE 'apt|dpkg|unattended' | grep -v grep

Somente quando ambos estiverem vazios (nenhum apt / dpkg executando) voce pode remover os arquivos de lock obsoletos.

$ sudo rm /var/lib/dpkg/lock-frontend
$ sudo rm /var/lib/dpkg/lock
$ sudo rm /var/cache/apt/archives/lock
$ sudo rm /var/lib/apt/lists/lock

Como recupero um dpkg interrompido?

Conclusao: Apos liberar o lock, execute sudo dpkg --configure -a. Ele termina de configurar pacotes deixados "descompactados mas nao configurados", depois apt-get install -f / apt update restaura a consistencia.

Mesmo apos o lock ser liberado, um apt anterior que morreu no meio da operacao pode deixar pacotes semi-instalados. dpkg --configure -a normaliza isso.

$ sudo dpkg --configure -a

Isso reconfigura todos os pacotes que foram descompactados mas ainda nao configurados. Depois repare dependencias quebradas e atualize as listas.

$ sudo apt-get install -f
$ sudo apt update

apt-get install -f (--fix-broken) repara pacotes com dependencias quebradas. Quando isso passar, apt install funciona normalmente de novo.

A sequencia padrao de recuperacao sao estes tres, na ordem:

sudo dpkg --configure -a
sudo apt-get install -f
sudo apt update

Como evitar recorrencia?

Conclusao: Em scripts e automacao, defina DPkg::Lock::Timeout para que o apt espere pelo lock em vez de falhar instantaneamente. Ele tenta novamente pelo numero de segundos dado. Padrao no apt 2.x e posterior.

Para trabalho manual, "esperar a atualizacao automatica terminar" e suficiente. Mas em CI ou scripts de provisionamento, colidir com uma atualizacao automatica e falhar e doloroso. O apt 2.x pode esperar um numero definido de segundos em vez de retornar erro imediatamente.

# Esperar ate 60 segundos pelo lock
$ sudo apt-get -o DPkg::Lock::Timeout=60 install nginx
# Esperar indefinidamente (-1)
$ sudo apt-get -o DPkg::Lock::Timeout=-1 install nginx

Para automacao que executa apt install logo apos a inicializacao de um servidor, adicionar DPkg::Lock::Timeout sozinho previne a maioria das colisoes de lock com o apt-daily da inicializacao.

O que nao fazer

  • rm nos arquivos de lock sem verificar se ha um processo
  • kill -9 em um apt / dpkg que esta atualizando
  • Executar duas instancias de apt ao mesmo tempo no mesmo servidor

Resumo: checklist

Conclusao: A ordem basica e "identificar -> esperar -> recuperar". Excluir arquivos de lock e ultimo recurso, somente apos confirmar que nenhum processo os segura. Siga essa ordem e voce corrige sem quebrar o dpkg.

  • [ ] Identificou quem segura via PID no erro ou lsof?
  • [ ] Se e unattended-upgrade / apt-daily, esperou alguns minutos?
  • [ ] Verificou que o "Software Updater" / packagekit grafico nao esta executando?
  • [ ] Se for matar, evitou kill -9 e usou systemctl stop ou kill normal?
  • [ ] Confirmou com lsof e ps que nada esta executando antes de excluir locks?
  • [ ] Se interrompido, recuperou com dpkg --configure -a -> apt-get install -f -> apt update?
  • [ ] Definiu DPkg::Lock::Timeout na automacao?

Proximas leituras