Risolvere l'errore apt "Could not get lock"

Pubblicato il 14 min di lettura

Perché apt risulta improvvisamente bloccato, quale processo c'è dietro, come individuarlo con lsof e fuser e come rimuovere il file di lock senza danneggiare il database dei pacchetti.

Vuoi installare al volo un pacchetto e apt si interrompe dopo un secondo. Al posto dell'elenco dei pacchetti compare una riga cercata milioni di volte in tutto il mondo: Could not get lock. Il riflesso di molte guide è cancellare subito il file di lock. Proprio questo riflesso trasforma regolarmente una banale attesa in un database dei pacchetti danneggiato. Questo articolo segue l'ordine che funziona su un sistema in produzione: prima capire chi tiene il lock, poi aspettare e solo alla fine intervenire.

Tutti i comandi vanno eseguiti come root. Se lavori come utente normale, anteponi sudo. Una precisazione subito: l'argomento riguarda esclusivamente Debian e Ubuntu. Su AlmaLinux, Rocky Linux, RHEL e Oracle Linux non esistono né apt-get/var/lib/dpkg, dnf affronta la questione in modo completamente diverso (vedi più avanti la sezione sulle differenze tra i sistemi).

Il messaggio di errore, parola per parola

A seconda della versione e di ciò che apt stava tentando di fare, l'output cambia. Queste sono le varianti che ti capiterà di incontrare:

E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr)
N: Be aware that removing the lock file is not a solution and may break your system.
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)
E: Unable to lock the administration directory (/var/lib/dpkg/), is another process using it?
E: Could not get lock /var/lib/apt/lists/lock. It is held by process 987 (apt-get)
E: Unable to lock directory /var/lib/apt/lists/
dpkg: error: dpkg frontend lock is locked by another process
dpkg: error: dpkg status database is locked by another process

La localizzazione italiana segnala la stessa cosa come "Impossibile ottenere il lock" oppure "Impossibile bloccare la directory di amministrazione". La parte importante è l'indicazione tra parentesi: il nome del processo. unattended-upgr, apt-get, aptitude, packagekitd o dpkg ti dicono già dove devi cercare.

Quattro file di lock, quattro messaggi diversi

apt e dpkg non bloccano in un punto solo, ma in quattro. Il file citato nel messaggio rivela in quale fase è nato il conflitto:

  • /var/lib/apt/lists/lock protegge gli elenchi dei pacchetti scaricati. Questo messaggio compare con apt update.
  • /var/cache/apt/archives/lock protegge la directory di download dei file .deb. Questo messaggio compare mentre apt sta scaricando i pacchetti.
  • /var/lib/dpkg/lock-frontend è il lock di livello più alto. Garantisce che a parlare con dpkg sia un solo frontend alla volta (apt, apt-get, aptitude, Ansible, uno script di installazione). È il messaggio che vedrai più spesso.
  • /var/lib/dpkg/lock protegge il database di stato vero e proprio. Chi tiene questo lock sta scrivendo davvero su /var/lib/dpkg/status.

Tutti e quattro i file sono vuoti. Non contengono dati, nessun PID, niente. Il blocco non sta nel contenuto, ma in un flock sul descrittore di file aperto. È il punto decisivo che quasi tutte le guide tralasciano.

Perché cancellare alla cieca può danneggiare il database dei pacchetti

Dato che il blocco è legato al descrittore di file e non al nome del file, cancellando succede questo: il processo in esecuzione conserva il suo descrittore e continua a lavorare indisturbato. Il file è sparito dalla directory, ma per lui continua a esistere. La tua seconda invocazione di apt crea un file nuovo con lo stesso nome, lo blocca senza problemi e crede di avere via libera.

Da quel momento due processi scrivono contemporaneamente in /var/lib/dpkg/status, estraggono file in parallelo nella stessa directory di destinazione e si eseguono a vicenda i trigger. Il risultato va da pacchetti configurati a metà fino a un database di stato che dpkg non riesce più a leggere. È esattamente ciò contro cui apt stesso mette in guardia con la riga N: Be aware that removing the lock file is not a solution and may break your system.

Rimuovere il file di lock è ammesso soltanto quando è dimostrato che non è più in esecuzione alcun processo che lo detiene. La dimostrazione è il cuore di questa guida, non il rm.

Il caso più frequente: l'aggiornamento automatico è in corso

