14

Raspberry-Pi без насилования SD-карты

Как узнал про overlay filesystem — и спешу поделиться с вами

Или история о том, как я перестал хоронить SD-карты каждый год

Фабула

Перепробовав кучу одноплатников — Orange Pi, Banana Pi, несколько Raspberry Pi — я каждый раз упирался в одну и ту же проблему: microSD-карта дохнет меньше чем за год. Полгода-год, и игрушка молча умирает: то SSH не пускает, то читает-пишет через раз.

И как-то всё руки не доходили заняться проблемой. Пока недавно не вылетела очередная SD-карта. Сегодня я узнал про overlay-filesystem — и спешу поделиться находкой.

Опытные линуксоиды, конечно, улыбнутся, но этот опыт я хочу запечатлеть прежде всего для себя — а вдруг ещё кому пригодится. Также, стараюсь описать все максимально подробно - для совсем новичков. Статья, конечно, на 70% состоит из возни с разделами файловой системы, про overlay тут только в самом конце, но это может тоже кому то пригодиться.

Цели, которую я преследую

  1. Операционка в read‑only — корневая файловая система монтируется только на чтение. Ничего не пишется на SD-карту без явного на то желания пользователя.

  2. Всё временное — в оперативку. Логи, настройки, эксперименты, содержимое /var и /tmp — живут в памяти и бесследно исчезают после выключения. Никакого мусора.

  3. Откат при перезагрузке. После ребута система как новенькая — никаких хвостов от случайно установленного пакета или кривого конфига.

  4. Простота доработки. Поставить пакет, поправить конфиг, обновиться — без плясок с монтированием. Как это сделать — расскажу ниже.

  5. Отдельный rw‑раздел для данных — «на всякий случай». Туда можно спокойно копировать файлы по SSH, не думая о том, поместятся ли они в оперативку. Этот раздел будет переживать перезагрузки.

0. Мой сетап

  1. Raspberry Pi Zero W

  2. Raspberry Pi OS Lite

  3. SD-карточка на 32Gb (8Gb на операционку, остальное - в RW разделе)

  4. Ubuntu server 26.04 на виртуальной машине VirtualBox (просто уже стояла, подойдет любой современный дистрибутив)

1. Устанавливаем операционку

Думаю, что тут справится любой, кто имел хоть какое-то знакомство с Raspberry Pi. Скачиваем Raspberry Pi imager, вставляем SD-карту в компьютер, выбираем нашу версию платы, настраиваем, ждем, пока образ запишется на карту.

После этого вставляем SD-карточку в Raspberry Pi, дожидаемся загрузки (логина по ssh или появления десктопа), выключаем, вытаскиваем карточку. Тут можно, конечно, сделать сразу все необходимые манипуляции с операционкой - установить пакеты, настроить, но мы можем это сделать и потом.

2. Работа с разделами

Грузим виртуалку, выводим список доступных /dev/sd*, подключаем SD-карточку, находим искомое устройство:

$ ls -la /dev/sd*

brw-rw---- 1 root disk 8, 0 May 9 18:48 /dev/sda

brw-rw---- 1 root disk 8, 1 May 9 18:48 /dev/sda1

brw-rw---- 1 root disk 8, 2 May 9 18:48 /dev/sda2

<подключаем SD-карту>

$ ls -la /dev/sd*

brw-rw---- 1 root disk 8, 0 May 9 18:48 /dev/sda

brw-rw---- 1 root disk 8, 1 May 9 18:48 /dev/sda1

brw-rw---- 1 root disk 8, 2 May 9 18:48 /dev/sda2

brw-rw---- 1 root disk 8, 16 May 9 18:49 /dev/sdb

brw-rw---- 1 root disk 8, 17 May 9 18:49 /dev/sdb1

brw-rw---- 1 root disk 8, 18 May 9 18:49 /dev/sdb2

