Ejecutas umount /mnt/data y Linux responde con el encogimiento de hombros de siempre: target is busy. Ahora estás entre hacer lo correcto (encontrar quién mantiene el montaje) y hacer lo rápido (reiniciar y fingir que fue “mantenimiento planificado”).
Esta es una guía de campo para Debian 13: cómo identificar el proceso exacto, archivo, directorio, namespace o consumidor del kernel que mantiene un montaje, usando lsof, fuser y algunos trucos con /proc que funcionan cuando las herramientas “amigables” mienten.
Qué significa realmente “device busy” (y qué no significa)
Cuando umount falla con “device busy”, el kernel se niega a desacoplar un montaje porque algo todavía lo referencia. Ese “algo” puede ser:
- Un proceso con un descriptor de archivo abierto bajo el montaje.
- Un proceso con su directorio de trabajo actual (
cwd) en algún punto de ese árbol. - Un proceso con su directorio raíz (
chrooto pivot root) dentro de él. - Un bind mount, overlay o propagación de mounts que mantiene el subárbol fijado.
- Un consumidor del kernel (swapfile, dispositivo loop, objetivo dm-crypt, estado del cliente NFS).
- Un namespace de montaje diferente (contenedor, servicio systemd) que aún lo usa.
Lo que normalmente no es: “el dispositivo está lento” o “el sistema de archivos está corrupto”. Eso puede causar bloqueos, errores de E/S o timeouts, pero “busy” trata sobre referencias, no salud.
Hay dos modos de dolor diferentes:
- “Busy” inmediato: el kernel sabe que hay referencias activas y se niega a desmontar limpiamente.
- Desmontajes que cuelgan: ejecutaste
umounty se queda bloqueado. Eso suele ser sistemas de archivos en red (NFS) o E/S atascada, no solo un archivo abierto.
Arreglar esto de forma fiable significa dejar de adivinar y comenzar a preguntarle al kernel: “¿Quién sostiene este montaje?” El camino más rápido sigue siendo lsof y fuser, pero necesitas conocer sus puntos ciegos y cómo rodearlos.
Guion de diagnóstico rápido (primer/segundo/tercer chequeo)
Cuando estás de guardia, no tienes tiempo para bailar interpretativo con umount. Haz esto.
1) Primer chequeo: ¿alguien tiene archivos o cwd bajo ese montaje?
- Ejecuta
findmntpara confirmar que apuntas al montaje correcto. - Ejecuta
fuser -vmpara una lista rápida de PIDs y tipos de acceso. - Ejecuta
lsof +f -- /mountpointcuando necesites nombres de archivo y usuarios.
2) Segundo chequeo: ¿es realmente una pila de mounts / bind / propagación?
- Busca submontajes:
findmnt -R /mountpoint. - Busca bind mounts:
findmnt -o TARGET,SOURCE,FSTYPE,OPTIONSy revisabind,rbind,shared. - Si desmontas el padre mientras un hijo está montado, el padre estará “busy” por una buena razón.
3) Tercer chequeo: ¿el holder está fuera de tu namespace (contenedores/systemd) o es del kernel?
- Revisa namespaces de contenedores: mira
/proc/<pid>/mountinfoy usalsns. - Revisa swapfiles y dispositivos loop:
swapon --show,losetup -a. - Revisa apilamientos dm/lvm:
lsblk -o NAME,TYPE,MOUNTPOINTS,PKNAME,dmsetup ls --tree.
Si solo memorizas una cosa: no recurras a umount -l hasta que hayas identificado al holder. El lazy unmount es una herramienta, no un modo de vida.
Flujo principal: lsof → fuser → /proc → namespaces
Este es el flujo que uso en sistemas Debian cuando aparece “device busy”. Escala desde “un desarrollador dejó una shell allí” hasta “el runtime de contenedores fijó un bind mount en otro namespace”.
Empieza con la verdad del montaje: findmnt
La salida de mount está bien, pero findmnt es más estructurado y menos engañoso. Quieres: target, source, fstype y opciones, y ver submontajes.
Luego pregunta por los holders: fuser y lsof
fuser es contundente y rápido: “estos PIDs tocan este montaje.” Puede indicar si el proceso tiene cwd allí, está ejecutando un binario desde ahí o simplemente tiene archivos abiertos.
lsof es más lento pero más rico: muestra rutas de archivos, números de fd y si el proceso mantiene un archivo borrado (clásico).
Cuando las herramientas no coinciden: /proc es la fuente de la verdad
A veces lsof no muestra cosas por permisos, namespaces o por un número absurdo de archivos abiertos. Entonces vas a /proc y lees los enlaces de proceso directamente (cwd, root, fd), o la tabla de mounts del kernel (/proc/self/mountinfo).
Finalmente: conciencia de namespaces
Si el montaje está retenido dentro de un contenedor u otro namespace de montaje, puedes mirar con el lsof del host y aun así “no ver nada”. Usa lsns y nsenter para mirar desde la perspectiva del holder.
Una verdad seca: Linux está perfectamente feliz dejándole a dos mundos distintos pensar que existen mounts diferentes. Eso no es un bug. Es martes.
Tareas prácticas (comandos, significado de la salida, decisiones)
Estas son tareas reales que ejecuto en producción, más o menos en el orden que las busco. Cada una incluye: el comando, qué significa la salida y la decisión que tomas a continuación.
Task 1: Confirma el montaje exacto y su origen
cr0x@server:~$ findmnt /mnt/data
TARGET SOURCE FSTYPE OPTIONS
/mnt/data /dev/sdb1 ext4 rw,relatime
Qué significa: Estás desmontando /mnt/data, respaldado por /dev/sdb1. Si SOURCE es algo como server:/export (NFS) o /dev/mapper/vg-lv (LVM), ya sabes qué casos especiales podrían aplicar.
Decisión: Si este no es el montaje que pretendías (común con barras finales o mounts anidados), para y corrige el objetivo. Si no, continúa.
Task 2: Revisa submontajes que hacen que el padre esté “busy”
cr0x@server:~$ findmnt -R /mnt/data
TARGET SOURCE FSTYPE OPTIONS
/mnt/data /dev/sdb1 ext4 rw,relatime
/mnt/data/cache tmpfs tmpfs rw,nosuid,nodev
/mnt/data/containers overlay overlay rw,relatime,lowerdir=...
Qué significa: No puedes desmontar /mnt/data mientras /mnt/data/cache o /mnt/data/containers sigan montados. Los mounts padre no expulsan mágicamente a los hijos.
Decisión: Desmonta primero los hijos (desde la ruta más profunda), o usa umount -R con intención y cuidado.
Task 3: Rápido “quién toca este montaje” con fuser
cr0x@server:~$ sudo fuser -vm /mnt/data
USER PID ACCESS COMMAND
/mnt/data: root 1321 ..c.. bash
www-data 1874 ..c.. nginx
postgres 2440 ..c.. postgres
Qué significa: Estos procesos tienen algo bajo ese montaje como cwd o un archivo abierto (las banderas ACCESS varían; c comúnmente indica current directory). Eso suele ser suficiente para explicar “busy”.
Decisión: Decide si detener el servicio limpiamente, mover la shell o matar solo los PID(s) que mantienen el montaje.
Task 4: Obtén nombres de archivos y descriptores con lsof
cr0x@server:~$ sudo lsof +f -- /mnt/data | head -n 8
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1874 www-data 10u REG 8,17 4096 212 /mnt/data/www/access.log
postgres 2440 postgres 12u REG 8,17 1048576 877 /mnt/data/pg_wal/0000000100000000000000A1
Qué significa: Ahora tienes las rutas concretas. Esta es la diferencia entre “algo lo está usando” y “nginx todavía registra ahí”.
Decisión: Si es un servicio, deténlo. Si es un proceso puntual, mátalo. Si es un archivo de logs, rota/recarga correctamente.
Task 5: Atrapa el clásico “shell sentado en el directorio”
cr0x@server:~$ sudo ls -l /proc/1321/cwd
lrwxrwxrwx 1 root root 0 Dec 29 11:05 /proc/1321/cwd -> /mnt/data
Qué significa: El PID 1321 tiene su directorio de trabajo dentro del montaje. Eso por sí solo fija el montaje.
Decisión: Si es tu shell, cd /. Si es la sesión de otra persona, coordina o termínala.
Task 6: Encuentra procesos cuyo root está dentro del montaje (chroot/pivot_root)
cr0x@server:~$ sudo ls -l /proc/2890/root
lrwxrwxrwx 1 root root 0 Dec 29 11:06 /proc/2890/root -> /mnt/data/chroots/buildenv
Qué significa: Ese proceso tiene su root dentro del montaje. Es común con sistemas de build, herramientas de recuperación y algunas configuraciones de contenedores.
Decisión: Detén ese proceso limpiamente si es posible. Matarlo puede dejar hijos; prepárate para rastrear grupos de procesos.
Task 7: Cuando lsof es lento o incompleto, escanea /proc por cwd/root ofensores
cr0x@server:~$ sudo bash -lc 'for p in /proc/[0-9]*; do
pid=${p#/proc/}
cwd=$(readlink -f $p/cwd 2>/dev/null || true)
root=$(readlink -f $p/root 2>/dev/null || true)
if [[ "$cwd" == /mnt/data* || "$root" == /mnt/data* ]]; then
printf "%s cwd=%s root=%s\n" "$pid" "$cwd" "$root"
fi
done | head'
1321 cwd=/mnt/data root=/
2890 cwd=/ root=/mnt/data/chroots/buildenv
Qué significa: Has enumerado rápidamente los “pins” obvios sin depender de la caminata por la tabla de archivos de lsof.
Decisión: Investiga cada PID con ps y decide si detener/matar o reubicar.
Task 8: Confirma qué es realmente el proceso (y si es esperado)
cr0x@server:~$ ps -p 1874 -o pid,user,comm,args
PID USER COMMAND COMMAND
1874 www-data nginx nginx: worker process
Qué significa: Sin misterio: es nginx. “Busy” es legítimo.
Decisión: Detén/recarga nginx, o apunta logs/contenido fuera del montaje antes de desmontar.
Task 9: Revisa si systemd creó o gestiona el montaje (y puede volver a montarlo)
cr0x@server:~$ systemctl status mnt-data.mount
● mnt-data.mount - /mnt/data
Loaded: loaded (/etc/fstab; generated)
Active: active (mounted) since Mon 2025-12-29 10:02:10 UTC; 1h 4min ago
Where: /mnt/data
What: /dev/sdb1
Qué significa: systemd conoce este montaje. Si es un par automount, puede volver a montarlo tan pronto como algo toque la ruta.
Decisión: Si intentas mantenerlo desmontado, detén/deshabilita la unidad .automount relevante o elimina la entrada de fstab antes de continuar.
Task 10: Detecta automount de systemd que reacciona inmediatamente
cr0x@server:~$ systemctl status mnt-data.automount
● mnt-data.automount - Automount /mnt/data
Loaded: loaded (/etc/fstab; generated)
Active: active (waiting) since Mon 2025-12-29 10:01:59 UTC; 1h 4min ago
Where: /mnt/data
Qué significa: Incluso después de desmontar, el siguiente acceso a /mnt/data puede volver a montarlo. Además, algunos procesos “probe” (indexadores, monitorización, completion de shell) pueden seguir tocándolo.
Decisión: Para ventanas de mantenimiento, detén explícitamente la unidad de automount: systemctl stop mnt-data.automount, y luego desmonta.
Task 11: Confirma si un montaje es shared/slave (la propagación puede sorprenderte)
cr0x@server:~$ findmnt -o TARGET,PROPAGATION /mnt/data
TARGET PROPAGATION
/mnt/data shared
Qué significa: La propagación de mounts está en juego. Un montaje “shared” puede propagar submontajes a través de namespaces. Esto es común con runtimes de contenedores.
Decisión: Si estás diagnosticando un host de contenedores, asume que otro namespace puede sostenerlo. Pasa a la inspección de namespaces.
Task 12: Identifica namespaces de montaje y encuentra al probable holder
cr0x@server:~$ sudo lsns -t mnt | head
NS TYPE NPROCS PID USER COMMAND
4026531840 mnt 168 1 root /sbin/init
4026532501 mnt 15 6123 root /usr/bin/containerd
4026532710 mnt 3 9012 root /usr/sbin/cron
Qué significa: Tienes múltiples namespaces de montaje. Si un montaje está ocupado en un namespace, puede que no aparezca como esperas en otro.
Decisión: Revisa a los propietarios probables de namespaces (containerd, dockerd, podman, servicios systemd) e inspecciona desde dentro de ese namespace.
Task 13: Entra en el namespace de montaje de un PID sospechado y ejecuta findmnt allí
cr0x@server:~$ sudo nsenter -t 6123 -m -- findmnt /mnt/data
TARGET SOURCE FSTYPE OPTIONS
/mnt/data /dev/sdb1 ext4 rw,relatime
Qué significa: El montaje existe dentro del namespace de containerd también. Puede haber un contenedor haciendo un bind-mount, manteniéndolo vivo.
Decisión: Usa nsenter para ejecutar fuser/lsof dentro de ese namespace, o detén el contenedor/servicio responsable.
Task 14: Cuando un archivo borrado pero abierto ocupa espacio (y a veces expectativas)
cr0x@server:~$ sudo lsof +L1 -- /mnt/data | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 7777 app 25u REG 8,17 5242880 0 901 /mnt/data/app/logs/app.log (deleted)
Qué significa: El archivo fue borrado pero sigue abierto. Esto no siempre bloquea el desmontaje por sí mismo, pero suele ser una pista: un proceso sigue usando activamente el sistema de archivos.
Decisión: Reinicia/recarga ese proceso o fuerza que cierre los logs (logrotate con postrotate adecuado). No borres archivos esperando que eso baste.
Task 15: Revisa swapfiles (un “busy” a nivel kernel que no resuelve lsof)
cr0x@server:~$ sudo swapon --show
NAME TYPE SIZE USED PRIO
/mnt/data/swapfile file 8G 2G -2
Qué significa: Swap está en ese sistema de archivos. El kernel no te permitirá desmontar el sistema de archivos mientras provea swap.
Decisión: swapoff /mnt/data/swapfile (y asegura suficiente RAM o swap alternativo), luego intenta desmontar de nuevo.
Task 16: Encuentra dispositivos loop respaldados por archivos en el montaje
cr0x@server:~$ sudo losetup -a
/dev/loop2: [0801]:123456 (/mnt/data/images/debian.qcow2)
Qué significa: Un dispositivo loop está usando un archivo en el montaje. Esa es una referencia del kernel; el desmontaje fallará hasta que se desasocie el loop.
Decisión: Detén lo que use el dispositivo loop (herramientas VM, mount del loop), luego losetup -d /dev/loop2.
Task 17: Ve el apilamiento device-mapper/LVM que mantiene ocupado un dispositivo de bloque
cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MOUNTPOINTS,PKNAME
sdb disk 500G
└─sdb1 part 500G /mnt/data
Qué significa: Caso simple: partición directa. Si ves nodos dm-* o volúmenes lógicos LVM, “busy” puede deberse a holders por encima o por debajo de la capa del sistema de archivos.
Decisión: Si LVM/dm-crypt está implicado, verifica que desmontaste primero el sistema de archivos, luego desactiva LVs/ cierra luks solo después de que esté desmontado.
Task 18: Revisa descriptores de archivos abiertos directamente (cuando desconfías de lsof)
cr0x@server:~$ sudo ls -l /proc/1874/fd | head
total 0
lr-x------ 1 www-data www-data 64 Dec 29 11:10 0 -> /dev/null
l-wx------ 1 www-data www-data 64 Dec 29 11:10 10 -> /mnt/data/www/access.log
lr-x------ 1 www-data www-data 64 Dec 29 11:10 11 -> /mnt/data/www/index.html
Qué significa: Prueba concreta: nginx tiene descriptores hacia ese montaje. No hay debate.
Decisión: Detén/recarga nginx, o cambia la configuración para que deje de usar esas rutas.
Task 19: Intenta un desmontaje limpio con contexto
cr0x@server:~$ sudo umount /mnt/data
umount: /mnt/data: target is busy.
Qué significa: Sigue estando fijado. Ahora no malgastas movimientos; iteras basándote en la evidencia del holder.
Decisión: Resuelve holders (detén servicios, desasocia loops, swapoff, desmonta submontajes) y reintenta.
Task 20: Usa un lazy unmount cuando hayas decidido que es aceptable
cr0x@server:~$ sudo umount -l /mnt/data
Qué significa: El montaje se desacopla del namespace ahora, pero la limpieza real se difiere hasta que las referencias desaparezcan. Los procesos pueden seguir accediendo al sistema de archivos mediante descriptores existentes.
Decisión: Haz esto solo cuando puedas tolerar “acceso zombi” y estés seguro de que el dispositivo subyacente no desaparecerá durante E/S activa. Si vas a desconectar almacenamiento, el lazy unmount puede convertir “mantenimiento” en “autopsia”.
Task 21: Forzar unmount (último recurso, mayormente para mounts de red)
cr0x@server:~$ sudo umount -f /mnt/data
umount: /mnt/data: umount failed: Operation not permitted
Qué significa: En Linux, -f tiene sentido principalmente para ciertos sistemas de archivos de red y situaciones específicas; para ext4/xfs locales, a menudo no actúa como esperas.
Decisión: No trates -f como una palanca universal. Arregla el holder, o usa lazy unmount con los ojos abiertos.
Task 22: Verifica que realmente desapareció (y no se re-montó por automount)
cr0x@server:~$ findmnt /mnt/data
Qué significa: Sin salida: no está montado en tu namespace actual.
Decisión: Si vuelve inmediatamente después del desmontaje, algo está tocando la ruta y disparando automount. Detén la unidad de automount o arregla el consumidor.
Broma 1: “Device busy” es la forma del kernel de decir que tiene planes esta noche y tú no estás en la agenda.
Casos especiales: systemd, NFS, contenedores, bind mounts, loop/LVM/dm-crypt
Montajes y automounts de systemd: tu sistema de archivos ya tiene un gestor
En Debian 13, systemd suele estar en el circuito aunque nunca lo pidieras. Las entradas en /etc/fstab se convierten en unidades generadas. Eso es bueno para comportamiento consistente al arranque, pero puede sorprender durante mantenimiento:
- Automount hace que desmontar se sienta inestable: desmontas y un proceso cualquiera hace stat en el directorio y vuelve a montarlo.
- Dependencias de unidades pueden mantener montajes activos porque un servicio Requires= de ellos.
Cuando necesitas que permanezca abajo, detén primero el automount y considera enmascarar temporalmente la unidad si un servicio se comporta mal y la revive.
NFS y “umount cuelga” versus “device busy”
NFS es un dolor de otra clase. Puedes ver “device busy”, pero más comúnmente umount simplemente espera… y espera… porque el kernel está intentando vaciar o resolver operaciones pendientes.
Ajustes del flujo para NFS:
- Si
umountcuelga, comprueba primero la conectividad de red y la salud del servidor. “Busy” puede ser secundario. - Usa
umount -lcon más frecuencia para NFS cuando un servidor se fue y necesitas recuperar el cliente, pero entiende la compensación. - Los handles obsoletos y montajes “hard” pueden hacer que los listados de procesos sean engañosos.
Contenedores: el holder está en otro namespace de montaje
Las pilas modernas de contenedores adoran los bind mounts y overlayfs. También adoran namespaces de montaje separados. Así es como obtienes el escenario clásico:
- Host: “Nada está usando
/mnt/data”. - Kernel: “No estoy de acuerdo”.
- Realidad: un contenedor tiene un bind mount de
/mnt/datadentro de su namespace, y algún proceso allí mantiene un archivo.
La solución es aburrida: identifica el namespace, entra en él, encuentra el holder, detén el contenedor/servicio. Intentar ser más listo que los namespaces con herramientas solo del host es cómo se pierde una hora.
Bind mounts y propagación de mounts: el pegamento invisible
Los bind mounts pueden crear situaciones “busy” que parecen irracionales si solo miras el objetivo obvio. El árbol de mounts importa. También la propagación:
- Un bind mount de un directorio dentro de
/mnt/dataa otro sitio significa que procesos pueden mantener el sistema de archivos sin tocar directamente las rutas/mnt/data. - Los mounts shared pueden propagar submontajes y mantener referencias vivas a través de namespaces.
Usa findmnt -R para visualizar el subárbol. Usa findmnt -o TARGET,SOURCE,OPTIONS,PROPAGATION para ver por qué se comporta como una hidra.
Loop devices, swapfiles, dm-crypt, LVM: consumidores del kernel no aparecen como “archivo abierto”
Si trabajas con imágenes, volúmenes encriptados o swapfiles “temporales”, puedes tener referencias a nivel de kernel:
- Swapfile impide desmontar hasta
swapoff. - Dispositivo loop respaldado por un archivo impide desmontar hasta desasociarlo.
- Stacks device-mapper pueden mantener dispositivos de bloque ocupados incluso después de desmontar el sistema de archivos, lo cual importa si intentas quitar el dispositivo subyacente.
Errores comunes: síntoma → causa raíz → solución
Estos son los patrones que veo repetidos en tickets, salas de chat y líneas de tiempo de incidentes. Los síntomas son familiares; las causas raíz suelen ser mundanas.
1) Síntoma: “umount dice busy pero lsof no muestra nada”
Causa raíz: Otro namespace de montaje lo sostiene; o ejecutaste lsof sin privilegios suficientes; o la referencia “busy” es un consumidor del kernel (swap/loop) en lugar de un archivo abierto de userland.
Solución: Ejecuta con sudo. Revisa namespaces con lsns -t mnt e inspecciona usando nsenter -t PID -m. Revisa swapon --show y losetup -a.
2) Síntoma: El montaje padre no se desmonta, pero “paraste todas las apps”
Causa raíz: Hay un submontaje bajo el padre (tmpfs, overlay, bind mount, montaje de contenedor).
Solución: findmnt -R /mnt/data, desmonta los hijos más profundos primero. Si estás haciendo un teardown, considera umount -R pero entiende que es recursivo y con consecuencias.
3) Síntoma: Desmonté con éxito, pero se monta de nuevo inmediatamente
Causa raíz: systemd automount, autofs o un servicio que monta bajo demanda. A veces también es tu shell o un agente de monitorización que toca el directorio.
Solución: Detén la unidad de automount (systemctl stop mnt-data.automount). Confirma con systemctl status. Enmascara temporalmente si es necesario para la ventana de mantenimiento. Mueve los probes fuera de la ruta.
4) Síntoma: “device busy” solo al intentar desacoplar el dispositivo de bloque (no al desmontar)
Causa raíz: Puede que hayas desmontado el sistema de archivos, pero el dispositivo de bloque sigue siendo usado por dm-crypt, LVM, multipath, MD RAID o dispositivos loop.
Solución: Usa lsblk para mapear holders; revisa dmsetup ls --tree; cierra mappings luks o desactiva LVs después de desmontar el sistema de archivos limpiamente.
5) Síntoma: “umount cuelga” en vez de fallar rápido
Causa raíz: Normalmente problemas de sistemas de archivos en red (servidor NFS inaccesible, montaje hard), o E/S bloqueada al vaciar buffers. No es lo mismo que “busy”.
Solución: Revisa dmesg -T por NFS atascado o errores de E/S. Verifica la salud de la red. Considera lazy unmount para NFS como táctica de recuperación si aceptas las compensaciones.
6) Síntoma: Maté el PID, pero “busy” persiste
Causa raíz: Mataste al proceso equivocado (líder de hilo vs worker), o los hijos heredaron el cwd, o un servicio se reinició instantáneamente vía systemd, o queda un holder en otro namespace.
Solución: Ejecuta de nuevo fuser -vm. Inspecciona árboles de procesos (ps --ppid o pstree si está instalado). Detén la unidad systemd en lugar de jugar a la ruleta de PIDs.
7) Síntoma: “busy” después de una tarea de mantenimiento basada en chroot
Causa raíz: La shell chroot o algún proceso auxiliar mantuvo root dentro del montaje.
Solución: Encuentra ofensores vía comprobaciones de /proc/*/root; sal del chroot; mata procesos que queden.
8) Síntoma: Usaste umount -l, se desenchufó el almacenamiento y luego las apps explotaron
Causa raíz: El lazy unmount permitió acceso continuo mediante FDs existentes. Cuando el dispositivo subyacente desapareció, esos FDs empezaron a fallar de maneras interesantes.
Solución: No hagas lazy-unmount de un sistema de archivos que vas a quitar a menos que también termines a los holders o estés en un apagado controlado.
Listas de verificación / plan paso a paso (desatascar con seguridad)
Este es el plan “no improvises bajo presión”. Úsalo para sistemas de archivos locales y adáptalo para NFS y hosts de contenedores.
Checklist A: Desmontaje estándar de sistema de archivos local (ext4/xfs/btrfs)
- Confirma el montaje y submontajes:
findmnt /mnt/datafindmnt -R /mnt/data
Decisión: Si hay submontajes, agenda el orden de desmontaje (de más profundo a más superficial).
- Encuentra holders en userland:
sudo fuser -vm /mnt/datasudo lsof +f -- /mnt/data
Decisión: Detén servicios limpiamente; no mates a ciegas.
- Revisa pins por cwd/root:
- Escanea
/proc/*/cwdy/proc/*/rooten busca de rutas bajo el montaje.
Decisión: Mueve shells, sal de chroots, detén jobs de build.
- Escanea
- Revisa consumidores del kernel:
swapon --showlosetup -a
Decisión: swapoff, desasocia loops, luego reintenta.
- Desmonta hijos, luego el padre:
sudo umount /mnt/data/cacheetc.sudo umount /mnt/data
Decisión: Si sigue ocupado, vuelve a ejecutar fuser; algo aún vive.
- Solo entonces considera lazy unmount:
sudo umount -l /mnt/data
Decisión: Si vas a retirar el almacenamiento subyacente, no dejes holders en ejecución.
Checklist B: Host de contenedores (se esperan namespaces)
- Identifica propagación de mounts y bind mounts:
findmnt -o TARGET,SOURCE,OPTIONS,PROPAGATION /mnt/datafindmnt -R /mnt/data
Decisión: Si es shared, asume que otros namespaces participan.
- Encuentra propietarios de namespaces:
sudo lsns -t mnt
Decisión: Apunta a PID(s) del runtime de contenedores para usar
nsenter. - Inspecciona desde dentro del namespace sospechoso:
sudo nsenter -t <pid> -m -- fuser -vm /mnt/data
Decisión: Detén el contenedor o la carga responsable que mantiene el montaje.
- Detén servicios orquestados limpiamente:
Decisión: Detén mediante systemd u orquestador, no con SIGKILL aleatorio.
Checklist C: Cliente NFS (cuando aparecen timeouts y cuelgues)
- Comprueba si es “busy” o “colgado”:
- ¿
umountfalla inmediatamente o bloquea?
Decisión: Si bloquea, investiga salud del servidor/red primero.
- ¿
- Encuentra procesos:
sudo fuser -vm /mnt/nfs
Decisión: Detén holders; para clientes atascados, considera lazy unmount.
- Táctica de recuperación:
sudo umount -l /mnt/nfs
Decisión: Úsalo cuando el servidor se fue y necesitas restaurar la operatividad local; limpia después.
Tres microhistorias corporativas desde el campo
Microhistoria 1: El incidente causado por una suposición equivocada
El equipo hacía una migración de almacenamiento rutinaria en una flota Debian. El plan era limpio: drenar tráfico, parar la app, desmontar el sistema viejo, cambiar al nuevo, arrancar la app. Lo habían ensayado en staging y fue aburrido. Eso debería haber sido la pista de que producción encontraría una nueva forma de ser interesante.
En el primer host, umount devolvió “target is busy.” El on-call supuso que era “algún proceso sobrante”, ejecutó lsof sobre el montaje, no vio nada y decidió que debía ser seguro hacer lazy unmount. El montaje desapareció, el script continuó y el volumen físico se desconectó unos minutos después.
Unos diez minutos después, la app empezó a arrojar errores esporádicos de E/S. No en cada petición. No consistentemente. Solo en jobs en background que usaban procesos workers de larga duración. La ruta principal de solicitud parecía bien, porque esos procesos se reiniciaban más seguido y “olvidaban” viejos file descriptors.
La suposición equivocada fue sutil: “si lsof no muestra nada, nadie lo está usando”. En realidad, el holder estaba en otro mount namespace creado por un servicio auxiliar que lanzaba workers en un contexto aislado. El lsof a nivel host no mostraba la imagen completa que pensaban ver.
La solución fue directa una vez dejaron de adivinar: identificaron namespaces con lsns, entraron con nsenter en el namespace del worker, ejecutaron fuser, detuvieron la unidad correcta limpiamente y luego desmontaron normalmente. La acción del postmortem no fue “no usar lazy unmount”. Fue “no usar lazy unmount hasta que hayas probado quién lo sostiene, incluyendo otros namespaces”.
Microhistoria 2: La optimización que salió mal
Otra organización tenía la costumbre: cuando las ventanas de mantenimiento eran cortas, preconfiguraban automount en /etc/fstab para datasets voluminosos. La idea tenía sentido: no montar volúmenes enormes al arranque; montarlos bajo demanda; ahorrar tiempo de boot; reducir la superficie de impacto. Incluso monitorizaban la latencia de montaje.
Luego llegó un agente de escaneo de seguridad. Rastrilló árboles de sistema de archivos buscando tipos de archivo interesantes. No sabía que “tocar una ruta” podía montar un dataset, y no le importaba. De pronto, datasets se auto-montaban durante la preparación del mantenimiento, justo después de que el equipo los hubiera desmontado “con éxito”.
El paso de desmontaje empezó a oscilar: el desmontaje funcionaba, un segundo después se montaba de nuevo, y umount devolvía busy porque el scanner ahora tenía archivos abiertos en él. El equipo reaccionó como lo hacen los humanos cuando se irritan: matar el proceso del scanner. Se reiniciaba. Más muertes. Más reinicios. Finalmente alguien fue más listo y enmascaró la unidad de automount.
La optimización falló porque automount convierte “un directorio existe” en “un dispositivo debe estar presente”. Es conveniente hasta que quieres que un estado desmontado persista. La solución aburrida fue detener/deshabilitar el automount durante mantenimiento y excluir esas rutas de los escáneres. La solución cultural fue mejor: tratar automount como una característica que necesita controles operacionales, no como el valor por defecto para todo lo grande e inconveniente.
Broma 2: Automount es genial hasta que se convierte en un becario muy entusiasta que sigue conectando cosas porque “parecían desconectadas”.
Microhistoria 3: La práctica correcta y aburrida que salvó el día
Había un servicio que usaba mucho almacenamiento con control de cambios estricto. El equipo SRE tenía un playbook que requería: identificar holders con dos métodos independientes, detener servicios por nombre de unidad (no por PID) y verificar que los mounts desaparecieran con findmnt en el namespace correcto. Todos se quejaban de que era lento. Parecía burocracia disfrazada de rigor.
Durante una falla de hardware, necesitaban evacuar datos y desconectar un disco fallando. El sistema de archivos no se desmontaba. El junior on-call empezó a entrar en pánico y alcanzó umount -l, porque eso es lo que había visto en internet. El líder pidió los pasos del playbook. Sin debates. Solo los ejecutaron.
fuser señaló a un proceso agente de backups. lsof mostró que estaba escribiendo a un archivo temporal en el montaje. Detener el agente vía systemd no lo paró, porque era lanzado por una unidad timer que reiniciaba una nueva instancia al instante. El segundo método del playbook lo atrapó: systemctl list-timers y el estado de la unidad mostraron al culpable.
Detuvieron el timer, detuvieron el servicio, verificaron que no quedaran holders, desmontaron limpiamente y luego desacoplaron el disco sin sorpresa adicional. Nadie aplaudió. Ese es el punto. En respuesta a incidentes, la condición de victoria es “aburrido”, no “ingenioso”.
Hechos interesantes y contexto histórico
- 1) “EBUSY” tiene ADN de Unix antiguo. El error “device or resource busy” viene de décadas; es una negativa a nivel kernel a desacoplar algo aún referenciado.
- 2) Los namespaces de montaje cambiaron el significado de “quién lo está usando”. Desde la llegada de namespaces, un montaje puede estar ocupado “en otro lugar” aunque tu shell no lo vea.
- 3)
lsofno es una syscall del kernel; es un investigador. Recorre tablas de procesos y descriptores para inferir archivos abiertos, lo que significa que los permisos y la escala importan. - 4)
fuseres anterior a los contenedores pero sigue ganando en velocidad. Suele ser más rápido para “dame PIDs”, porque pregunta al kernel de forma distinta a la resolución completa de rutas de lsof. - 5) El lazy unmount existe porque la realidad es desordenada.
umount -lfue creado para casos donde necesitas desacoplar una ruta aun si quedan referencias, común en recuperación. - 6) “Busy” no trata solo de archivos. El cwd/root de un proceso es una referencia a un inode en ese sistema de archivos. Eso basta para que el kernel no lo desacople.
- 7) Los swapfiles son una clásica trampa. Parecen “solo un archivo” hasta que descubres que el kernel los trata como dispositivo de paginación y se niega a desmontar.
- 8) Los dispositivos loop convierten un archivo en dispositivo de bloque. Por eso las imágenes respaldadas por loop mantienen sistemas de archivos ocupados aún cuando no aparece un proceso userland con un archivo abierto de forma obvia.
- 9) systemd generando unidades de mount desde fstab cambió expectativas operacionales. Los mounts ahora son “objetos gestionados” con dependencias, timeouts y comportamiento de automount.
Preguntas frecuentes (FAQ)
Q1: ¿Cuál es el comando único más rápido para encontrar qué bloquea umount?
A: Empieza con sudo fuser -vm /mnt/data. Es rápido, legible y te dice qué PIDs están implicados. Sigue con lsof para nombres de archivo.
Q2: ¿Por qué a veces lsof tarda una eternidad en sistemas grandes?
A: Puede ser proporcional a “procesos × descriptores de archivo”, y a menudo resuelve rutas. En hosts con muchos contenedores y miles de FDs por proceso, está haciendo trabajo real. Usa fuser primero, o lsof dirigido por PID cuando ya tengas sospechosos.
Q3: ¿Por qué no funciona umount -f para sistemas de archivos locales?
A: En Linux, “forzar” unmount tiene sentido principalmente para ciertos sistemas de archivos de red o casos especiales. Para ext4/xfs locales, el kernel no los arrancará si están ocupados, porque eso crea problemas de consistencia.
Q4: ¿Es seguro umount -l?
A: Puede ser seguro en escenarios controlados: necesitas que la ruta se desacople y sabes que el almacenamiento subyacente seguirá accesible hasta que los holders terminen. Es inseguro si planeas quitar el almacenamiento mientras los holders siguen en ejecución.
Q5: ¿Cómo sé si un contenedor está sosteniendo mi montaje?
A: Revisa namespaces de montaje con sudo lsns -t mnt, identifica PIDs probables del runtime, luego nsenter -t PID -m y ejecuta findmnt/fuser allí. Si encuentras holders, detén el contenedor/servicio limpiamente.
Q6: ¿Realmente puede bloquear el “directorio actual” aunque no haya archivos abiertos?
A: Sí. El cwd de un proceso es una referencia a un inode en ese sistema de archivos. El kernel no desacoplará un sistema de archivos que aún tenga referencias activas.
Q7: ¿Por qué se re-monta justo después de desmontar?
A: Automount (systemd o autofs) o un servicio tocando la ruta. Deshabilita/detén la unidad de automount durante mantenimiento y averigua quién está sondeando el directorio.
Q8: ¿Y si fuser muestra PIDs pero matarlos no ayuda?
A: Puede que estés matando workers mientras un supervisor los reinicia (systemd, cron, timers), o que el holder esté en otro namespace. Detén la unidad, no el síntoma, y vuelve a comprobar namespaces.
Q9: ¿Cómo demostrar confiablemente que está desmontado?
A: Usa findmnt /mnt/data (sin salida significa desmontado en ese namespace). También revisa findmnt -R /mnt/data por submontajes persistentes. Si hay namespaces involucrados, verifica también dentro del namespace relevante.
Q10: ¿Alguna filosofía operativa además de comandos?
A: Sí: identifica al holder antes de elegir el método para desatascar. Como ha enfatizado el pensador de sistemas John Allspaw (idea parafraseada), la resiliencia viene de entender cómo se hace el trabajo realmente, no cómo esperabas que se hiciera.
Próximos pasos que deberías hacer realmente
Cuando la página se calme y ya no estés mirando “device busy”, haz las pequeñas correcciones que previenen la próxima ronda de dolor:
- Codifica el flujo en un runbook:
findmnt→findmnt -R→fuser→lsof→ namespaces → consumidores del kernel. - Deja de matar PIDs como primera respuesta. Prefiere detener la unidad systemd, el contenedor o el timer. Los procesos reaparecen.
- Audita swapfiles e imágenes respaldadas por loop bajo montajes extraíbles. Si debes usarlos, documéntalos y crea un procedimiento de teardown.
- Para automounts, define un modo de mantenimiento: una secuencia conocida de comandos que detiene automount y suprime probes “útiles”.
- Forma a tu equipo en namespaces. Ya no es avanzado; es Linux normal. “No lo veo” no es lo mismo que “no está ahí”.