In circa nove casi su dieci, su un server appena installato, il colpevole è innocuo e legittimo: unattended-upgrades. Ubuntu attiva per impostazione predefinita gli aggiornamenti di sicurezza non presidiati nelle immagini server e cloud, e due timer systemd avviano l'operazione:

  • apt-daily.timer parte alle 06:00 e alle 18:00 con un ritardo casuale fino a dodici ore e aggiorna gli elenchi dei pacchetti.
  • apt-daily-upgrade.timer parte alle 06:00 con un ritardo casuale fino a 60 minuti e installa gli aggiornamenti di sicurezza.

Il ritardo casuale è il motivo per cui l'errore sembra presentarsi a orari del tutto arbitrari. Nelle immagini cloud si aggiunge il primo avvio: al primo boot cloud-init esegue da sé un apt update. Chi accede due minuti dopo il provisioning e vuole installare subito qualcosa finisce quasi inevitabilmente contro il lock. Se stai configurando un nuovo server conviene quindi seguire l'ordine della nostra checklist per i nuovi server root: prima un respiro, poi l'installazione.

Lo stato dell'aggiornamento automatico si controlla così:

systemctl list-timers 'apt-daily*'
systemctl status unattended-upgrades.service
journalctl -u apt-daily-upgrade.service --since "-2h" --no-pager
tail -n 30 /var/log/unattended-upgrades/unattended-upgrades.log

Chi tiene il lock? Diagnosi con lsof e fuser

Prima di qualsiasi intervento va risposta una domanda: c'è ancora qualcuno al lavoro? Due strumenti lo dicono in modo affidabile. Se mancano, arrivano dai pacchetti lsof e psmisc, che ovviamente potrai installare solo quando il lock sarà sparito. Sui sistemi in produzione entrambi fanno quindi parte della dotazione di base.

lsof /var/lib/dpkg/lock-frontend
lsof /var/lib/dpkg/lock
lsof /var/cache/apt/archives/lock
lsof /var/lib/apt/lists/lock

Un output tipico è questo:

COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
unattended 1234 root    5uW  REG  254,1        0 1049 /var/lib/dpkg/lock-frontend

La W dopo il numero del descrittore di file significa: lock in scrittura attivo. Solo questa voce blocca davvero apt, un handle semplicemente aperto senza W non lo fa. Qui va quindi tutto bene, il processo sta lavorando.

Se invece non torna alcun output, nessuno tiene più il lock. Tieni presente che in questo caso normale lsof restituisce il codice di uscita 1, senza alcun messaggio di errore. Lo stesso vale per fuser. In uno script con set -e o in una catena con && la diagnosi si interrompe quindi proprio quando il risultato è buono. Lì conviene scrivere lsof /var/lib/dpkg/lock-frontend || true.

Una riserva importante sul valore di prova: un output vuoto significa davvero "nessuno sta bloccando" solo se il file di lock non è stato cancellato prima. Se è stato rimosso mentre un processo lo teneva ancora, quel processo continua a tenere l'inode orfano, ma sotto quel nome di file lsof non vede più nulla. Controlla quindi sempre anche l'elenco dei processi.

Senza lsof, fuser fa lo stesso lavoro:

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

Uno sguardo all'elenco dei processi mostra inoltre da quanto tempo l'operazione è in corso. La colonna etimes riporta il tempo di esecuzione in secondi, il che aiuta a farsi un'idea:

ps -eo pid,ppid,etimes,stat,cmd | grep -E 'apt|dpkg|unattended' | grep -v grep

Interpreta il risultato così:

  • Tempo di esecuzione sotto i dieci minuti, stato S oppure R: funzionamento normale. Aspetta.
  • Tempo di esecuzione oltre un'ora, accesso alla rete, mirror lenti: ancora plausibile. Verifica con tail -f /var/log/apt/term.log se qualcosa si muove.
  • Stato D (uninterruptible sleep) per lungo tempo: il processo è bloccato sul percorso di input e output. La causa di solito è un disco pieno o difettoso, non apt.
  • Stato T (fermato): qualcuno ha sospeso l'operazione con Ctrl+Z. Falla ripartire con kill -CONT PID.
  • Il processo non esiste più, il lock resta: adesso, e solo adesso, rimuovere il file di lock è legittimo.

Una causa frequente e sottovalutata è una partizione piena: dpkg si interrompe a metà estrazione e lascia esattamente questo stato. Se df -h /var è vicino al 100%, leggi prima come liberare spazio su un disco pieno sotto Linux e ripara la gestione dei pacchetti solo dopo.

Aspettare nel modo giusto invece di interrompere: DPkg::Lock::Timeout

