#!/bin/bash # # Fichier image # # Vérification des arguments if [ -z "$1" ] then echo echo -e "\033[38;2;255;0;0;1m[ERREUR] Indiquer le fichier image à redimentionner\e[0m" echo exit 1 fi imageFile=$1 # # Demande de confirmation # echo -e "\033[38;2;255;0;0;1mATTENTION! ce script est fait pour redimentionner les images de cartes SD de Raspberry Pi utilisant Raspberry Pi OS. L'utilisation de ce script pour un autre utilisation risque de produire des résultats inattendus.\e[0m" echo -e "\033[38;2;255;0;0;1mPour plus de détails et l'explication du script, voir ici: https://www.jesus-forain.fr/blog/reduire-la-taille-d-une-image-de-carte-sd-d-un-raspberry-pi-136.html\e[0m" echo echo -e "\033[38;2;255;0;0;1mLe fichier image donné en argument sera modifié, il est conseillé de faire une copie de sauvegarde de ce fichier image\e[0m" echo echo -e "Fichier à réduire: \033[38;2;0;255;255;1m$imageFile\e[0m" echo -n "Confirmer (O/N)? " read confirm confirm=$(echo $confirm | tr '[:upper:]' '[:lower:]') if [ $confirm != o ]; then exit 0 fi # # Recherche d'un périphérique loop libre # echo -e "\033[38;2;0;255;255;1m[INFO] Recherche d'un périphérique /dev/loopX libre\e[0m" loopNb=0 nbLoopDevices=$(ls -l /dev | grep -e "loop[0-9]\+" | wc -l) echo -e "$nbLoopDevices périphériques /dev/loopX disponibles" losetup | grep /dev/loop$loopNb > /dev/null while (( $? == 0 )); do echo "/dev/loop$loopNb est utilisé" loopNb=$(($loopNb + 1)) # Plus de loopX disponible if (($loopNb >= $nbLoopDevices)); then echo -e "\033[38;2;255;0;0;1m[ERREUR] aucun périphérique /dev/loopX libre\e[0m" exit 1 fi losetup | grep /dev/loop$loopNb > /dev/null done echo -e "\033[38;2;0;255;255;1m[INFO] /dev/loop$loopNb est libre\e[0m" # # Montage de l'image # echo -e "\033[38;2;0;255;255;1m[INFO] Montage de l'image\e[0m" losetup /dev/loop$loopNb $imageFile if (( $? != 0 )); then echo -e "\033[38;2;255;0;0;1m[ERREUR] échec du montage de l'image\e[0m" exit 1 fi # # Rechargement de la table des partitions # echo -e "\033[38;2;0;255;255;1m[INFO] Rechargement de la table des partitions\e[0m" partprobe /dev/loop$loopNb if (( $? != 0 )); then echo -e "\033[38;2;255;0;0;1m[ERREUR] échec du rechargement de la table des partitione\e[0m" exit 1 fi # Affichage de la structure des partitions echo -e "\033[38;2;0;255;255;1m[INFO] affichage de la structure des partitions\e[0m" lsblk /dev/loop$loopNb # # Vérification du filesystem # echo -e "\033[38;2;0;255;255;1m[INFO] Vérification du filesystem\e[0m" e2fsck -y -f /dev/loop${loopNb}p2 # Pas de vérifications du code retour car s'il y a des corrections la valeur est "faux" # # Redimensionnement du filesystem # echo -e "\033[38;2;0;255;255;1m[INFO] Redimensionnement du filesystem. Cette étape est la plus longue du script et peut durer plusieurs dizaines de minutes selon la taille du fichier image\e[0m" resize2fs -p /dev/loop${loopNb}p2 -M if (( $? != 0 )); then echo -e "\033[38;2;255;0;0;1m[ERREUR] échec du redimensionnement du filesystem\e[0m" exit 1 fi # Récupération d'informations sur les partitions blockCount=$(dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "Block count" | awk '{print $3}') blockSize=$(dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "Block size" | awk '{print $3}') sectorsSize=$(fdisk -l $imageFile | grep Units | awk '{print $8}') partitionStart=$(fdisk -l /dev/loop$loopNb | grep -e "/dev/loop${loopNb}p2.*Linux" | awk '{print $2}') partitionEnd=$((($blockCount * $blockSize) / $sectorsSize + 1)) echo -e "\033[38;2;0;255;255;1m[INFO] Informations sur les partitions\e[0m" echo "nombre de blocs : $blockCount" echo "taille de bloc : $blockSize octets" echo "taille de secteur : $sectorsSize octets" echo "début de partition: $partitionStart" echo "fin de partition : ($blockCount * $blockSize) / $sectorsSize + 1) = $partitionEnd" # # Modification des partitions # echo -e "\033[38;2;0;255;255;1m[INFO] Modification des partitions\e[0m" # Script fdisk trouvé ici: # https://superuser.com/questions/332252/how-to-create-and-format-a-partition-using-a-bash-script sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | fdisk /dev/loop$loopNb p # afficher la table des partitions d # menu supprimer la partition 2 # supprimer la partition N°2 n # menu nouvelle partition p # type de partition (primaire) 2 # appliquer à la partition N°2 $partitionStart # début de la partition +$partitionEnd # fin de la partition. Attention, il y a un '+' devant la taille # Do you want to remove the signature? [Y]es/[N]o: => non par défaut p # affichage du nouveau partitionnement w # écriture des modifications sur les partitions q # Quitter EOF # Pas de vérification de la valeur de retour car ça sera toujours faux à cause du message "Re-reading the partition table failed.: Argument invalide" # Récupération d'infos sur la nouvelle partition newPartitionEnd=$(fdisk -l /dev/loop$loopNb | grep -e "/dev/loop${loopNb}p2.*Linux" | awk '{print $3}') newFileSize=$((($newPartitionEnd + 1) * $sectorsSize)) # # Redimentionnement du fichier image # # Détacher la disque virtuel /dev/loopX echo -e "\033[38;2;0;255;255;1m[INFO] Détacher la disque virtuel /dev/loop$loopNb\e[0m" losetup -d /dev/loop$loopNb if (( $? != 0 )); then echo -e "\033[38;2;255;0;0;1m[ERREUR] échec du détachement du périphérique /dev/loop$loopNb\e[0m" exit 1 fi # Réduction du fichier image echo -e "\033[38;2;0;255;255;1m[INFO] Réduction du fichier image à $newFileSize octets\e[0m" truncate -s $newFileSize $imageFile if (( $? != 0 )); then echo -e "\033[38;2;255;0;0;1m[ERREUR] échec de la réduction du fichier image\e[0m" exit 1 fi echo echo -e "\033[38;2;0;255;0;1mTERMINÉ\e[0m" echo