Caveat : Il va sans dire que tout ce qui suit est très dangereux et peut mener à effacer les anciennes données en cas d’erreur. Si vous utilisez ceci sans le comprendre, ne vous plaignez pas de la catastrophe qui s’ensuivra. Mais vos sauvegardes sont à jour, n’est-ce pas ?

Configuration

J’aime les configurations simples sur ma machine de travail : une partition unique (/dev/sda1) avec une partition de swap séparée (/dev/sda5).

Sur le nouveau disque que j’ai acheté (1 To), et qui doit remplacer complètement l’ancien, je veux une partition /dev/sdb1 de 995 Go et le reste de swap (/dev/sdb2). L’ancien disque est destiné à terme à quitter la machine (le /dev/sdb deviendra donc /dev/sda, histoire d’augmenter les chances de confusion).

Les deux disques sont en SATA, j’ai juste branché le nouveau disque dans la machine avec le câble électrique et le câble SATA.

Les configurations plus complexes sont laissées en exercice au lecteur (sachant que le plus problématique est toujours la partition racine du système, les autres se manipulant en général sans problème).

Préalable

D’abord une sauvegarde des fichiers importants (ceci est aussi laissé en exercice au lecteur).

Pour éviter certains des problèmes que j’ai rencontré, j’aurais tendance à conseiller de désinstaller provisoirement le paquet qui s’occupe des mises en veille (il a eu du mal à gérer le changement de la partition de swap qu’il utilise) :

aptitude remove uswspd

Ceux qui ont de la place disque par ailleurs peuvent carrément faire une image complète plus ou moins compressée de leur partition système (par exemple avec partimage). Je fais sans pour le moment.

Lancement

Si la système de la machine ne faisait pas partie de ce qu’il fallait migrer, on aurait pu tout faire depuis le système par défaut (quitte à booter en mode single) mais là le plus simple est encore de booter avec un Knoppix ou en l’occurence un LiveCD Ubuntu. On a tout le confort de l’interface graphique avec les copier-coller entre plusieurs terminaux ou éditeurs.

Config ancienne

Quand le LiveCD a démarré, il offre un système fonctionnel tournant uniquement sur le DVD, et il n’a pas monté les disques durs (un autre LiveCD aurait pu se comporter différemment).

Vu que tout ce que l’on va faire nécessite des droits étendus, autant se loguer comme dieu omnipotent tout de suite :

sudo su

On vérifie ce qu’il y a sur l’ancien disque que le système déjà présent connaît comme /dev/sda. Pour voir et modifier le partitionnement des disques j’utilise parted en ligne de commande (mais en mode graphique il existe gparted) :

root@ubuntu:~# parted /dev/sda p

Disk /dev/sda: 300GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 32,3kB 294GB 294GB primary ext3 boot
2 294GB 300GB 6218MB extended
5 294GB 300GB 6218MB logical linux-swap

Nouveau disque

On crée les partitions du nouveau disque (connu comme /dev/sdb) avec parted.

Attention de ne pas se tromper entre /dev/sda et /dev/sdb sinon on repartitionne l’ancien disque !

parted /dev/sdb

Pour vérifier qu’il n’y rien (si le disque est neuf) :

print

Pour créer la nouvelle partition :

mkpartfs 1

Demander une partition de type primary, le système par défaut ext2, de début 0GB et de fin 995GB (toujours préciser les unités pour lever les ambiguïtés).

Pour que le système puisse démarrer dessus, mettre le flag d’amorçage :

set 1 boot on

print

Number Start End Size Type File system Flags
1 32,3kB 995GB 995GB primary ext2 boot

De la même manière, on crée une partition 2 qui prend la fin du disque :

(parted) mkpart
Partition type? primary/extended? primary
File system type? [ext2]?
Start? 995GB
End? 1001GB
(parted) p

Disk /dev/sdb: 1000GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 32,3kB 995GB 995GB primary ext3 boot
2 995GB 1000GB 5198MB primary linux-swap

quit

Plus tard, on utilisera dd, donc inutile de formater la première partition. Par contre sur la deuxième on prépare le swap :

mkswap /dev/sdb2

Copie du système

La commande suivante est hautement dangereuse. Elle copie bloc par bloc le contenu de la partition sda1 sur sdb1 (if signifie input file et of output file). Une erreur et on écrase la partition à copier par la vide ! Si quelqu’un connaît un moyen de poser une protection en écriture qui bloque dd, je suis preneur.

La durée dépend du volume, ça prend facilement des heures avec des disques récents (moyenne de 50 Mo/s dans mon cas, soit 6000 s pour 300 Go) :

dd if=/dev/sda1 of=/dev/sdb1 conv=noerror,sync bs=64M

À présent sdb1 contient un clonage de la partition racine sda1. Comme je suis parano, je vérifie qu’elle se porte bien (y a pas de raison mais Murphy veille) :

e2fsck -f /dev/sdb1