Da apt 2.x esiste un'opzione che rende superflua buona parte dei problemi negli script. Invece di interrompersi subito, apt attende per un numero prefissato di secondi che il lock venga rilasciato:

apt-get -o DPkg::Lock::Timeout=60 install -y htop

Il valore -1 significa attesa illimitata. Per renderlo permanente lo imposti in un file di configurazione dedicato. L'assenza dell'estensione non è una svista, apt legge il file anche senza .conf:

echo 'DPkg::Lock::Timeout "300";' > /etc/apt/apt.conf.d/99lock-timeout
apt-config dump DPkg::Lock::Timeout

La seconda riga è la controprova. Deve restituire DPkg::Lock::Timeout "300";, solo allora il file è davvero attivo.

E adesso il limite che quasi nessuna guida riporta e che nei casi seri fa la differenza: l'opzione non copre tutti e quattro i lock. Misurato su Debian 11, 12 e 13 oltre che su Ubuntu 22.04 e 24.04, ogni volta con un processo esterno che tiene il lock tramite fcntl:

Lockapt attende con DPkg::Lock::Timeout?
/var/lib/dpkg/lock-frontendsì, esattamente il tempo impostato
/var/lib/dpkg/lock
/var/cache/apt/archives/lockno, interruzione in meno di un secondo
/var/lib/apt/lists/lockno, interruzione in meno di un secondo

In pratica questo significa due cose. Primo: con apt-get update l'opzione non serve a nulla, perché lì in gioco c'è il lock degli elenchi. Anche con DPkg::Lock::Timeout=-1 il comando si interrompe immediatamente con E: Could not get lock /var/lib/apt/lists/lock e codice di uscita 100, invece di attendere. Secondo: anche con install il timeout aiuta solo finché chi blocca tiene il lock del frontend. Se un processo parallelo è fermo su un download e tiene quindi il lock degli archivi, apt non attende nemmeno un secondo.

Per i ruoli Ansible, gli script cloud-init e le pipeline di deployment serve quindi in aggiunta un ciclo di ripetizione esterno, oppure l'intera operazione va serializzata con flock:

for i in $(seq 30); do apt-get update && break; sleep 10; done
flock /var/lib/apt/lists/lock apt-get update

Su Debian 12, Debian 13, Ubuntu 22.04 e Ubuntu 24.04 l'opzione è disponibile. Sui sistemi molto vecchi (Debian 9, Ubuntu 16.04) apt non la conosce e la ignora in silenzio, senza segnalare alcun errore.

Quando davvero non c'è più nessun processo: rimuovere il file di lock

Hai dimostrato con lsof e ps che nessuno sta più lavorando sulla gestione dei pacchetti. Solo adesso arriva l'intervento. Se invece un processo è ancora attivo e devi terminarlo, usa prima il segnale gentile e mai subito kill -9:

kill -TERM 1234

Un SIGTERM dà a unattended-upgrades la possibilità di portare a termine in modo pulito la chiamata dpkg in corso. Un SIGKILL a metà estrazione lascia invece esattamente quei pacchetti installati a metà che poi dovrai ripulire faticosamente. Dopo il SIGTERM attendi almeno 30 secondi e ricontrolla.

Se l'elenco dei processi è pulito, rimuovi i file di lock:

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

I file vengono ricreati automaticamente alla successiva invocazione di apt. Non devi crearli a mano né assegnare loro permessi particolari. Vale però anche il contrario: la cancellazione non ripara permessi errati né un proprietario errato, elimina solo il nome. Chi si aspetta da questo una riparazione sta cercando nel posto sbagliato. Ancora più delicato del rm è svuotare i file soltanto, per esempio con : > /var/lib/dpkg/lock-frontend: così l'inode resta e un eventuale vecchio processo ancora attivo rimane visibile in lsof.

Dopo l'intervento: dpkg --configure -a

Questo passaggio non è facoltativo. Un'operazione interrotta lascia pacchetti nello stato "estratti, ma non configurati". A quel punto apt si rifiuta di procedere con:

E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem.

Il comando porta a termine tutti i passaggi di configurazione rimasti in sospeso:

dpkg --configure -a

Segue poi la verifica delle dipendenze rotte:

apt-get --fix-broken install -y
apt-get check

Un dettaglio interessante per il controllo successivo: in /var/lib/dpkg/updates/ si trova il journal di dpkg. Se dopo dpkg --configure -a la directory è vuota, tutto è stato elaborato. Se ci sono ancora file numerati, l'operazione non è arrivata in fondo.

