Уменьшение размера образа для Raspberry Pi

Часто так случается, что при копировании образа одной SD карты на другую, появляется ошибка о нехватке места. Вроде бы образ снят с карты размером 8Гб, и копируем на карту точно такого же размера, а места всё равно не хватает. В чем дело?

Причина такой неприятности кроется в том, что размер, указанный на любом электронном носителе, является лишь ориентировочным. Практически всегда носители разных производителей и даже разных моделей одной марки имеют отличающийся размер. Эти отличия могут не превышать нескольких мегабайт, или даже сотен килобайт, но для копирования образа это становится критичным.

Чтобы решить проблему нам нужно как-то укоротить исходный образ. Как правило, карта редко бывает забита под завязку, так что откусить лишние гигабайты образа будет вполне безобидным шагом. Этим мы и займемся.

1) Первое, что нам потребуется сделать — это создать свежий образ SD-карты. Размер образа будет идентичен размеру карты, с которой он снят. Чтобы этот образ куда-то сохранить, нам потребуется носитель большего размера. Например, если образ будет иметь размер 8Гб, для создания можно использовать обычную USB флешку на 16Гб или 32Гб.

2) Втыкаем флешку в USB порт и выясняем имя, выданное ей операционной системой. Делаем это с помощью утилиты fdisk:

sudo fdisk -l
rpi_find_dev

Судя по увиденному, флешка получила имя /dev/sda1 и на ней файловая система NTFS. Также мы видим, что основная SD карта разбита на два раздела: mmcblk0p1 и mmcblk0p2. Сделаем вывод, что сама карта называется /dev/mmcblk0, это нам пригодится.

3) Теперь монтируем флешку с помощью команды mount, предварительно создав для неё папку:

sudo mkdir /mnt/usbf
sudo mount /dev/sda1 /mnt/usbf

После выполнения этой команды в папке /mnt/usbf появится содержимое нашей флешки.

4) Создаем образ SD карты на флешке:

sudo dd bs=4M if=/dev/mmcblk0 of=/mnt/usbf/my_raspbian.img

В этой команде bs — размер блока. Чем он меньше, тем дольше будет длиться процесс создания. Обычно ставят 4M, а если что-то пойдет не так — можно попробовать bs=1M. Для образа размером 16Гб время процедуры может составить около часа.

5) После того, как образ будет создан, приступим к удалению из него пустого пространства. Для этой операции используем bash-скрипт от sirlagz, немного модифицированный для урезания из образа только 90% пустого пространства.

#!/bin/bash
# Automatic Image file resizer
# Written by SirLagz
strImgFile=$1

if [[ ! $(whoami) =~ “root” ]]; then
echo “”
echo “**********************************”
echo “*** This should be run as root ***”
echo “**********************************”
echo “”
exit
fi

if [[ -z $1 ]]; then
echo “Usage: ./autosizer.sh ”
exit
fi

if [[ ! -e $1 || ! $(file $1) =~ “x86” ]]; then
echo “Error : Not an image file, or file doesn’t exist”
exit
fi

partinfo=`parted -m $1 unit B print`
partnumber=`echo “$partinfo” | grep ext4 | awk -F: ‘ { print $1 } ‘`
partstart=`echo “$partinfo” | grep ext4 | awk -F: ‘ { print substr($2,0,length($2)-1) } ‘`
loopback=`losetup -f –show -o $partstart $1`
e2fsck -f $loopback
minsize=`resize2fs -P $loopback | awk -F’: ‘ ‘ { print $2 } ‘`

# Modified minsize calc by Kevin Rattai
#
# original minsize produces 0bytes on partition, calculated as:
# minsize=`echo “$minsize+1000” | bc`
#
# New minsize calc produces 10% minsize as available space
minsize=`echo “($minsize+($minsize*0.1))/1” | bc`

resize2fs -p $loopback $minsize
sleep 1
losetup -d $loopback
partnewsize=`echo “$minsize * 4096” | bc`
newpartend=`echo “$partstart + $partnewsize” | bc`
part1=`parted $1 rm 2`
part2=`parted $1 unit B mkpart primary $partstart $newpartend`
endresult=`parted -m $1 unit B print free | tail -1 | awk -F: ‘ { print substr($2,0,length($2)-1) } ‘`
truncate -s $endresult $1

Создаем в домашней папке пустой файл и делаем его исполянемым:

