Mise à jour : Debian 10.8 / Buster
Le changement de racine a pour objectif d'ouvrir et exploiter un shell sur un système de fichier dont la racine est différente de celle utilisée pour démarrer. Cette technique permet par exemple de prendre la main sur un système qui ne démarre plus (problème de boot) et de tenter de le réparer.
Le principe consiste, après avoir démarré sur un premier système (distribution installée ou distribution live), à monter la racine du système "à dépanner" sur ce premier système. Le changement de racine permet alors d'intervenir, depuis la console du premier système, sur le second système.
Dans ce qui suit, le premier système démarré est situé sur le disque /dev/sda, le système sur lequel on veut intervenir par un changement de racine est situé sur un disque externe /dev/sdb.
Démarrer le premier système et vérifier les partitions et leurs points de montage.
$ lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda1 ext4 debian8 a42b8919-e6a8-49e0-845e-6feb76b02297 /
├─sda2 swap swap e08131c8-298b-4368-81e4-502c3b83bef5 [SWAP]
└─sda3 ext4 home 78f7dc86-7d34-45aa-80c0-99538d77a3f7 /home
sdb
├─sdb1 ext4 debian8usb cf5a0c1d-9a16-4010-bb2a-29da4c8e23e6
├─sdb2 swap swapusb 332cd5f3-6008-4645-8668-5675a2b93497
└─sdb3 ext4 homeusb 1b6b8ae2-3f7e-4e2e-ad2d-09093726fc95
$ sudo mount /dev/sdb1 /mnt
$ sudo mount /dev/sdb3 /mnt/home
$ sudo mount --bind /proc /mnt/proc
$ sudo mount --bind /sys /mnt/sys
$ sudo mount --bind /sys/firmware/efi/efivars # Pour pouvoir utiliser efibootmgr
$ sudo mount --bind /dev /mnt/dev # Pour l'accès aux partitions externes, par exemple, pour la mise en place de grub sur la MBR
$ sudo mount --bind /dev/pts /mnt/dev/pts # Évite le message : E: Impossible d'écrire le journal (Est-ce que /dev/pts est monté ?) - posix_openpt (2: Aucun fichier ou dossier de ce type)
$ sudo mount --bind /run /mnt/run # Évite le message sudo: unable to resolve host xxxxxxx : Name or service not known
La commande peut être résumée en :
$ sudo -- bash -c 'for i in {proc,sys,sys/firmware/efi/efivars,dev,dev/pts,run};do mount --bind /$i /mnt/$i;done'
Le changement de racine s'effectue par la commande chroot /chemin_point_montage. Dans le cas présent :
$ sudo chroot /mnt
Désormais le shell est ouvert, en tant que super-utilisateur, à la racine du système chrooté /.
La commande devient :
$ sudo -- bash -c 'chroot --userspec nom_utilisateur:nom_utilisateur /mnt'
Les identifiants utilisateur (par exemple 1000:1000) peuvent également être utilisés.
Le shell s'ouvre en tant qu'utilisateur, à la racine du système chrooté /, ce qui pose un problème de droit et de cohérence.
bash: /root/.bashrc: Permission non accordée
Se déplacer dans un répertoire utilisateur, par exemple, en l'indiquant par son chemin complet (ne pas utiliser ~ qui désigne alors le home du super-utilisateur) :
$ cd /home/nom_utilisateur
# [[ "$(stat -c %d:%i /)" = "$(stat -c %d:%i /proc/1/root/.)" ]] && echo "We are standalone!" || echo "We are chroot!"
We are chroot!
Vérification du montage du système de fichier
# findmnt -o target,source,fstype
TARGET SOURCE FSTYPE
/ /dev/sdb2 ext4
├─/boot/efi /dev/sdb1 vfat
├─/proc proc proc
├─/sys sysfs sysfs
├─/dev udev devtmpfs
│ └─/dev/pts devpts devpts
└─/run tmpfs tmpfs
Pour distinguer plus facilement les environnements, créer dans l'environnement chrooté, un fichier /etc/debian_chroot contenant un texte spécifique. Celui-ci sera ajouté entre parenthèses au début du prompt :
# echo "ssd" >/etc/debian_chroot
L'ancien prompt, de la forme :
root@host:/Chemin
devient (après fermeture et réouverture du shell ou du chroot) :
(ssd)root@host:/chemin
Pour sortir du chroot, utiliser exit. Si l'on a lancé des sous-shells à l'intérieur du chroot, il faudra les fermer au préalable.
# exit
exit
$ sudo umount /mnt/run
$ sudo umount /mnt/dev/pts
$ sudo umount /mnt/dev
$ sudo umount /mnt/proc
$ sudo umount /mnt/home
$ cd ..
$ sudo umount /mnt
Équivalent à :
$ sudo -- sh -c 'for i in {run,dev/pts,dev,sys/firmware/efi/efivars,sys proc;do umount /mnt/$i; done'
$ sudo umount /mnt
Si le démontage échoue avec un message d'erreur indiquant qu'un système de fichier est occupé
Vérifier les systèmes de fichier encore montés (on a pu en monter certains plusieurs fois ...), si par exemple le système chrooté est monté en /mnt
$ findmnt |grep /mnt # Possibilité de spécifier le type de fichier -t ext4, etc...
On peut également utiliser cat /etc/mtab ou le résultat de mount etc....
Identifier les processus utilisant ces systèmes de fichier en tant qu'utilisateur et en tant que root avec lsof
$ lsof /mnt
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 12457 philippe cwd DIR 259,5 4096 2 /mnt
lsof 12999 philippe cwd DIR 259,5 4096 2 /mnt
lsof 13000 philippe cwd DIR 259,5 4096 2 /pnt
$ sudo fuser -k -i /mnt
/mnt: 3221rc 3315rc 3382rc 3599rc
Tuer le processus 3221 ? (y/N) y
Tuer le processus 3315 ? (y/N) y
Tuer le processus 3382 ? (y/N) y
Tuer le processus 3599 ? (y/N) y
Dans le cadre d'un chroot, il peut-être intéressant de partager un dossier entre le système d'origine et le système chrooté.
Une fois le montage du système /dev/sdb1 effectué :
Pour partager un dossier entre les deux environnements, par exemple ./partage_origine d'un coté, et /mnt/partage_chroot de l'autre
$ sudo mount --bind ./partage_origine /mnt/partage_chroot
Le contenu du dossier partage_origine apparaît dans partage_chroot. L
Les additions, suppressions effectuées depuis un environnement ou un autre sont reportées automatiquement dans l'autre
Le contenu initial du dossier partage_chroot n'apparaît pas
Pour ne plus partager le dossier :
$ sudo umount /mnt/partage_chroot
Le contenu du dossier partage_origine conserve les modifications (additions, suppressions, ...) effectuées pendant le partage
Le contenu original du dossier partage_chroot est restitué et ne prend pas en compte les modifications effectuées pendant le partage
Le système chrooté peut alors être démonté.