Se qualcosa è comunque andato storto: errori successivi e via di ritorno

Qui le altre guide si fermano. Questi messaggi compaiono quando si è cancellato troppo presto oppure si è terminato il processo in modo troppo brusco:

dpkg: error processing package nginx (--configure):
 package is in a very bad inconsistent state; you should
 reinstall it before attempting configuration
Errors were encountered while processing:
 nginx
E: Sub-process /usr/bin/dpkg returned an error code (1)

La via d'uscita passa da una rimozione forzata del pacchetto rotto e da una nuova installazione. Usa --force-remove-reinstreq esclusivamente per quel singolo pacchetto interessato, mai in modo indiscriminato:

dpkg --remove --force-remove-reinstreq nginx
apt-get install -y nginx

Una seconda variante riguarda gli elenchi dei file:

dpkg: warning: files list file for package 'libssl3' missing; assuming package has no files currently installed

In questo caso la riparazione arriva reinstallando lo stesso pacchetto con apt-get install --reinstall. Quali pacchetti si trovino davvero in uno stato non pulito lo elenca:

dpkg --audit

Nel caso peggiore è danneggiato /var/lib/dpkg/status stesso, riconoscibile da messaggi come dpkg: unrecoverable fatal error, aborting: parsing file '/var/lib/dpkg/status'. Allora aiutano due copie di sicurezza che il sistema crea da solo: /var/lib/dpkg/status-old e le copie ruotate ogni giorno in /var/backups/dpkg.status.0 fino a dpkg.status.6.gz. Ripristina la più recente delle due prima di pensare a una reinstallazione del sistema. Prima di farlo crea assolutamente un backup del file rotto.

Differenze tra i sistemi

Qui non esiste "una soluzione per tutti", la situazione di partenza cambia parecchio:

  • Ubuntu 22.04 e 24.04: unattended-upgrades è attivo nelle immagini server, l'errore è all'ordine del giorno. Si aggiunge needrestart, che dopo ogni installazione apre una finestra interattiva e tiene aperta l'operazione, lock compreso, finché qualcuno non conferma. Negli script imposta quindi DEBIAN_FRONTEND=noninteractive.
  • Debian 12 e Debian 13: i timer apt-daily.timer e apt-daily-upgrade.timer esistono anche qui, ma se l'aggiornamento automatico venga davvero eseguito dipende dall'immagine e da /etc/apt/apt.conf.d/20auto-upgrades. Verifica, non dare per scontato.
  • Container: in un'immagine Docker non girano né systemd né unattended-upgrades. Un lock lì significa praticamente sempre passaggi paralleli nella build oppure un layer in cache con un file di lock rimasto lì. Chi costruisce immagini regolarmente trova un punto di partenza nel nostro articolo su Docker su Debian e Ubuntu.
  • Sistemi desktop: lì il lock è spesso tenuto da packagekitd o dal gestore grafico degli aggiornamenti, non da apt.
  • AlmaLinux, Rocky Linux e RHEL: lì il problema in questa forma non esiste, dnf usa /var/run/dnf.pid e per impostazione predefinita attende invece di interrompersi. Il messaggio è allora Waiting for process with pid ... to finish. In cosa questa famiglia si distingua per il resto lo mostra l'articolo su htop su AlmaLinux, Rocky e RHEL.

Come capire che è di nuovo tutto pulito

Quattro verifiche che insieme danno un quadro affidabile:

dpkg --audit
apt-get check
apt-get --fix-broken install -y
apt-get update

dpkg --audit nel caso ideale non stampa proprio nulla. apt-get check termina con le righe sulla lettura degli elenchi dei pacchetti e senza errori. apt-get --fix-broken install segnala 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. E apt-get update arriva in fondo senza messaggi di lock. Inoltre ls /var/lib/dpkg/updates/ dovrebbe mostrare una directory vuota, e uno sguardo a /var/log/dpkg.log dovrebbe chiudere le ultime azioni con lo stato status installed invece di half-configured:

tail -n 20 /var/log/dpkg.log

Prevenire invece di riparare

