Réduire en automatique la taille d'une image disque de carte SD de Raspberry Pi
- Jacques Tenneguin
- 14 mars
- 5 min de lecture
Dernière mise à jour : 2 avr.
Réduire en automatique la taille d'une image disque de carte SD de Raspberry Pi grâce à un script bash (_shrink_sd_card.sh)
Pour ce faire, vous devez, dans un premier temps, réaliser une copie de votre carte SD de Raspberry Pi sur votre disque PC. Reportez vous au blog sur la création d’une image disque de Raspberry Pi.
Puis lorsque votre image de Raspberry Pi est placée sur le disque de votre PC, lancez l’utilitaire écrit en Bourne Bash avec la commande suivante :
$ . ~/_shrink_sd_card.sh NomDeFichierImageACompresser
Le fichier script _shrink_sd_card.sh doit être placé sous la racine du système. Sinon placez le dans un répertoire et appelez le script en mettant ce nom de répertoire avant le nom du script comme :
$ . ~/Documents/_shrink_sd_card.sh NomDeFichierImageACompresser
si vous avez copié le script dans ~/Documents/
Voici les écrans affichés lors d’un déroulement standard :




Voici enfin le script qui a servit à l'affichage des écrans précédents :
#!/bin/bash
# _shrink_sd_card.sh
# Script Initial par Jésus Forain :
# https://www.jesus-forain.fr/blog/reduire-la-taille-d-une-image-de-carte-sd-d-un-raspberry-pi-136.html
# Modifications par Jacques Tenneguin
# https://axiomeinfo21.com
_fErr()
{
if [ "$LOOP" == "true" ]; then
sudo losetup -d /dev/loop$loopNb
fi
}
# Définition des paramètres en Français et Anglais
FR=0
GB=1
aUNITS=( "Unités" "Units" )
aBLOCKCOUNT=( "Nombre blocs" "Block count" )
aBLOCKSIZE=( "Taille bloc" "Block size" )
LOOP="false"
#
# Fichier image
#
# Vérification des arguments
if [ -z "$1" ]; then
echo
echo "[ERREUR] Indiquer en paramètre le fichier image à redimentionner"
echo
return 1
fi
imageFile="$1"
#
# Demande de confirmation
#
echo "ATTENTION! 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. Les structures issues de NOOBS_x_x_x.zip ne sont pas gérées par ce script."
echo "Pour 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 ou https://axiomeinfo21.com"
echo
echo "Le fichier image donné en argument sera modifié, il est conseillé de faire une copie de sauvegarde de ce fichier image"
echo
echo "Fichier à réduire: $imageFile"
read -p "Confirmer (O/N)? " confirm
if [ $confirm != "o" ] && [ $confirm != "O" ]; then
return 0
fi
echo
#
# Verification du nombre de partitions de l'image
#
declare -i _Nb=0; let _Nb=$( sudo fdisk -l "$imageFile" | grep -c "$imageFile" ); let _Nb--
if [ $_Nb -ne 2 ]; then
echo "[ERREUR] échec l'image ne contient pas 2 partitions"
return 2
fi
echo "[INFO] L'image contient bien 2 partitions seulement"
echo
#
# Recherche d'un périphérique loop libre
#
echo "[INFO] Recherche d'un périphérique /dev/loopX libre"
loopNb=0
nbLoopDevices=$(ls -l /dev | grep -e "loop[0-9]\+" | wc -l)
echo -e "$nbLoopDevices périphériques /dev/loopX disponibles"
sudo 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 "[ERREUR] aucun périphérique /dev/loopX libre"
return 3
fi
sudo losetup | grep /dev/loop$loopNb > /dev/null
done
LOOP="true"
echo "[INFO] /dev/loop$loopNb est libre"
echo
#
# Montage de l'image
#
echo "[INFO] Montage de l'image"
sudo losetup /dev/loop$loopNb "$imageFile"
if (( $? != 0 )); then
echo "[ERREUR] échec du montage de l'image"
_fErr; return 4
fi
echo
#
# Rechargement de la table des partitions
#
echo "[INFO] Rechargement de la table des partitions"
sudo partprobe /dev/loop$loopNb
if (( $? != 0 )); then
echo "[ERREUR] échec du rechargement de la table des partitions"
_fErr; return 5
fi
echo
# Affichage de la structure des partitions
echo "[INFO] affichage de la structure des partitions"
sudo lsblk /dev/loop$loopNb
echo
#
# Vérification du filesystem
#
echo "[INFO] Vérification du filesystem"
sudo 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"
echo
#
# Redimensionnement du filesystem
#
echo "[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"
sudo resize2fs -p /dev/loop${loopNb}p2 -M
if (( $? != 0 )); then
echo "[ERREUR] échec du redimensionnement du filesystem"
_fErr; return 6
fi
echo
# Récupération d'informations sur les partitions
echo "[INFO] Récupération d'informations sur les partitions"
blockCount=$(sudo dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "${aBLOCKCOUNT[$FR]}" | awk '{print $3}')
if [ "$blockCount" == "" ]; then
blockCount=$(sudo dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "${aBLOCKCOUNT[$GB]}" | awk '{print $3}')
fi
blockSize=$(sudo dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "${aBLOCKSIZE[$FR]}" | awk '{print $3}')
if [ "$blockSize" == "" ]; then
blockSize=$(sudo dumpe2fs -h /dev/loop${loopNb}p2 2>/dev/null | grep "${aBLOCKSIZE[$GB]}" | awk '{print $3}')
fi
sectorsUnits=$(sudo fdisk -l "$imageFile" | grep "${aUNITS[$FR]}" | awk '{print $4}')
if [ "$sectorsUnits" == "" ]; then
sectorsUnits=$(sudo fdisk -l "$imageFile" | grep "${aUNITS[$GB]}" | awk '{print $4}')
fi
sectorsBaseSize=$(sudo fdisk -l "$imageFile" | grep "${aUNITS[$FR]}" | awk '{print $6}')
if [ "$sectorsBaseSize" == "" ]; then
sectorsBaseSize=$(sudo fdisk -l "$imageFile" | grep "${aUNITS[$GB]}" | awk '{print $6}')
fi
sectorsSize=$(($sectorsUnits * $sectorsBaseSize))
partitionStart=$(sudo fdisk -l /dev/loop$loopNb | grep -e "/dev/loop${loopNb}p2.*Linux" | awk '{print $2}')
if [ "$partitionStart" == "" ]; then
# Au cas ou la 2me partition n'est de type linux
partitionStart=$(sudo fdisk -l /dev/loop$loopNb | grep -e "/dev/loop${loopNb}p2.*" | awk '{print $2}')
fi
partitionEnd=$((($blockCount * $blockSize) / $sectorsSize + 1))
echo
echo "[INFO] Informations sur les partitions"
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"
if [ "$blockCount" == "" ] || [ "$blockSize" == "" ] || [ "$sectorsUnits" == "" ] || \
[ "$sectorsBaseSize" == "" ] || [ "$sectorsSize" == "" ] || [ "$partitionStart" == "" ] || \
[ "$partitionEnd" == "" ]; then
echo "[ERREUR] Vérifiez les langues de sudo fdisk et sudo dumpe2fs : Anglais ou Français : UNITS, BLOCKCOUNT, BLOCKSIZE, ..."
_fErr; return 7
fi
echo
#
# Modification des partitions
#
echo "[INFO] Modification des partitions"
# Script sudo 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 | sudo 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=$(sudo fdisk -l /dev/loop$loopNb | grep -e "/dev/loop${loopNb}p2.*Linux" | awk '{print $3}')
newFileSize=$((($newPartitionEnd + 1) * $sectorsSize))
if [ "$newPartitionEnd" == "" ] || [ "$newFileSize" == "" ]; then
echo "[ERREUR] Vérifiez les partitions de sudo fdisk..."
_fErr; return 8
fi
echo
#
# Redimentionnement du fichier image
#
# Détacher la disque virtuel /dev/loopX
echo "[INFO] Détacher le disque virtuel /dev/loop$loopNb"
sudo losetup -d /dev/loop$loopNb
if (( $? != 0 )); then
echo "[ERREUR] échec du détachement du périphérique /dev/loop$loopNb"
_fErr; return 9
fi
echo
# Réduction du fichier image
echo "[INFO] Réduction du fichier image à $newFileSize octets"
sudo truncate -s $newFileSize "$imageFile"
if (( $? != 0 )); then
echo "[ERREUR] échec de la réduction du fichier image"
_fErr; return 10
fi
echo
echo "Ok : Réduction du fichier image terminée"
echo
Comments