Usando un chroot para arreglar un sistema que no arranca

recoveryMe acaba de pasar que haciendo un dist-upgrade en el portátil de repente se ha quedado la pantalla en negro, y por alguna razón ni siquiera me dejaba hacer login desde una consola (tty1).

Encima conectando por ssh cualquier cosa que hiciese me daba una violación de segmento, y ya en el intento a la desesperada de reiniciar ni siquiera llegaba a arrancar.

En este momento lo primero que se te pasa por la cabeza es “ME CAGO EN LA P***!!!!!” y ya te ves haciendo backup desde un LiveCD y reinstalando todo.

Pero espera! Aun queda una última esperanza: chroot.

¿Qué es el chroot? Es una utilidad que te permite montar la ruta que le indiques dentro de un “jail”, haciendo que cualquier cosa que se ejecute dentro de esa jaula crea que el contenido del jail es la raíz del sistema.

O sea, pongamos que tienes un linux instalado en tu disco duro y arrancas el ordenador desde un LiveCD. Abres una consola y le dices que haga un chroot con la ruta del linux instalado en el disco duro, y desde ese momento en esa consola estarás trabajando como si tuvieses arrancado ese Linux desde el disco duro.

Esto incluye concretamente (que es lo que nos interesa para este caso) que al hacer un apt-get los paquetes no se instalen en tu LiveCD si no en el Linux del PC.

Paso 1: Arranca desde un LiveCD e identifica las particiones

Una vez arrancamos el ordenador desde un LiveCD (o LiveUSB) abrimos el nautilus y veremos discos disponibles para montar. Hacemos click en ellos para montarlos y ver su contenido.

Abrimos una consola y ejecutamos un mount, que nos mostrará los nombres de los discos y dónde están montados.

Con lo que necesitamos quedarnos de esto es:

  • El punto de montaje de la unidad root (desde nautilus veremos que contiene los directorios /root, /home, /etc…). El nombre de este punto de montaje será algo del estilo de “/media/jfqlk342-asldkj23-43kjasdf”.
  • El nombre del disco (por ejemplo /dev/sda1) de la partición de boot, que es la que contendrá archivos con nombres del estilo de “vmlinuz-3.11.0-15-generic“.

Paso 2: Creando el chroot

Como el Linux de nuestro disco duro no está arrancado no tendrá nada en los directorios /dev, /proc y /sys, ya que su contenido se genera durante el arranque. Usaremos los mismos directorios de nuestro sistema arrancado desde el LiveCD.

Todo esto a partir de aquí deberemos hacerlo como root. Donde pone “/mount/point” lo reemplazamos por el punto de montaje de la unidad de root que identificamos en el paso 1.

mount -o bind /proc /mount/point/proc
mount -o bind /dev /mount/point/dev
mount -o bind /dev/pts /mount/point/dev/pts
mount -o bind /sys /mount/point/sys

En caso de que se vaya a actualizar también el kernel (como era el caso en el dist-upgrade que estaba haciendo yo) necesitamos montar también la partición boot. Reemplazamos /dev/sda1 por el nombre de unidad que hemos identificado para la partición boot en el paso 1 anterior, e igual que antes reemplazamos /mount/point por el punto de montaje de la partición root:

mount /dev/sda1 /mount/point/boot

Como queremos tener acceso a internet desde nuestro chroot necesitamos copiar el archivo /etc/resolv.conf, de forma que tengamos acceso a los DNS:

cp /etc/resolv.conf /mount/point/etc/resolv.conf

Ya tenemos todo listo, podemos proceder a crear el chroot:

chroot /mount/point /bin/bash

Ahora estamos dentro de la instalación de nuestro disco duro, como si estuviese arrancada.

Paso 3: Recuperando el sistema

Si se nos quedó el dist-upgrade a medias lo más seguro es que tengamos paquetes pendientes mal configurados, así que resolvemos eso antes que nada:

apt-get install -f

Es posible que al ejecutar eso (debido a que la instalación quedó a medias) nos de error de sobreescritura de archivos. Le decimos que adelante, que sobreescriba lo que necesite:

apt-get install -f -o Dpkg::Options::="--force-overwrite"

Esperamos a que complete la instalación, y ya podemos salir del chroot con un exit y reiniciar el equipo. Si todo ha ido bien nuestro ordenador arrancará correctamente como si nada hubiese pasado.