cd /home/pi
touch cut_img.sh
chmod 755 cut_img.sh

Затем открываем в любом редакторе, и копируем в него содержимое скрипта. Например в редакторе nano:

nano cut_img.sh

6) Чтобы скрипт заработал, нам понадобится доустановить пакет bc:

sudo apt-get install bc

Говорим yes на все вопросы, которые задаст установщик.

7) Ну всё, теперь мы готовы к процедуре. Запускаем скрипт, указав в качестве параметра ранее созданный образ:

sudo ./cut_img.sh /mnt/usbf/my_raspbian.img

Ждем окончания его работы.

Вот и все. После выполнения скрипта, размер образа my_raspbian.img станет намного меньше исходного, и теперь его можно будет записать на любую карту подходящего размера.


Изменено:

Уменьшение размера образа для Raspberry Pi: 26 комментариев

  1. срасибо за описание…но я не программист…поробовал по пунктам…чтото не получилось…
    вопрос:
    1. надо делать все под польщователем root?
    2.вы описываете:(1) Первое, что нам потребуется сделать — это создать свежий образ SD-карты ) это надо закачать образ или вы описываете, что просто нужна флешка…пустая?
    3.вы описываете в последнем пункте: (Ждем окончания его работы.) что после этого? образ появляется на флешке…

    • Образ — это копия всей файловой системы, снятая с носителя и упакованная определенным образом в файл. Собственно, создание образа — это и есть копирование его с носителя.
      Предположим вы скачали образ с сайта: https://www.raspberrypi.org/downloads/, который весит около 2Гб.
      Затем скопировали его на 16Гб SD-карту с помощью соответствующей программы. Затем вы развернули образ на весь размер карты, так что у вас файловая система стала занимать все 16Гб. Из них 2Гига занято операционной системой и еще 14Гб пустого места.
      Вдруг вам захотелось снять образ с этой SD-карты, и передать его другу. Но у друга флешка на 8Гб! Вот именно для таких случаев данная процедура и нужна. Ибо вы иначе никак не сможете записать образ размером 16Гб на карту размером 8Гб.

      Насчет root. А в каком именно месте ломается данная процедура? Может быть проблема в чем то другом. Но можно попробовать и под root, хуже не будет.

      В конце процедуры, образ, который был указан в качестве параметра скрипта, станет меньше размером. После этого его нужно будет записать на SD-карту.

  2. Следует добавить, что если образ больше 4ГБ, то флэшка должна быть отформатирована в соответствующей файловой системе (напр NTFS).
    Поскольку Raspbian «из коробки» NTFS не поддерживает, необходимо выполнить:
    sudo apt-get update
    sudo apt-get install ntfs-3g
    После этого становится доступна запись на NTFS носитель.

  3. “**********************************”
    “*** This should be run as root ***”
    “**********************************”
    “”
    Не работает

    • в итоге тоже самое выходит в терменале первые строки скрипта и все размер остается прежним.

  4. Делаю по пунктам всё как описано, но скрипт выдаёт на экране
    “”
    “**********************************”
    “*** This should be run as root ***”
    “**********************************”
    “”
    И на этом тишина … в HTOP никаких процессов. Что делаю не так ? Все действия под root производил. Создание скрипта точно как описано у Вас. Подскажите если не трудно может в скрипте ошибка или нужно, что-то для него
    Образ правда делал с SD карты на другой системе потому что, если его делать с загруженной Raspberry не даст доступа к файловой системе.
    sudo apt-get install bc установлено..
    sudo apt-get install ntfs-3g установлено…

    • Вообще, судя по скрипту, эта ошибка вылазит если скрипт запускается не от рута (первые строчки скрипта). Может у вас с sudo какие-то проблемы.. Система чистая, никакого волшебства с ней не творилось?

      • Нет под su строго система собрана для дальнейшего клонирования. Поэтому не пойму в чём проблема другие скрипты работают в ней. Не под su даже этого окна не было бы.

  5. парни всем привет, у кого с работал данны метод, давно думаю скинуть систему с 32 на 8 гб , а то без дела почти 30гб. черканите

    • не работвет не хр@на эта инструция сам попробовал верхние строки скрипта выходят и все. так ничего и не на шел чем можно образ из 32гб записать в 4гб звнято то всего около 3 гб.

      • Сергей, уточните на каком шаге у вас проблема возникла? Может скриншот есть?

  6. Добрый день!
    Сделал так, как написано, но получил ответ:
    Error : Not an image file, or file doesn’t exist.
    Судя по всему, не нравится выражение [[ ! -e $1 || ! $(file $1) =~ “x86” ]],
    а именно ! $(file $1) =~ “x86”.
    Попытался закомментить эту проверку, т.к. точно уверен, откуда получил этот файл, но в процессе обработки лезут ошибки на обнаруженные неверные символы.

  7. В добавление к предыдущему.
    Решил вставить строчку перед строкой проверки:
    echo $(file $1)

    Получил ответ:
    10_03_raspbian.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x0,130,3), end-CHS (0x8,40,32), startsector 8192, 122880 sectors

  8. Не работает у людей так как в коде используются русские кавычки “x86” вместо стандартных «

  9. Как это сделать на винде? Не входит образ на флешку (типа 16, но не 16)!
    Образ есть на винте?

  10. Я убил на это несколько часов, пока подготовил все подходящие носители, и в итоге:
    awk: 1: unexpected character 0xe2
    ./cut_img.sh: command substitution: line 27: syntax error near unexpected token `(‘
    ./cut_img.sh: command substitution: line 27: `echo “$partinfo” | grep ext4 | awk -F: ‘ { print substr($2,0,length($2)-1) } ‘’
    losetup: failed to parse offset: ‘/media/RPIcopy.img’: Invalid argument
    Usage: e2fsck [-panyrcdfktvDFV] [-b superblock] [-B blocksize]
    [-l|-L bad_blocks_file] [-C fd] [-j external_journal]
    [-E extended-options] [-z undo_file] device

    • подтверждаю. по ссылке нормальный код. чё то автор с кавычками намудрил

  11. Сегодня уже 02.07.21. Похоже решение этой задачи забросили.
    У меня проблема возникла в самом начале.
    После создания папки для флешки монтирование флешки не получилось.
    Жаль. Тема актуальная.

  12. Вот рабочий вариант:

    #!/bin/bash
    # Automatic Image file resizer
    # Written by SirLagz
    strImgFile=$1

    if [[ ! $(whoami) =~ «root» ]]; then
    echo «»
    echo «**********************************»
    echo «*** This should be run as root ***»
    echo «**********************************»
    echo «»
    exit
    fi

    if [[ -z $1 ]]; then
    echo «Usage: ./autosizer.sh »
    exit
    fi

    #if [[ ! -e $1 || ! $(file $1) =~ «x86» ]]; then
    if [[ ! -e $1 || ! $(file $1) =~ «x83» ]]; then
    echo «Error : Not an image file, or file doesn’t exist»
    #exit
    fi

    partinfo=`parted -m $1 unit B print`
    partnumber=`echo «$partinfo» | grep ext4 | awk -F: ‘ { print $1 } ‘`
    partstart=`echo «$partinfo» | grep ext4 | awk -F: ‘ { print substr($2,0,length($2)-1) } ‘`
    loopback=`losetup -f —show -o $partstart $1`
    e2fsck -f $loopback
    minsize=`resize2fs -P $loopback | awk -F’: ‘ ‘ { print $2 } ‘`
    minsize=`echo $minsize+1000 | bc`
    resize2fs -p $loopback $minsize
    sleep 1
    losetup -d $loopback
    partnewsize=`echo «$minsize * 4096» | bc`
    newpartend=`echo «$partstart + $partnewsize» | bc`
    part1=`parted $1 rm 2`
    part2=`parted $1 unit B mkpart primary $partstart $newpartend`
    endresult=`parted -m $1 unit B print free | tail -1 | awk -F: ‘ { print substr($2,0,length($2)-1) } ‘`
    truncate -s $endresult $1

  13. sudo dd bs=4M if=/dev/mmcblk0 of=/mnt/hdd/raspbian.img
    с флешки получается образ 30Гб. Ужимается скриптом до 7.5 Гб.
    При восстановлении W32diskimage ругается, что на начальный файл, что на сжатый. При восстановлении на сжатом файле Расберри не грузится.
    Обаз, созданный с флешки программой W32diskimage при последующем восстановлении рабочий, все грузится. Попробую как скрипт его уменьшит и получится с уменьшенного загрузится. Если нет, снесу нафиг этот скрипт.

Добавить комментарий для un Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.