Paspberry Pi при записи образа создает два раздела - один для удобной настройки (файловая система FAT), другой - непосредственно системный (ext4). Их мы и видим в списке: /dev/sdb1 и /dev/sdb2.

Вероятнее всего, нам нужен второй раздел, но на всякий случай перепроверим: подмонтируем его, проверим размер и отмонтируем:

# sudo mount /dev/sdb2 /mnt

$ df -h /mnt

Filesystem Size Used Avail Use% Mounted on

/dev/sdb2 29G 2.3G 25G 9% /mnt

# sudo umount /dev/sdb2

Видим, что общий размер 29Gb, занято системой ~2.3Gb. Оно.

Правильный порядок действий при изменении размера (особенно уменьшении) выглядит так:

  1. Проверилиr файловую систему

  2. Уменьшили саму файловую систему

  3. Уменьшили раздел так, чтобы он совпал с новым размером ФС

Начнем с проверки файловой системы. Запускаем и ждём завершения:

# sudo e2fsck -f /dev/sdb2

e2fsck 1.47.2 (1-Jan-2025)

Pass 1: Checking inodes, blocks, and sizes

Pass 2: Checking directory structure

Pass 3: Checking directory connectivity

Pass 4: Checking reference counts

Pass 5: Checking group summary information

rootfs: 74119/1847360 files (0.2% non-contiguous), 715247/7506944 blocks

После завершения - задаем новой размер файловой системы в 8Gb:

# sudo resize2fs /dev/sdb2 8G

resize2fs 1.47.2 (1-Jan-2025)

Resizing the filesystem on /dev/sdb2 to 2097152 (4k) blocks.

The filesystem on /dev/sdb2 is now 2097152 (4k) blocks long.

Наша файловая система занимает 2097152 блоков размером 4К (или 4096 байт). Эти числа нам пригодятся в будущем. Теперь нужно разделить диск на 2 части - одну оставить для системы, вторую - для нашего RW раздела. Итак, запускаем fdisk на устройстве /dev/sdb

#sudo fdisk /dev/sdb

Welcome to fdisk (util-linux 2.41.3).

Changes will remain in memory only, until you decide to write them.

Be careful before using the write command.

Command (m for help): __

Утилита запускается, и просит ввести команду. Сначала перепроверим разделы и узнаем их номера. Вводим команду p (печать разделов):

Command (m for help): p

Disk /dev/sdb: 29.14 GiB, 31293702144 bytes, 61120512 sectors

Disk model: STORAGE DEVICE

Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disklabel type: dos

Disk identifier: 0x9298fc3d

Device Boot Start End Sectors Size Id Type

/dev/sdb1 16384 1064959 1048576 512M c W95 FAT32 (LBA)

/dev/sdb2 1064960 61120511 60055552 28.6G 83 Linux

Мы видим boot раздел в FAT32 (для настройки параметров raspberry pi) и linux-раздел с основной файловой системой. Также видим, что размер сектора тут - 512 байт. Это тоже нам пригодится.

Теперь аккуратно удаляем второй раздел:

Command (m for help): d

Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Теперь нужно создать новый раздел нужного размера (8Gb). Для этого нужно знать его начало (в секторах по 512 байт) и его конец (также в секторах по 512 байт).

Начало раздела мы знаем из результата выполнения команды p выше: 1064960. Нужно расчитать конец. Из результата выполнения команды resize2fs нам известно, что наша файловая система занимает 2097152 4096-байтных блоков.

Пересчитаем это в 512-байтные: 2097152 * 4096 / 512 = 16777216.

Добавив к этому значению начало сектора, получим номер конечного сектора:

16777216 + 1064960 = 17842176

Создадим новый системный раздел взамен удалённого ранее командой n, указав, что нужен primary-раздел (p) и номер 2. Введем номер первого сектора 1064960 и последнего 17842176.

Важно - см. последнюю строку!

