Corrigindo "Could not get lock" no apt/dpkg

Corrigindo "Could not get lock" no apt/dpkg

O que significa "Could not get lock"?

Conclusão: apt e dpkg são projetados para executar um de cada vez, protegidos por arquivos de lock. Este erro significa que outro processo já segura o lock. Na maioria das vezes, é uma atualização automática em segundo plano.

Quando você 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 instância de cada vez para nunca corromper o banco de dados de pacotes. Essa exclusão mútua é aplicada com arquivos de lock: enquanto uma operação está em andamento, qualquer outro comando falha ao adquirir o lock e imprime este erro.

Portanto nada está "quebrado" -- você foi simplesmente recusado porque algo já está na fila. Na maioria dos casos, esperar alguns minutos resolve. Apressar-se para excluir os arquivos de lock é a reação mais perigosa; o primeiro passo correto é ver quem segura o lock.

Premissas (ambiente alvo)

  • SO: Ubuntu / distribuições baseadas em Debian (qualquer uma que use apt / dpkg)
  • Você pode usar sudo
  • Não faça rm nos arquivos de lock primeiro (razão explicada abaixo)

Quais arquivos de lock o apt usa?

Conclusão: Não 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 estágio travou.

O apt usa arquivos de lock separados para diferentes estágios. O caminho mostrado no erro indica onde está travado.

Arquivo de lock Função Usado durante
/var/lib/dpkg/lock-frontend Todo o frontend apt Quase todas operações apt
/var/lib/dpkg/lock O banco de dados dpkg Descompactação / configuração
/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 está segurando todo o frontend.

Os arquivos de lock são vazios; a exclusão é aplicada com flock (um lock de arquivo), não pela existência do arquivo. "O arquivo existe, então exclua" é o modelo mental errado. Quando o processo que segura sai, o próximo apt funciona normalmente mesmo que o arquivo ainda esteja lá.

Por que o lock não pode ser adquirido?

Conclusão: 90% das vezes outro processo da família apt está executando. Se resume a atualizações automáticas, o atualizador gráfico, um duplo lançamento ou um crash anterior -- e atualizações automáticas dominam.

A causa quase sempre se enquadra em um dos quatro padrões.

Causa Situação típica Direção
Atualização automática em segundo plano Acabou de iniciar / timer apt-daily disparou Esperar
Ferramenta gráfica de atualização "Software Updater" / packagekit executando Fechar o GUI
apt lançado duas vezes apt deixado executando em outro terminal Esperar terminar
apt anterior travou Terminal fechado no meio da instalação / queda de energia Comando de recuperação

O primeiro é de longe o mais comum. O Ubuntu executa apt-daily.service / apt-daily-upgrade.service em timers que disparam logo após a inicialização e em horários aleatórios, executando apt update ou unattended-upgrades em segundo plano. Executar apt install logo após provisionar um servidor frequentemente colide com estes.

Como encontro o processo que segura o lock?

Conclusão: Comece com lsof ou fuser para encontrar qual processo tem o arquivo de lock aberto. O apt moderno também imprime o PID no erro. Sabendo o que é (apt / unattended-upgrades / etc.), a correção se segue.

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

O apt moderno imprime held by process 1234 (apt) no erro. Quando não 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 está segurando. Se você não tem lsof, fuser também funciona.

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

Listar processos da família apt fornece uma visão mais ampla.

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

Se quem segura é unattended-upgrade ou apt-daily, uma atualização automática está executando -- apenas espere. Se é um duplo lançamento manual de apt, finalize a outra sessão.

E se uma atualização automática for a causa?

Conclusão: Atualizações automáticas (unattended-upgrades) terminam em poucos minutos, então esperar é o melhor. Matar o processo deixa a atualização parcialmente aplicada. Pare o serviço adequadamente apenas se realmente não puder esperar.

Se lsof mostra unattended-upgrade, esse processo não é prejudicial -- está aplicando atualizações de segurança. Geralmente termina em 1-5 minutos e libera o lock por conta própria.

Para acompanhar o progresso, verifique o status.

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

Se nunca terminar, ou você tiver uma razão real para parar, não faça kill -9 -- pare adequadamente como serviço.

$ sudo systemctl stop unattended-upgrades

kill -9 no meio de uma atualização deixa pacotes "descompactados mas não configurados", o que força uma recuperação com dpkg --configure -a depois. Se precisar parar, prefira systemctl stop ou um kill normal (SIGTERM).

Quando é seguro excluir os arquivos de lock?

Conclusão: Excluir arquivos de lock é um último recurso, permitido somente após confirmar com lsof que nenhum processo os segura. Excluir enquanto um processo está executando corrompe o banco de dados dpkg.

Você verá conselhos para "apenas excluir os arquivos de lock". Isso só é válido como passo final após confirmar que nenhum apt / dpkg está executando. Excluir enquanto um processo está ativo e duas instâncias 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) você 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?

Conclusão: Após liberar o lock, execute sudo dpkg --configure -a. Ele termina de configurar pacotes deixados "descompactados mas não configurados", depois apt-get install -f / apt update restaura a consistência.

Mesmo após o lock ser liberado, um apt anterior que morreu no meio da operação pode deixar pacotes semi-instalados. dpkg --configure -a normaliza isso.

$ sudo dpkg --configure -a

Isso reconfigura todos os pacotes que foram descompactados mas ainda não configurados. Depois repare dependências quebradas e atualize as listas.

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

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

A sequência padrão de recuperação são estes três, na ordem:

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

Como evitar recorrência?

Conclusão: Em scripts e automação, defina DPkg::Lock::Timeout para que o apt espere pelo lock em vez de falhar instantaneamente. Ele tenta novamente pelo número de segundos dado. Padrão no apt 2.x e posterior.

Para trabalho manual, "esperar a atualização automática terminar" é suficiente. Mas em CI ou scripts de provisionamento, colidir com uma atualização automática e falhar é doloroso. O apt 2.x pode esperar um número 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 automação que executa apt install logo após a inicialização de um servidor, adicionar DPkg::Lock::Timeout sozinho previne a maioria das colisões de lock com o apt-daily da inicialização.

O que não fazer

  • rm nos arquivos de lock sem verificar se há um processo
  • kill -9 em um apt / dpkg que está atualizando
  • Executar duas instâncias de apt ao mesmo tempo no mesmo servidor

Resumo: checklist

Conclusão: A ordem básica é "identificar -> esperar -> recuperar". Excluir arquivos de lock é último recurso, somente após confirmar que nenhum processo os segura. Siga essa ordem e você corrige sem quebrar o dpkg.

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

Próximas leituras