Un apt upgrade que se queda colgado rara vez tiene una sola causa — suele ser una cadena de bloqueos que se van destapando uno tras otro. Este es un caso real donde tres problemas distintos se encadenaron: un lock de dpkg, un bloqueo de debconf, y finalmente un deadlock real entre dos servicios de systemd provocado por needrestart.
Cómo se encadenó el problema
apt.systemd.dailytenía tomado el lock inicialmente — el timer automático de actualizaciones de Ubuntu/Debian corriendo en segundo plano, compitiendo por el mismo recurso que elapt upgrademanual.- Al liberarse ese lock, apareció un bloqueo real en debconf, con el mensaje
/var/cache/debconf/config.dat is locked by another process. - Al actualizar
libc6(una librería base que usan prácticamente todos los procesos del sistema), needrestart intentó reiniciar automáticamente los servicios que dependían de ella — y quedó colgado a mitad de ese proceso. - Esto generó un deadlock real entre Zabbix y MySQL:
zabbix-server.serviceestaba en estado restart (running), mientrasmysql.servicequedó en start (waiting) — cada uno esperando indefinidamente al otro, sin que ninguno pudiera avanzar por sí solo. - Cancelar manualmente los jobs colgados de systemd liberó el bloqueo, y
aptpudo terminar correctamente. - El sistema quedó estable, solo pendiente de un reinicio para cargar el nuevo kernel instalado durante la actualización.
Por qué pasa esto: el rol de needrestart
needrestart es una herramienta que, tras actualizar paquetes, detecta qué servicios en ejecución siguen usando versiones antiguas de librerías ya reemplazadas (típicamente detectando referencias a archivos .so borrados en memoria), y ofrece reiniciarlos automáticamente para que carguen las versiones nuevas. Es útil en general, pero cuando el paquete actualizado es algo tan fundamental como libc6, la lista de servicios a reiniciar puede ser larga — y si dos de esos servicios tienen una dependencia circular entre sí a nivel de arranque (como Zabbix, que necesita a MySQL corriendo, mientras MySQL en este caso quedó esperando por un recurso que Zabbix tenía tomado), el reinicio automático masivo puede desencadenar exactamente el tipo de deadlock que ocurrió aquí.
Diagnóstico: ver quién tiene el lock
sudo lsof /var/lib/dpkg/lock-frontend
sudo lsof /var/lib/dpkg/lock
sudo lsof /var/cache/debconf/config.datlsof (list open files) muestra qué proceso tiene abierto un archivo específico — en este caso, los archivos de lock que usan dpkg y debconf para evitar que dos instancias se ejecuten simultáneamente y corrompan el estado de paquetes instalados. Si el comando devuelve un PID, ese es el proceso responsable del bloqueo.
Detener los procesos automáticos de APT
sudo systemctl stop apt-daily.service
sudo systemctl stop apt-daily-upgrade.service
sudo systemctl stop apt-daily.timer
sudo systemctl stop apt-daily-upgrade.timerUbuntu y Debian ejecutan actualizaciones automáticas de índices de paquetes (y opcionalmente de seguridad) en segundo plano mediante estos timers. Si uno de ellos está corriendo justo cuando se intenta un apt upgrade manual, ambos procesos compiten por el mismo lock — deteniendo estos servicios temporalmente se elimina esa competencia.
Limpiar procesos colgados
sudo kill -9 <PID>Último recurso cuando un proceso relacionado con apt/dpkg queda genuinamente colgado (no avanza ni responde) — kill -9 lo termina de forma forzosa, sin darle oportunidad de limpiar sus propios recursos. Debe usarse con cuidado, solo tras confirmar con lsof o ps que el proceso realmente está detenido y no simplemente trabajando lento.
Reparar el estado de dpkg
sudo dpkg --configure -a
sudo apt -f installdpkg --configure -a retoma y completa la configuración de cualquier paquete que haya quedado a medias (por una interrupción, un lock forzado a matar, etc.). apt -f install («fix broken») resuelve dependencias rotas que hayan quedado como resultado.
Ver y cancelar jobs pendientes en systemd
# Listar jobs de systemd en curso o en espera
systemctl list-jobs
# Cancelar jobs específicos por su número de job (no PID de proceso)
sudo systemctl cancel 2421271 2421892Esto fue lo que realmente destrabó el problema en este caso. Un «job» de systemd es una operación de cambio de estado en curso sobre una unidad (arrancar, detener, reiniciar) — cuando dos jobs quedan esperándose mutuamente (como el restart de Zabbix esperando el start de MySQL, y viceversa por otra dependencia), systemctl list-jobs los muestra con su estado (running o waiting), y cancel con el número de job los elimina de la cola sin necesidad de matar procesos a nivel de sistema operativo.
Reiniciar servicios manualmente si hace falta
sudo systemctl restart mysql
sudo systemctl restart zabbix-serverTras romper el deadlock cancelando los jobs colgados, conviene reiniciar los servicios afectados manualmente, en el orden correcto de dependencia (la base de datos primero, el servicio que depende de ella después) para asegurar que ambos queden arriba de forma limpia.
Validar el estado final
sudo dpkg --configure -a
sudo apt -f install
sudo apt upgradeRepetir estos comandos confirma que ya no quedan paquetes a medio configurar ni dependencias rotas, y permite completar la actualización que originalmente se había colgado.
Revisar servicios fallidos
systemctl --failedLista únicamente las unidades que quedaron en estado failed tras todo el proceso — un chequeo final rápido para confirmar que ningún otro servicio quedó afectado colateralmente por el deadlock o por los reinicios forzados.
Reiniciar para cargar el kernel nuevo
sudo rebootCuando la actualización incluye un kernel nuevo (común en actualizaciones de libc6 y paquetes base), el sistema sigue corriendo con el kernel anterior en memoria hasta el próximo reinicio. No es urgente hacerlo de inmediato si el sistema está estable — se puede programar para una ventana de mantenimiento sin prisa.
# Confirmar el kernel cargado después del reinicio
uname -rResumen del flujo de diagnóstico
- Si
aptno avanza: verificar locks conlsofsobre los archivos dedpkgydebconf. - Detener los timers automáticos de
apt-dailysi están compitiendo por el lock. - Si un proceso está genuinamente colgado (no solo lento), terminarlo con
kill -9tras confirmarlo. - Reparar con
dpkg --configure -ayapt -f install. - Si el problema persiste tras esto, revisar
systemctl list-jobs— puede haber un deadlock real entre servicios provocado porneedrestart, especialmente tras actualizar librerías base comolibc6. - Cancelar los jobs colgados con
systemctl cancel, reiniciar manualmente los servicios afectados en el orden correcto de dependencia, y validar consystemctl --failed.