Si tout va bien, on peut à présent monter la nouvelle partition dans le système de fichier de notre LiveCD. Je monte aussi l’ancienne (ici en lecture seule avec ro), pour y récupérer ou regarder des choses si je me mélange les pinceaux dans mes modifs, on pourrait s’en passer.
Les répertoires de montage sont /mnt/nouveau et /mnt/ancien, c’est selon l’humeur.

mkdir /mnt/ancien
mkdir /mnt/nouveau
mount -o ro /dev/sda1 /mnt/ancien/
mount /dev/sdb1 /mnt/nouveau/

Et puis je regarde la place disponible. Dans tout le fatras de pseudo-systèmes de fichier temporaires, virtuels, système... qu’a créé le LiveCD, seuls sont intéressants les vrais systèmes de fichiers dans /dev/sd*

root@ubuntu:~# df -h
Filesystem Size Used Avail Use% Mounted on
...
/dev/sda1 270G 237G 19G 93% /mnt/ancien
/dev/sdb1 270G 237G 19G 93% /mnt/nouveau

Retaillage

Là on s’aperçoit avec horreur ou satisfaction que le nouveau système de fichiers fait exactement la même taille (270 Go) que l’ancien. Évidemment, c’en est un clonage direct ! L’étape suivante consiste à redimensionner ce nouveau système de fichiers à la taille de sa partition (995 Go).

D’abord on la démonte :

umount /mnt/nouveau

J’ignore si c’est vraiment critique, mais un tutoriel que j’ai trouvé conseille de supprimer préalablement le journal de la partition ext3 (la transformant en simple ext2). Ça ne mange pas de pain.

tune2fs -O ^has_journal /dev/sdb1

resize réclamera de toute façon qu’un scandisk soit effectué :

e2fsck -f /dev/sdb1

Et on lance le retaillage :

root@ubuntu:~# resize2fs -p /dev/sdb1
resize2fs 1.40.2 (12-Jul-2007)
Resizing the filesystem on /dev/sdb1 to 242920865 (4k) blocks.
Begin pass 1 (max = 5224)
Extending the inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 2 (max = 433)
Relocating blocks XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 2190)
Scanning inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 5 (max = 16)
Moving inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/sdb1 is now 242920865 blocks long.

Et je remets le journal en place pour retrouver un ext3 journalisé :

tune2fs -j /dev/sdb1

L’UUID

Pour les détails sur le concept d’UUID, voir sur doc.ubuntu.org. Sommairement pour les novices ou ceux comme moi qui ont démarré Linux au XXè siècle, l’UUID est un identifiant propre à une partition. On peut ainsi fixer des points de montage fixes en fonction de cet UUID en le précisant dans /etc/fstab à la place des habitues /dev/... qui ont la fâcheuse habitude de changer suivant l’ordre de détection des disques.

Pour détecter les UUID de chaque partition, la commande est :

blkid

Et là, nouvelle horreur, la nouvelle partition possède un identifiant identique à l’ancienne !

En fait, ce n’est gênant que si on veut conserver au moins un temps l’ancien disque dans la machine. Si l’ancien disque part se faire reformater ailleurs, il n’y a plus de problème.

Dans mon cas, je conserve les deux disques et j’ai besoin de donner un nouvel identifiant (arbitraire) à la nouvelle partition :

tune2fs -U random /dev/sdb1

On cherche le nouvel identifiant qui servira par la suite :

root@ubuntu:~# blkid
/dev/sda1: UUID="4955dbe1-6f16-4616-b4a7-7bee7644a88c" SEC_TYPE="ext2" TYPE="ext3"
/dev/sda5: TYPE="swap" UUID="29492826-d014-460e-8bdc-61c915f0c032"
/dev/sdb1: UUID="72825599-4ed6-454a-95be-be609ffb1492" SEC_TYPE="ext2" TYPE="ext3"
/dev/sdb2: TYPE="swap" UUID="577c575d-63e7-4919-a4c1-43e3c8e10326"

Et enfin on remonte le nouveau système :

mount /dev/sdb1 /mnt/nouveau/

Et un df -h renvoie entre autres :

/dev/sdb1 913G 237G 639G 28% /mnt/nouveau

Joie ! Le nouveau système utilise bien son (presque) téra, et a conservé les 237 Go copiés de l’ancien système.

Modification du /etc/fstab

Si on bootait tout de suite sur le nouveau système, il aurait du mal à trouver tout seul son nouvel environnement. Le plus important est le /etc/fstab.

Les Ubuntu récents utilisent à présent systématiquement les UUID comme identifiants des disques. C’est moins lisible que les mentions comme /dev/sda1 mais à l’heure du SATA et des disques externes branchés dans l’ordre que l’on veut, c’est beaucoup plus sûr.

Le fichier /etc/fstab du nouveau système est monté chez nous comme /mnt/nouveau/etc/fstab, et dedans l’ancienne ligne

UUID=4955dbe1-6f16-4616-b4a7-7bee7644a88c / ext3 nouser,defaults,errors=remount-ro,noatime,auto,rw,dev,exec,suid,user_xattr 0 1

doit être commentée (ou conservée en indiquant un autre point de montage comme /mnt/ancien_disque) et remplacée par :