Не удаляем предыдущую сигнатуру, иначе файловая система будет уничтожена -> вводим N!

Command (m for help): n

Partition type

p primary (1 primary, 0 extended, 3 free)

e extended (container for logical partitions)

Select (default p): p

Partition number (2-4, default 2): 2

First sector (2048-61120511, default 2048): 1064960

Last sector, +/-sectors or +/-size{K,M,G,T,P} (1064960-61120511, default 61120511): 17842176

Created a new partition 2 of type 'Linux' and of size 8 GiB.

Partition #2 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: N

Теперь создаем новый раздел - для пользовательских данных (RW) на всю оставшуюся часть флешки. Номер раздела - третий. Начальный сектор будет (конечный-для-раздела-2 + 1), то есть 17842176 + 1 = 17842177, а конечный - пустой. fdisk автоматически подставит последний доступный сектор:

Command (m for help): n

Partition type

p primary (2 primary, 0 extended, 2 free)

e extended (container for logical partitions)

Select (default p): p

Partition number (3,4, default 3): 3

First sector (2048-61120511, default 2048): 17842177

Last sector, +/-sectors or +/-size{K,M,G,T,P} (17842177-61120511, default 61120511):

Created a new partition 3 of type 'Linux' and of size 20.6 GiB.

Все, что мы делали выше - пока не записалось на флешку и эти изменения только запланированы. Перед записью изменений еще раз все перепроверим, введя команду p снова:

Command (m for help): p

Disk /dev/sdb: 29.14 GiB, 31293702144 bytes, 61120512 sectors

Disk model: STORAGE DEVICE

Units: sectors of 1 * 512 = 512 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disklabel type: dos

Disk identifier: 0x9298fc3d

Device Boot Start End Sectors Size Id Type

/dev/sdb1 16384 1064959 1048576 512M c W95 FAT32 (LBA)

/dev/sdb2 1064960 17842176 16777217 8G 83 Linux

/dev/sdb3 17842177 61120511 43278335 20.6G 83 Linux

Все верно. boot раздел на месте, у системного начальный сектор остался тем же, размр изменился. Появился новый третий раздел на остаток. Запишем изменения, введя команду w:

Command (m for help): w

The partition table has been altered.

Calling ioctl() to re-read partition table.

Syncing disks.

Готово.

Теперь создадим файловую систему на новом разделе командой mkfs.ext4:

# sudo mkfs.ext4 /dev/sdb3

mke2fs 1.47.2 (1-Jan-2025)

Creating filesystem with 5409791 4k blocks and 1354560 inodes

Filesystem UUID: 378e7266-5fa3-4591-a2e5-5b5732bb047d

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,

4096000

Allocating group tables: done

Writing inode tables: done

Creating journal (32768 blocks): done

Writing superblocks and filesystem accounting information: done

Извлекаем готовую флешку, выключаем виртуалку, она больше не понадобиться:

# sudo eject /dev/sdb

# sudo shutdown

Вставляем флешку в Raspberry Pi, включаем, логинимся.

3. Финалим всё на Raspberry Pi

Здесь я хочу сделать следующее: примонтировать user-раздел, сделать автоматическое монтирование при загрузке, включить overlay-режим файловой системы и сделать автоматическую перезагрузку устройства, дабы чистить память. Поехали!

3.1 Монтируем новый раздел

В Raspberry Pi разделы флешки называются иначе, вот они:

$ ls -la /dev/mmcblk0*

brw-rw---- 1 root disk 179, 0 May 8 22:04 /dev/mmcblk0

brw-rw---- 1 root disk 179, 1 May 8 22:05 /dev/mmcblk0p1

brw-rw---- 1 root disk 179, 2 May 8 22:04 /dev/mmcblk0p2

brw-rw---- 1 root disk 179, 3 May 8 22:04 /dev/mmcblk0p3