Perché l'errore non si trasformi in una perdita di tempo, aiutano quattro abitudini:

  1. Impostare il timeout e ripetere comunque. DPkg::Lock::Timeout in /etc/apt/apt.conf.d/99lock-timeout fa attendere apt sul lock del frontend e su quello di dpkg, invece di farlo interrompere. Dato che il lock degli archivi e quello degli elenchi non rientrano, negli script si aggiunge un ciclo di ripetizione esterno. Insieme, i due coprono praticamente tutti i casi.
  2. Non aggiornare mai in una semplice sessione SSH. Se la connessione cade durante apt upgrade, dpkg si interrompe a metà operazione. Avvia gli aggiornamenti più lunghi in tmux o screen. Le basi le trovi nell'articolo su come collegarti al server via SSH.
  3. Evitare Ctrl+C nel frattempo. Durante il download un'interruzione è poco critica, durante l'estrazione e la configurazione produce esattamente i pacchetti installati a metà descritti nella sezione precedente.
  4. Non far collidere le proprie finestre di manutenzione con i timer di sistema. Chi esegue un aggiornamento pianificato per conto proprio lo imposta sfalsato nel tempo e con un timeout. Come configurarlo in modo pulito è spiegato negli articoli sui cron job sotto Linux e sui servizi systemd personalizzati.

Un'ultima nota sulla via d'uscita apparentemente più semplice: apt remove unattended-upgrades elimina sì i conflitti di lock, ma ti toglie anche gli aggiornamenti di sicurezza automatici. Su un server raggiungibile pubblicamente è un pessimo affare. È molto più sensato mantenere l'aggiornamento automatico e rendere pazienti le proprie operazioni.


In breve: lsof sul file di lock indicato, controllo dell'elenco dei processi, attesa. Solo quando è dimostrato che non gira più nulla, rimuovi i file di lock, poi sempre dpkg --configure -a e apt-get check. Con DPkg::Lock::Timeout nella configurazione di apt e un ciclo di ripetizione attorno ad apt-get update il resto si risolve da sé.

Domande frequenti

Posso semplicemente cancellare il file di lock?
Solo se hai prima dimostrato con lsof o fuser che nessun processo lo tiene più. Il blocco è legato al descrittore di file aperto, non al nome del file. Se cancelli mentre un processo sta lavorando, subito dopo girano due operazioni contemporaneamente sullo stesso database dei pacchetti, e questo lo danneggia.
Quanto devo aspettare prima di intervenire?
Con unattended-upgrades dieci o trenta minuti sono normali, con aggiornamenti di grandi dimensioni su mirror lenti anche di più. Verifica con tail -f /var/log/apt/term.log se qualcosa si muove ancora. Finché lì compaiono nuove righe, l'operazione sta lavorando e tu non intervieni.
Che cosa significa il nome di processo unattended-upgr nel messaggio di errore?
È l'aggiornamento di sicurezza automatico, avviato dai timer systemd apt-daily.timer e apt-daily-upgrade.timer. Il nome è troncato a 15 caratteri. Conviene lasciar terminare questa operazione, non interromperla.
Perché dopo aver rimosso il file di lock serve dpkg --configure -a?
Un'operazione interrotta lascia pacchetti nello stato estratti, ma non configurati. dpkg --configure -a recupera questi passaggi rimasti in sospeso. Senza questo comando apt rifiuta qualsiasi altra installazione con il messaggio dpkg was interrupted.
Come evito questo errore negli script e nei ruoli Ansible?
Con apt-get -o DPkg::Lock::Timeout=300 invece di un ciclo di attesa sui nomi dei processi. Per renderlo permanente inserisci DPkg::Lock::Timeout "300"; in /etc/apt/apt.conf.d/99lock-timeout, il valore -1 significa attesa illimitata. Importante: l'opzione agisce solo sul lock del frontend dpkg e sul lock di dpkg. Sul lock degli archivi e su quello degli elenchi apt non attende comunque, quindi con apt-get update non serve a nulla, è dimostrato. Lì ti serve un ciclo di ripetizione tuo, per esempio: for i in $(seq 30); do apt-get update && break; sleep 10; done
Questo errore esiste anche su AlmaLinux o Rocky Linux?
In questa forma no. dnf blocca tramite /var/run/dnf.pid e per impostazione predefinita attende l'altra operazione invece di interrompersi. Lì il messaggio è Waiting for process with pid ... to finish.
Dopo la riparazione apt segnala ancora errori su un singolo pacchetto, che faccio?
Verifica con dpkg --audit quale pacchetto è interessato, rimuovi esattamente quello con dpkg --remove --force-remove-reinstreq PACCHETTO e reinstallalo subito dopo. Non applicare mai questa opzione in modo indiscriminato a tutti i pacchetti.

apt dpkg Debian Ubuntu Gestione dei pacchetti Risoluzione dei problemi unattended-upgrades Linux