UUID=72825599-4ed6-454a-95be-be609ffb1492 / ext3 nouser,defaults,errors=remount-ro,noatime,auto,rw,dev,exec,suid,user_xattr 0 1

De même, il faut modifier l’identifiant de l’ancien swap et le remplacer par le nouveau.
Au passage, on fera de même dans le fichier /mnt/nouveau/etc/initramfs-tools/conf.d/resume qui doit contenir l’UUID du nouveau swap :

RESUME=UUID=577c575d-63e7-4919-a4c1-43e3c8e10326

Séquence de boot

Il reste encore à adapter le boot loader, grub de nos jours, auquel je ne comprends pas toujours grand chose. Je serais bien resté à lilo si ce dernier avait réussi à s’adapter au XXIè siècle.

À ce stade, j’ai préféré carrément éteindre et ouvrir la machine, et débrancher l’ancien disque. J’ai mis le nouveau à la place de l’ancien pour me retrouver avec un disque principal « en premier » dans les listes (/dev/sda ou (hd0). Et l’ancien disque étant hors-circuit, il reste récupérable et bootable même en cas de pépin. Enfin, je ne risque pas de booter dessus par inadvertance en me croyant sur le nouveau système ! Oui, je suis un étourdi et j’en tiens compte.

Je redémarre sur le LiveCD et je remonte mon nouveau système en vérifiant qu’il est bien devenu /dev/sda dans la nouvelle configuration des disques :

blkid
/dev/sda1: UUID="72825599-4ed6-454a-95be-be609ffb1492" SEC_TYPE="ext2" TYPE="ext3"
/dev/sda2: TYPE="swap" UUID="577c575d-63e7-4919-a4c1-43e3c8e10326"

mkdir /mnt/nouveau
mount /dev/sda1 /mnt/nouveau

Pour mettre à jour grub il est nécessaire que celui-ci se croie dans la configuration réelle future. chroot permet de faire croire aux commandes postérieures que /mnt/nouveau est leur racine ( / ).

Sans les deux premiers mount il serait impossible à grub d’accéder aux disques depuis l’environnement « chrooté » :

mount -t proc none /mnt/nouveau/proc
mount -o bind /dev /mnt/nouveau/dev

chroot /mnt/nouveau/

Le fichier intéressant est /boot/grub/menu.lst. Il faut encore échanger l’UUID sur la ligne contenant « kopt ». Il est inutile de le faire dans les autres lignes, ce serait écrasé par update-grub plus tard.

# kopt=root=UUID=72825599-4ed6-454a-95be-be609ffb1492 ro

NB : En cas de configuration plus complexe, il faudra aussi faire attention au disque de boot indiqué à grub : (hd0) ? (hd1) ?

update-grub est une commande Debian qui régénère le vrai menu grub :

update-grub
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-2.6.24-21-386
Found kernel: /boot/vmlinuz-2.6.24-21-generic
Found kernel: /boot/vmlinuz-2.6.24-19-generic
Found kernel: /boot/memtest86+.bin
Updating /boot/grub/menu.lst ... done

Et ensuite avec cat /boot/grub/menu.lst on vérifie que les entrées de menu par défaut connaissent bien le nouvel UUID.

Alea jacta est

Et on reboote en croisant les doigts.

Il m’est arrivé que certains disques encore dans /etc/fstab mais déconnectés (typiquement : l’ancien disque) soient introuvables et bloquent le boot. Si la machine semble bloquée au boot, un Alt-F1 permet d’accéder à la console et de poursuivre le boot par Entrée ou Ctrl-D.

Retour de l’hibernation

Si tout va bien dans le nouveau système, on finalise en remettant en place le paquet enlevé :

aptitude install uswsusp

Vérifier que dans /etc/uswsusp.conf il indique bien la nouvelle partition de swap (/dev/sda2 chez moi) comme partition de sauvegarde de la mémoire.

Pour l’hibernation, dont j’ai déjà parlé ici, toujours dans /mnt/nouveau/etc/ il faut modifier uswsusp.conf, ligne resume device.

Vérification que le nouveau disque n’est pas une bouse

En fait il aurait fallu faire ceci bien avant. Je me suis déjà fait brûler par des disques qui avaient mal supporté le voyage dans un mauvais conditionnement. Donc je l’ai utilisé massivement quelques jours en le remplissant de copies de sauvegardes et autres fichiers non critiques. Smartmontools devrait déjà être installé mais sait-on jamais :

aptitude install smartmontools

Il n’y a pas d’interface graphique, il faut se taper la ligne de commande alors que la vérification des disques devrait faire partie de la maintenance habituelle accessible aux débutants. Bref :

On lance un test rapide :

smartctl -t short /dev/sda

=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Short self-test routine immediately in off-line mode".
Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 2 minutes for test to complete.
Test will complete after Sun Aug 31 11:54:15 2008

Use smartctl -X to abort test.

Deux minutes après on peut lire le résultat sous forme allégée

smartctl -H /dev/sdb
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

Ou cryptiquement complète (fouiller sur Google pour les détails) :

smartctl --all /dev/sdb

(blabla...)
# 1 Short offline Completed without error 00% 51 -