/dev/mmcblk0 - устройство
/dev/mmcblk0p1 - boot-раздел
/dev/mmcblk0p2 - системный раздел
/dev/mmcblk0p3 - большой раздел для данных, RW.

Создаем новую точку монтирования для RW-раздела (/dev/mmcblk0p3). Я хочу, чтобы она была в корне файловой системы и открытая для записи от текущего пользователя:

# sudo mkdir /work

# sudo chown $(whoami):$(whoami) /work
# sudo chmod 700 /work

Создаем скрипт автоматического монтирования и открываем его на редактирования:

# sudo nano /etc/systemd/system/work.mount

ВАЖНО! Имя файла .mount должно строго соответствовать пути монтирования, в котором символы / заменяются на - (дефис), а начальный слэш опускается.

Примеры:

/work -> work.mount
/mnt/data -> mnt-data.mount
/var/lib/docker -> var-lib-docker.mount

Содержимое файла:

[Unit]

Description=Mount /dev/mmcblk0p3 on /work

DefaultDependencies=no

After=systemd-udevd.service

Requires=systemd-udevd.service

Before=local-fs.target

Before=umount.target

Conflicts=umount.target

[Mount]

What=/dev/mmcblk0p3

Where=/work

Type=ext4

Options=defaults,noatime

[Install]

WantedBy=local-fs.target

Нажимаем Ctrl + X, подтверждаем сохранение, Y:

Включаем mount-юнит, перезагружаемся чтобы проверить:

# sudo systemctl enable work.mount

Created symlink '/etc/systemd/system/local-fs.target.wants/work.mount' → '/etc/systemd/system/work.mount'.

# sudo reboot

Проверяем:

$ df -h

Filesystem Size Used Avail Use% Mounted on

...

/dev/mmcblk0p2 7.9G 2.3G 5.3G 30% /

/dev/mmcblk0p3 21G 2.1M 20G 1% /work

/dev/mmcblk0p1 505M 78M 427M 16% /boot/firmware

...

Все три раздела - там, где им нужно быть.

3.2 Включаем overlay-filesystem

# sudo raspi-config

Идём в Perfomance options -> P2 Overlay file system Enable/disable read only file system

Стрелкой влево выбираем Yes:

Ждем пока доставятся пакеты ... Процесс завершился успешно:

Нажимаем Yes, если нам не нужно менять информацию на /boot разделе внутри самой системы (если вытащить флешку и вставить в компьютер - все будет работать в режиме чтения-записи):

Две стрелки вправо - <Finish>, соглашаемся с перезагрузкой...

После этого все изменения в системном разделе будут в оперативной памяти. Это очень удобно для экспериментов - пробуем что то настроить - не получается - перезагрузка и система "девственная".

Для того, чтобы перейди в "write" режим (записать конфиг, обновить систему, доставить пакеты и так далее ..) необходимо просто выполнить команду:

# sudo overlayroot-chroot

Сделать все необходимые действия и выйти из режима, на всякий случай сделав синхронизацию

# cd /

# sync

: Эти изменения запишуться в системный раздел.

3.3 Автоматическая перезагрузка для очистки оперативки

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

Откроем на запись наш системный раздел и добавим crontab, который выполняет автоматическую перезагрузку, например, в 4:00 ночи:

# sudo overlayroot-chroot

# crontab -e

Дописываем в конец:

0 4 * * * /usr/sbin/reboot

Ctrl+X, соглашаемся на запись ( Y ), видим что новый crontab установлен, синхронизируемся и выходим.

crontab: installing new crontab

# cd /

# sync

# exit

Вот и всё. Теперь ваша SD-карта живёт спокойно, система загружается в read-only, любые эксперименты умирают вместе с перезагрузкой, а для важных данных есть отдельный /work.

Если захотите что-то обновить или поставить — sudo overlayroot-chroot, сделали дело, вышли. Несложно.

Надеюсь, эта инструкция сэкономит вам пару нервных клеток и одну SD-карту в год.

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества