Todo equipo de operaciones tiene una historia de fantasmas. No del tipo «la sala de servidores está encantada»—esos suelen ser problemas de ventilación o puertas de rack mal cerradas.
Me refiero a la historia que empieza con una ventana de cambios calmada y termina con una consola que te devuelve la mirada como un frigorífico vacío.
rm -rf / es el coco, claro, pero el verdadero villano siempre es el mismo: la certeza humana aplicada a un sistema incierto.
Esto explica cómo el comando se volvió un género, qué se rompe realmente cuando se ejecuta (o casi se ejecuta) y qué debes hacer para que tu nombre nunca forme parte del folclore de otra gente.
Qué significa realmente rm -rf / (y por qué es peor de lo que suena)
En teoría, rm elimina entradas de directorio. En la práctica, en un sistema en producción, elimina las rutas que tu SO necesita para seguir siendo un SO.
Las opciones son las que lo convierten en leyenda:
-r(recursivo): recorre el árbol, borrando todo lo que pueda alcanzar.-f(forzar): no hace preguntas; suprime muchos errores; continúa sin detenerse./: empieza en el directorio raíz, la parte superior de casi todo lo que te importa.
«Casi» hace mucho trabajo ahí. Linux no es un gran montón de archivos. Es un montón de puntos de montaje: sistema de archivos raíz, /boot separado,
/var, /home, /run efímero, montajes de red, bind mounts, overlays de contenedores y cualquier otra cosa que el equipo de plataforma haya hecho durante un incidente hace tres años.
rm -rf / intenta recorrer toda esa topología. Hasta dónde llega depende de los límites de montaje, permisos, banderas inmutables,
si eres root, si estás en un contenedor y si tu distro tiene salvaguardas. Pero incluso lo «parcial» es catastrófico: borrar suficiente de /lib o /usr
puede convertir a cada proceso en ejecución en un turista condenado—vivo durante un rato, pero incapaz de cargar la siguiente biblioteca compartida, ejecutar el siguiente binario o reiniciar el servicio que tratabas de arreglar.
Una forma práctica de pensarlo: no estás «borrando el SO», estás borrando las suposiciones que permiten que el SO siga curándose a sí mismo.
La mayoría de las interrupciones en producción no son explosiones dramáticas. Son sistemas que pierden la capacidad de recuperarse de fallos pequeños.
Broma #1: La forma más rápida de aprender recuperación ante desastres es teclear rm -rf / una vez. La segunda más rápida es ver a tu compañero hacerlo.
Hay un giro adicional: en sistemas modernos, el comando que escribiste no siempre es el que se ejecuta. Alias de shell, envoltorios (buenos o malos)
y capas de automatización pueden cambiar la semántica. Si estás en un contenedor, / podría ser el sistema de archivos del contenedor, no el del host—a menos que hayas montado el host dentro.
En Kubernetes, puedes eliminar un deployment y recrearlo; eliminar el PersistentVolumeClaim equivocado y estás practicando aceptación.
El peligro más profundo: borrar «nombres» mientras los procesos siguen en ejecución
Unix permite que un proceso mantenga un archivo abierto incluso después de que haya sido desvinculado. Eso es una característica—hasta que no lo es.
Cuando borras un archivo de log que usa un proceso en ejecución, el uso de disco puede no bajar, porque el inode sigue abierto. Cuando borras bibliotecas compartidas bajo un servicio en ejecución,
el servicio puede seguir funcionando hasta el siguiente reload, despliegue continuo, crash o fork/exec. Por eso algunos incidentes con rm -rf parecen «bien»
durante minutos u horas, y luego se deshacen en el peor momento: en el siguiente reinicio, durante un failover o después de un reboot del nodo.
Cómo ocurre realmente en la vida corporativa
La mayoría de los equipos imagina un incidente «rm -rf /» como un administrador aburrido haciendo algo caricaturescamente temerario. La realidad es más mundana y peligrosa:
es un ingeniero cansado, un plazo ajustado, un copy-paste, una shell en producción que se parece a staging, y un comando que «siempre funcionó antes».
El género persiste porque es una tormenta perfecta de anti-patrones operativos:
- Intención ambigua: «Limpiar disco» no es una tarea; es un síntoma.
- Comandos por memoria muscular:
rm -rfse vuelve un reflejo en lugar de una decisión. - Dériva de privilegios: pediste sudo «temporalmente», y se quedó.
- Confusión de entorno: las shells de prod y stage difieren por un título de pestaña.
- Automatización sin frenos: el comando estaba dentro de un script, herramienta o job.
Aquí soy opinativo: si un sistema requiere que los humanos borren archivos rutinariamente bajo presión, al sistema le falta una capa de seguridad. Los humanos no son
capas de seguridad. Los humanos son la razón por la que necesitamos capas de seguridad.
Hechos e historia: cómo llegamos aquí
Este comando no se volvió meme por accidente. Algo de historia concreta te ayuda a predecir cómo se comportará tu entorno:
- Los primeros Unix hicieron la eliminación intencionalmente simple. La filosofía favorecía herramientas pequeñas y composabilidad; las barreras eran culturales, no técnicas.
rmelimina entradas de directorio, no «borra de forma segura». Los datos pueden persistir en disco hasta ser sobrescritos; por eso a veces funcionan las herramientas de recuperación.- La «protección del directorio raíz» evolucionó con el tiempo. GNU coreutils introdujo
--preserve-rootpor defecto en muchas distros para prevenirrm -rf /. - BusyBox y sistemas embebidos difieren. Algunos entornos tienen implementaciones más pequeñas o diferentes de
rm; las suposiciones de los servidores no siempre se aplican. - Los namespaces de montaje cambiaron el radio de daño. Contenedores y chroots pueden hacer que «/» signifique otra cosa—hasta que montas el host dentro.
- Systemd aumentó la dependencia de
/runy del estado generado. Borrar bajo/runpuede romper servicios inmediatamente de formas extrañas. - Sistemas de archivos copy-on-write cambiaron la matemática de recuperación. Snapshots en ZFS/Btrfs pueden hacer que un «ups» sea recuperable—si existen snapshots y la retención tiene sentido.
- La automatización de operaciones convirtió errores individuales en eventos de flota. Un mal
rmen una ejecución de gestión de configuración puede propagarse rápido.
Observa el patrón: cada era añade poder y luego nuevas formas de aplicar ese poder a gran escala. Por eso el género sigue estrenando secuelas.
Modos de fallo: qué se rompe primero, después y de forma extraña más tarde
1) Fallo inmediato: desaparecen binarios y bibliotecas
Borra suficiente de /bin, /sbin, /usr/bin, /lib, /lib64 y pierdes la capacidad de ejecutar comandos,
reiniciar demonios o incluso autenticar. Las sesiones SSH pueden permanecer, pero cualquier nuevo intento de login puede fallar si faltan módulos PAM o shells.
2) Falla en cámara lenta: el sistema sigue funcionando… hasta que necesita exec
Los procesos en ejecución pueden seguir ejecutando código que ya está en memoria. Por eso el primer gráfico que ves puede estar «todo en verde».
Luego ocurre un reload del servicio. Un nuevo worker intenta arrancar. Un health check provoca un reinicio. Y de repente la máquina no puede generar el proceso
que habría arreglado el servicio.
3) Confusión plano de datos vs plano de control
En sistemas modernos, el plano de control (orquestación, agentes, gestores de paquetes, configuración) es lo que trae de vuelta al plano de datos.
rm -rf suele matar primero el plano de control: desaparecen binarios de agentes, se paran servicios del sistema, desaparecen configuraciones de DNS, faltan certificados.
Ahora incluso «reinstalar el paquete» se convierte en «¿cómo ejecuto el instalador?».
4) Dolor específico del almacenamiento: borrados parciales, estado de app inconsistente
Los sistemas de archivos no garantizan consistencia a nivel de aplicación. Si borras partes de un directorio de base de datos, puedes acabar con algo peor que «caído»:
obtienes «arriba pero mintiendo». Algunas bases de datos se niegan a arrancar si faltan archivos (bien). Otras arrancan y sirven datos parciales (mal).
En almacenamiento en red, los borrados pueden ser asíncronos o retardados por caching.
5) Matices de virtualización y contenedores
En un host, borrar / suele ser fatal. En un contenedor, puede ser una capa reseteable—a menos que el contenedor tenga montajes privilegiados o escriba en volúmenes.
El patrón más trágico en 2026 no es «alguien dinamitó el sistema de archivos del contenedor».
Es «alguien dinamitó el volumen persistente montado porque parecía un directorio temporal».
Cita (idea parafraseada): Todo falla, y la resiliencia viene de diseñar para la recuperación, no de creer que puedes prevenir todos los errores.
— Werner Vogels (idea parafraseada)
Broma #2: Lo único más permanente que un recurso en la nube es un comando de borrado que ejecutaste con -f.
Guía de diagnóstico rápido
Este es el orden de triaje que uso cuando alguien dice «creo que borré algo» o «la máquina actúa como encantada» y los logs están sospechosamente silenciosos.
Tratas de responder tres preguntas rápido: (1) ¿sigue el host siendo confiable?, (2) ¿qué falta?, (3) ¿recuperamos reparando, haciendo rollback o reconstruyendo?
Primero: confirma el alcance y detén la hemorragia
- Congela la automatización: detén ejecuciones de gestión de configuración, jobs cron, despliegues CI/CD y autorremediaciones que puedan seguir borrando o «arreglando» lo equivocado.
- Preserva la sesión: mantén viva cualquier shell root existente; no cierres la sesión. Un reboot suele ser un punto de no retorno.
- Identifica si es host vs contenedor: un contenedor puede reemplazarse; un host puede contener datos únicos.
Segundo: verifica si el sistema aún puede ejecutar herramientas básicas
- ¿Puedes ejecutar
/bin/ls? Si no, estás en territorio de reconstrucción. - ¿Está
/liblo bastante intacto para el enlace dinámico? Si faltan libs compartidas, muchos comandos fallarán con «No such file or directory» aunque el binario exista. - ¿El gestor de paquetes funciona? Si sí, podrías reinstalar paquetes faltantes.
Tercero: elige la vía de recuperación según lo que importe
- Si los datos están intactos y el SO es reproducible: reconstruye el host y vuelve a adjuntar los volúmenes de datos.
- Si el SO está intacto y faltan pocos archivos: restaura desde snapshot/backups, o reinstala paquetes, y luego verifica integridad.
- Si la integridad de los datos es incierta: detén los servicios, haz snapshot del estado dañado (si es posible) y restaura en un entorno limpio para validar.
Buscador rápido de cuellos de botella (cuando el sistema está «lento» tras un casi-accidente)
A veces el incidente es un casi-accidente: el borrado se abortó, pero el sistema ahora está cojeando—bloqueos en la DB de paquetes, IO de disco disparado, replay de journaling,
agotamiento de inodos o un proceso desbocado escaneando el sistema de archivos. Este es el camino más corto al cuello de botella:
- ¿Saturación de IO de disco? Revisa
iostat/pidstaty pistas de latencia del sistema de archivos. - ¿Sistema de archivos lleno o sin inodos? Revisa
dfydf -i. - ¿Hay un borrar desbocado aún en ejecución? Encuentra procesos
rmy recorridos de directorio conlsofyps. - ¿Confusión de montajes? Verifica qué está montado dónde con
findmnt. - ¿Logging o journald en espiral? Revisa errores en
journalctly uso de disco.
Tareas prácticas: comandos, salidas y decisiones (12+)
Estos son comandos reales y ejecutables. Cada uno incluye qué significa la salida y qué decisión debería forzarte a tomar.
Úsalos en orden de menos destructivo a más invasivo.
Task 1: Confirma dónde apunta realmente “/” (host vs contenedor)
cr0x@server:~$ cat /proc/1/cgroup | head
0::/user.slice/user-1000.slice/session-3.scope
Significado: Si PID 1 es systemd en el host, verás slices del host. En contenedores, a menudo ves rutas docker/kubepods.
Decisión: Si es un contenedor, reemplazarlo puede ser mejor que recuperarlo—a menos que los volúmenes persistentes hayan sido afectados.
Task 2: Verifica qué está montado y dónde podrían haberse cruzado los borrados
cr0x@server:~$ findmnt -R / | head -n 15
TARGET SOURCE FSTYPE OPTIONS
/ /dev/nvme0n1p2 ext4 rw,relatime
|-/boot /dev/nvme0n1p1 ext4 rw,relatime
|-/var /dev/nvme1n1p1 xfs rw,relatime
|-/run tmpfs tmpfs rw,nosuid,nodev
`-/mnt/data tank/data zfs rw,xattr,noacl
Significado: Borrar “/” podría haber tocado /var y /mnt/data también, dependiendo del recorrido y permisos.
Decisión: Si datos críticos están en montajes separados, prioriza preservar y snapshotear esos montajes antes de hacer cualquier otra cosa.
Task 3: Comprueba si un borrado sigue en ejecución (detén la hemorragia)
cr0x@server:~$ ps -eo pid,etime,cmd | grep -E 'rm -rf|rm -r|unlink' | grep -v grep
24188 00:02 rm -rf /var/tmp/cache
Significado: El proceso ofensivo podría estar aún recorriendo el árbol.
Decisión: Si está apuntando al camino equivocado, páralo inmediatamente (kill o aisla el host). Si está apuntando al camino correcto y es necesario, considera limitar la velocidad en lugar de matarlo.
Task 4: Confirma que el sistema de archivos raíz no esté lleno ni sin inodos
cr0x@server:~$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p2 80G 78G 1.2G 99% /
Significado: Estás a una instalación de paquete de la falla, y los archivos temporales no pueden crearse con fiabilidad.
Decisión: Si necesitas acciones de recuperación que escriban en disco (reinstalar paquetes, restaurar archivos), libera espacio primero—con cuidado y con borrados dirigidos.
cr0x@server:~$ df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/nvme0n1p2 5242880 5242000 880 100% /
Significado: Agotamiento de inodos. Puedes tener GB libres pero aun así no poder crear archivos.
Decisión: Busca explosiones de archivos pequeños (caches, temp dirs). No lances «scripts de limpieza» que puedan vagar hacia territorio inseguro.
Task 5: Detecta rápidamente directorios núcleo faltantes
cr0x@server:~$ ls -ld /bin /sbin /lib /lib64 /usr /etc
ls: cannot access '/lib64': No such file or directory
drwxr-xr-x 2 root root 4096 Jan 22 09:10 /bin
drwxr-xr-x 2 root root 4096 Jan 22 09:10 /etc
drwxr-xr-x 2 root root 4096 Jan 22 09:10 /lib
drwxr-xr-x 2 root root 4096 Jan 22 09:10 /sbin
drwxr-xr-x 9 root root 4096 Jan 22 09:10 /usr
Significado: Si directorios faltan por completo, el sistema ya está en mal estado; si están presentes, el contenido aún puede estar eliminado.
Decisión: Si rutas núcleo faltan, inclínate hacia reconstruir y restaurar en lugar de reparaciones parciales.
Task 6: Prueba si el enlazado dinámico está roto
cr0x@server:~$ /bin/ls --version
/bin/ls: error while loading shared libraries: libselinux.so.1: cannot open shared object file: No such file or directory
Significado: El binario existe, pero faltan bibliotecas compartidas requeridas.
Decisión: No pierdas tiempo intentando «arreglar un servicio». Si faltan libs núcleo, necesitas reinstalar paquetes desde una fuente confiable o reconstruir.
Task 7: Determina qué paquetes poseen un archivo faltante (ejemplo RPM)
cr0x@server:~$ rpm -qf /usr/bin/ssh
openssh-clients-8.7p1-36.el9.x86_64
Significado: El paquete que debería proveer ese archivo.
Decisión: Si el gestor de paquetes funciona y los repos son accesibles, reinstala el conjunto de paquetes para los binarios faltantes—luego verifica integridad.
Task 8: Verifica señales de integridad del sistema de archivos (ejemplo ext4)
cr0x@server:~$ dmesg | tail -n 12
[ 9832.118331] EXT4-fs warning (device nvme0n1p2): ext4_dx_add_entry:2534: Directory index full!
[ 9832.118899] EXT4-fs (nvme0n1p2): mounted filesystem with ordered data mode. Quota mode: none.
Significado: Podrías tener problemas de índices/directorios/inodos, o recuentos patológicos de archivos.
Decisión: Si el kernel advierte sobre estructuras del sistema de archivos, programa un fsck offline y prepárate para reconstruir; no sigas martillando el disco.
Task 9: Identifica archivos «borrados pero aún abiertos» que consumen disco
cr0x@server:~$ lsof +L1 | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 4121 app 123w REG 253,0 104857600 0 91827 /var/log/app/app.log (deleted)
Significado: El espacio en disco no se recuperará hasta que el proceso cierre el descriptor de archivo.
Decisión: Reinicia el servicio (con cuidado) o mándale señal para reabrir logs. Esta es una trampa clásica: «borramos logs pero el disco sigue lleno».
Task 10: Confirma qué cambió recientemente (escaneo mtime con restricción)
cr0x@server:~$ find /etc -maxdepth 2 -type f -mmin -60 | head
/etc/resolv.conf
/etc/ssh/sshd_config
/etc/systemd/system/app.service
Significado: Muestra archivos modificados en la última hora—útil para correlacionar con un script malo o un deploy.
Decisión: Si configs núcleo cambiaron inesperadamente, trátalo como un fallo de automatización; revierte la configuración vía GitOps o restaura versiones conocidas buenas.
Task 11: Estado de snapshots en ZFS antes de «arreglar» nada
cr0x@server:~$ zfs list -t snapshot | tail -n 5
tank/data@hourly-2026-01-22-0800 0B - 120G -
tank/data@hourly-2026-01-22-0900 0B - 120G -
Significado: Existen snapshots. Esa es tu red de seguridad, si no la destruyes con una «limpieza».
Decisión: Si sospechas pérdida de datos, clona el snapshot para investigación en lugar de hacer rollback in situ.
Task 12: Restaurar un solo directorio desde un snapshot ZFS (vía clone + rsync)
cr0x@server:~$ zfs clone tank/data@hourly-2026-01-22-0900 tank/restore_tmp
cr0x@server:~$ rsync -aH --numeric-ids /tank/restore_tmp/appstate/ /mnt/data/appstate/
sending incremental file list
./
db/
db/manifest.json
sent 1,284 bytes received 92 bytes 2,752.00 bytes/sec
total size is 9,812,034 speedup is 7,131.35
Significado: Restauraste solo lo que necesitabas, preservando propiedad y hardlinks.
Decisión: Prefiere restauraciones quirúrgicas sobre rollback completo cuando la disponibilidad importa y no estás seguro del alcance exacto del borrado.
Task 13: Listado de snapshots Btrfs y restauración dirigida
cr0x@server:~$ btrfs subvolume list /mnt
ID 256 gen 9012 top level 5 path @
ID 257 gen 9011 top level 5 path @home
ID 410 gen 9001 top level 5 path @snapshots/2026-01-22_0900
cr0x@server:~$ rsync -aH --numeric-ids /mnt/@snapshots/2026-01-22_0900/etc/ /etc/
sending incremental file list
./
ssh/sshd_config
sent 23,110 bytes received 1,204 bytes 48,628.00 bytes/sec
total size is 214,980 speedup is 8.84
Significado: Puedes tratar snapshots como árboles de origen de solo lectura para restaurar.
Decisión: Si no tienes snapshots, deja de discutir «no los necesitamos» y empieza a presupuestarlos.
Task 14: Detecta alias peligrosos y opciones de shell que ocultan riesgo
cr0x@server:~$ alias rm
alias rm='rm -i'
Significado: El prompt interactivo puede prevenir errores en tu shell—pero no protegerá scripts, cron o sesiones no interactivas.
Decisión: No confíes en alias como seguridad. Usa límites de permiso, snapshots y salvaguardas en las herramientas.
Task 15: Confirma la configuración preserve-root de GNU rm
cr0x@server:~$ rm --help | grep -E 'preserve-root|no-preserve-root'
--preserve-root do not remove '/' (default)
--no-preserve-root do not treat '/' specially
Significado: En este sistema, rm por defecto se niega a eliminar /.
Decisión: Bien, pero no suficiente: los scripts aún pueden apuntar a montajes críticos, y alguien puede pasar --no-preserve-root.
Task 16: Audita un script sospechoso sin ejecutarlo
cr0x@server:~$ bash -n /usr/local/bin/cleanup.sh
cr0x@server:~$ shellcheck /usr/local/bin/cleanup.sh | head
In /usr/local/bin/cleanup.sh line 18:
rm -rf "$TARGET_DIR"/*
^-- SC2115 (warning): Use "${var:?}" to ensure this never expands to /* .
Significado: Análisis estático detectó un clásico peligro de expansión.
Decisión: Si un script de limpieza puede expandirse a /*, trátalo como un arma cargada. Arréglalo, añade salvaguardas y tests.
Tres micro-historias corporativas (anónimas, dolorosamente plausibles)
Micro-historia 1: El outage causado por una suposición equivocada
Un equipo mantenía una flota de hosts Linux que ejecutaban una mezcla de servicios legacy y cargas en contenedores. Tenían un «layout estándar»:
los datos de la aplicación vivían en /srv/app, y el SO en el volumen raíz. El runbook on-call decía: «Si el disco está lleno, limpia archivos antiguos en
/srv/app/tmp«.
Una nueva imagen de host llegó en silencio. Todavía tenía /srv/app/tmp, pero ahora era un symlink a /var/tmp/app para unificar logging y manejo de temporales.
Ese cambio nunca se documentó, porque parecía una «refactorización interna», y a los servicios no les importó.
Una noche, el uso de disco cruzó un umbral. El on-call se conectó, ejecutó el comando habitual para limpiar temporales y notó que tardaba más de lo normal.
Añadió un -f y se fue a atender otra alerta. El borrado ahora estaba rastreando por /var, no por un directorio estrecho de temporales,
y se estaba comiendo más que cachés: logs rotados, estado de runtime y partes de la base de datos de paquetes.
El servicio no falló inmediatamente. Se degradó. Luego el nodo se reinició por el schedule de kernel, y apareció el daño real:
servicios del sistema no arrancaban, la resolución DNS fallaba y el nodo no podía descargar imágenes porque faltaban certificados y bundles CA.
La capa de orquestación lo marcó como no saludable y reubicó cargas, lo que ocultó el incidente hasta que un evento de escalado consumió la capacidad restante.
El postmortem no fue «no borres cosas». La solución fue estructural: eliminar sorpresas de symlinks, hacer de la limpieza de temporales una operación a nivel de servicio
y tratar «¿a dónde apunta realmente esta ruta?» como una comprobación de primera clase en los runbooks. Además: deja de tratar el «layout estándar» como religión.
El layout estándar es un rumor a menos que se valide continuamente.
Micro-historia 2: La optimización que salió mal
Un equipo de plataforma quería despliegues más rápidos. Construyeron un paso de limpieza en su pipeline para eliminar directorios de releases antiguos:
/opt/app/releases/*, conservar los tres últimos, borrar el resto. Sensato. Luego alguien notó que la limpieza a veces tardaba minutos en hosts ocupados.
«Optimizó» con un borrado paralelo: encontrar releases viejos y eliminarlos concurrentemente.
La optimización funcionó en staging. En producción, creó un nuevo modo de fallo: las releases contenían bind mounts usados para profiling de rendimiento y
caches efímeras. Los borrados paralelos provocaron una tormenta de operaciones de sistema de archivos, saturando IO. La latencia subió, no solo para la app, sino para todo el nodo.
Los health checks fallaron. Servicios se reiniciaron. Los reinicios se ejecutaron desde directorios parcialmente borrados.
Luego el verdadero pie en la trampa: en un despliegue, la variable que apuntaba al directorio de releases estaba vacía porque un paso previo falló.
El script siguió corriendo. La salvaguarda era «si el directorio existe», que pasó porque el script recayó en /opt/app.
Bajo el borrado paralelo, eliminó mucho más de lo previsto, incluyendo bibliotecas compartidas distribuidas con la app.
El equipo se recuperó rápido redeployando, pero el incidente fue caro en tiempo y credibilidad. La lección fue aburrida y poco glamorosa:
no optimices operaciones destructivas sin medir efectos a nivel del sistema y nunca dejes que una ruta de borrado se calcule sin validación rígida.
Si quieres velocidad, usa snapshots y cambios atómicos, no borrados más rápidos.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Un servicio cercano a finanzas almacenaba datos críticos en datasets ZFS con snapshots horarios retenidos 72 horas y snapshots diarios 30 días.
No era sofisticado. Era política: «Cada dataset tiene snapshots. Sin excepciones. Se aplica retención. Se hacen simulacros de restauración trimestrales.»
La gente se quejaba porque consumía espacio y requería planificación.
Durante una ventana de mantenimiento, un ingeniero ejecutó un comando de limpieza destinado a un montaje de staging. La ruta parecía correcta y el tab completion «ayudó».
Era el montaje de producción. Se dieron cuenta en minutos porque el monitoreo estaba afinado para detectar churn de archivos y picos de escritura en datasets ZFS, no solo CPU.
Hicieron dos cosas inteligentes inmediatamente: primero, detuvieron el servicio para evitar escribir nuevos datos en una estructura de directorios medio borrada. Segundo,
crearon un snapshot nuevo del dataset dañado (sí, haz snapshot del desastre) para preservar el estado forense. Luego clonaron el último snapshot limpio
y restauraron solo los subdirectorios faltantes.
El servicio volvió en un tiempo razonable y no necesitaron revertir todo el dataset, evitando pérdida de datos de los minutos posteriores al snapshot.
El postmortem también fue aburrido: nada de heroísmos, solo un recordatorio de que los snapshots no son «teatro de backups» si realmente puedes restaurar rápido.
Los simulacros de restauración del equipo hicieron que nadie tuviera que adivinar los comandos bajo presión.
Errores comunes: síntoma → causa raíz → solución
1) «El disco sigue lleno después de borrar logs»
Síntoma: df -h no muestra espacio libre aunque borraste archivos grandes.
Causa raíz: Los archivos fueron borrados pero permanecen abiertos por procesos en ejecución (inodos desvinculados).
Solución: Usa lsof +L1 para encontrar culpables; reinicia el proceso o mándale señal para reabrir logs. Considera copytruncate en logrotate solo cuando sea necesario; prefiere reabrir correctamente.
2) «Los comandos dicen ‘No such file or directory’ pero el binario existe»
Síntoma: Ejecutar /bin/ls falla aunque ls está presente.
Causa raíz: El cargador dinámico o bibliotecas compartidas fueron removidos (ej., /lib64/ld-linux-x86-64.so.2 u otras dependencias).
Solución: Deja de intentar reinicios aleatorios. Restaura/reinstala bibliotecas núcleo via gestor de paquetes o reconstruye desde una imagen. Si el gestor de paquetes está roto, usa medios de rescate o ata el disco a otro host.
3) «El sistema arranca pero los servicios no se inician»
Síntoma: Tras un reinicio, muchas unidades fallan; journald se queja; la red puede estar rota.
Causa raíz: Borrado parcial bajo /etc, /usr, /var, o archivos de unidades systemd y dependencias faltantes.
Solución: Trátalo como fallo de integridad. Si tienes snapshots, restaura configs y unidades; si no, reconstruye y vuelve a adjuntar datos. Verifica con cheques de integridad de paquetes (rpm -Va en sistemas RPM) si están disponibles.
4) «Pods de Kubernetes siguen reiniciando tras una limpieza»
Síntoma: Pods en crashloop; nodos parecen bien; errores de app incluyen archivos faltantes en rutas montadas.
Causa raíz: La limpieza apuntó a una ruta de PersistentVolume montada, no a la capa del contenedor.
Solución: Para el job/pod que está borrando. Restaura el PVC desde snapshot/backup del almacenamiento. Añade controls de admisión y runAsNonRoot; elimina hostPath mounts salvo que sean absolutamente necesarios.
5) «La automatización borró el directorio equivocado en muchos hosts»
Síntoma: Muchos hosts se degradan simultáneamente; faltan las mismas rutas.
Causa raíz: Gestión de configuración o job CI ejecutó una tarea destructiva con una mala expansión de variable o inventario mal apuntado.
Solución: Congela el pipeline. Revierte el cambio. Añade condiciones de guardia: requiere allowlist explícita de rutas, rechaza variables vacías y ejecuta tareas destructivas solo con aprobación manual + dry run.
6) «El script de limpieza funcionó meses y luego lo arruinó»
Síntoma: Script antiguo de larga data de repente se vuelve destructivo.
Causa raíz: El entorno cambió: targets de symlink, puntos de montaje, nuevos bind mounts, cambios en la imagen base del contenedor o la ruta ahora apunta a otro filesystem.
Solución: Haz que los scripts validen invariantes: asegura que la ruta esté en el filesystem esperado (findmnt), que coincida con un patrón exacto, que no sea / ni esté vacía y que no sea un symlink salvo que esté permitido explícitamente.
7) «Restauramos desde backup pero la app está inconsistente»
Síntoma: La app arranca pero los datos están corruptos o faltan escrituras recientes.
Causa raíz: Restauraste un backup a nivel de sistema de archivos sin consistencia a nivel de aplicación; WAL/transacciones no alineadas.
Solución: Usa backups consistentes con la app (herramientas nativas de base de datos) o detén/quiesce antes del snapshot. Tras restaurar, corre chequeos de integridad y reconcilia con logs/replicas.
Listas de verificación / plan paso a paso
Lista preventiva: haz que «rm -rf /» sea una historia que cuenten otros equipos
- Snapshots en todo lo que importe. Si no puedes snapshotearlo, necesitas backup con restores probados. Prefiere ambos.
- Menor privilegio por defecto. Elimina sudo amplio; usa escalada just-in-time con trazas de auditoría.
- Haz que las rutas peligrosas sean difíciles de tocar. Montajes separados para datos; considera root de solo lectura para appliances; usa flags inmutables donde aplique.
- Guardrails en scripts: exige variables no vacías (
${VAR:?}), niega/, evita sorpresas por globbing, resuelve symlinks deliberadamente. - Cultura de dry-run: usa
findpara imprimir candidatos antes de borrar; guarda la salida en notas de incidente. - Observabilidad para churn de archivos: alerta sobre tasas inusuales de borrado en datasets críticos, no solo CPU/mem.
- Haz simulacros de restauración. La primera vez que restaures no debería ser durante un outage.
Lista operativa: borrado seguro bajo presión
- Prueba la ruta. Usa
readlink -fyfindmntpara confirmar límites de montaje y symlinks. - Lista, no borres. Empieza con: «¿qué exactamente se eliminará?»
- Prefiere mover a cuarentena. Renombra un directorio a una ruta de cuarentena primero cuando sea posible, luego borra más tarde.
- Limita y observa. Si el borrado es grande, puede provocar un outage por IO. Considera dividir en lotes fuera de pico.
- Detén servicios antes de borrar datos con estado. Especialmente bases de datos y colas.
- Tener una vía de rollback. Haz snapshot antes de borrar si el filesystem lo soporta; si no, respalda el directorio objetivo.
Lista de incidentes: sospecha de borrado accidental
- Congela la automatización (CI/CD, Ansible, jobs cron de limpieza).
- Captura evidencia: montajes actuales, procesos en ejecución, estadísticas de disco/inodos, últimos comandos si están disponibles.
- Evalúa el alcance: solo SO vs montaje de datos; contenedor vs host; nodo aislado vs flota.
- Elige estrategia de recuperación: rebuild+reattach, restore desde snapshot, reinstalación de paquetes o herramientas de recuperación de archivos.
- Valida: salud del servicio, cheques de integridad de datos y verificación de dependencias.
- Postmortem: arregla la salvaguarda, no a la persona.
Preguntas frecuentes
1) ¿Sigue funcionando rm -rf / en Linux moderno?
A menudo no, porque GNU rm típicamente tiene por defecto --preserve-root. Pero no te relajes: la gente puede pasar
--no-preserve-root, usar otras herramientas (find -delete, rsync --delete) o borrar montajes críticos bajo / sin apuntar al raíz mismo.
2) ¿Por qué algunos sistemas siguen funcionando tras borrados importantes?
Porque los procesos en ejecución ya cargaron código y tienen descriptores de archivo abiertos. Pueden seguir hasta que necesiten ejecutar un nuevo binario,
cargar una biblioteca compartida, rotar logs o reiniciarse.
3) ¿Es seguro borrar dentro de un contenedor?
Es más seguro solo si borras la capa del contenedor y no volúmenes montados. La parte peligrosa suele ser el volumen que contiene datos reales.
Si tu contenedor ve rutas del host o montajes privilegiados, «contenedor» deja de ser una frontera significativa.
4) ¿Cuál es la alternativa más segura a rm -rf para limpieza?
Cuando puedas: renombra/mueve a un directorio de cuarentena primero y borra después. Cuando debas borrar: usa find con restricciones explícitas
(límite de filesystem, profundidad, antigüedad, propiedad) y registra lo que borras. Y haz snapshot antes si el filesystem lo permite.
5) ¿Puedo recuperar archivos borrados en ext4/xfs?
A veces, pero no lo des por hecho. La recuperación depende de si los bloques fueron sobrescritos, si TRIM corrió en SSDs y qué tan rápido dejaste de escribir.
Snapshots y backups son la vía confiable; la recuperación forense es el último recurso.
6) ¿Por qué rm -rf a veces es tan lento?
Borrar muchos archivos pequeños es intensivo en metadata: recorrido de directorios, actualizaciones de inodos, escrituras de journal. En almacenamiento de red puede ser peor.
Además, la eliminación puede saturar IO y bloquear otras cargas de trabajo. La «limpieza» puede convertirse en el outage.
7) ¿Deberíamos aliasar rm a rm -i globalmente?
Bien para shells interactivas, mayormente inútil para automatización. También entrena a la gente a teclear «y» mil veces sin pensar.
Mejor: aplica menor privilegio, añade allowlists de rutas y confía en snapshots/backups para seguridad real.
8) ¿Cuál es la mejor defensa contra comandos destructivos a nivel de flota?
Defensa en profundidad: aprobaciones para automatización destructiva, alcance de entorno, infraestructura inmutable con flujos de trabajo de reconstrucción
y snapshots a nivel de almacenamiento. Además: staging que sea realmente representativo, para que los scripts fallen ruidosamente antes de llegar a producción.
9) ¿Qué pasa si hoy no tenemos snapshots?
Entonces tu primer paso no es una herramienta nueva; es una política. Decide qué datos deben ser recuperables, define RPO/RTO, implementa backups
y realiza simulacros de restauración. Los snapshots son poderosos, pero solo si existen procedimientos de retención y restauración.
10) ¿Cómo detengo un borrado desbocado de forma segura?
Si el objetivo es incorrecto, páralo rápido: mata el proceso, desmonta el filesystem afectado si es posible o aísla el host.
Luego haz snapshot del dataset dañado (si es soportado) antes de intentar reparaciones para no perder el estado forense.
Conclusión: siguientes pasos que puedes hacer esta semana
«rm -rf /» es famoso porque es simple, irreversible y siempre espera tu peor día. Pero las historias no tratan realmente de un comando.
Tratan de frenos faltantes: sin snapshots, privilegios descuidados, scripts que aceptan variables vacías y runbooks que asumen que el layout del filesystem es estático.
Pasos prácticos:
- Inventaria datasets críticos y ponlos en almacenamiento con snapshots (o hazles backup con restores verificados).
- Audita scripts de limpieza por peligros de variables vacías y sorpresas de symlink/montaje; añade allowlists y paradas rígidas.
- Realiza un simulacro de restauración este mes. Cronométralo. Escribe el runbook a partir de lo que realmente pasó.
- Reduce privilegios permanentes y exige aprobaciones explícitas para automatización destructiva a escala.
- Actualiza tu runbook on-call de «disco lleno» para que empiece con diagnóstico, no con borrado.
Si haces eso, no solo evitarás un incidente definitorio de género. También harás el trabajo diario más tranquilo—menos pánico, menos sorpresas
y menos mitos de «funcionó la última vez» que se tratan como ingeniería.