Файловая система на SD карте — при некоторых обстоятельствах может стать большой головной болью владельцев Raspberry Pi. Дело в том, что современные бюджетные SD-карты (и SSD) имеют весьма ограниченный ресурс записи. В зависимости от типа: QLC — около 1 тыс, самые распространенные сегодня TLC 3D NAND — 3 тыс циклов перезаписи. И только однослойная версия SLC имеет до 100 тыс циклов.
Чем это плохо? Для обычного пользователя — ничем. Но если ваши приложения сильно нуждаются в оперативной памяти, они начинают активно использовать своп — участок накопителя, который становится расширением ОЗУ. Ясно, что этот своп будет интенсивно уменьшать ресурс NAND памяти.
Второй пример — Raspberry Pi в качестве видерегистратора или системы журналирования. Та же история. На носитель ведется непрерывная запись данных: видеопотоки раз за разом записываются поверх своих старых версий.
Дополнительный шок — смерть файловой системы на SD-карте после аварийного отключения питания. На своих Raspberry Pi, используемых для учебных целей мы наблюдали такое не раз.
Как с этим бороться? Заставить Raspberry Pi работать с внешним HDD накопителем. В отличие от NAND памяти, классические жесткие диски трудятся десятилетиями при интенсивной нагрузке. Этим и займемся!
Перенос файловой системы на внешний USB накопитель
К сожалению, полностью избавиться от SD-карты на Raspberry Pi проблематично, так как без неё операционная система не сможет загрузиться. Как минимум, на SD-карте должен остаться раздел boot. А вот всё остальное — rootfs, можно и нужно вынести на внешний USB накопитель. Делаем по шагам.
1. Скачиваем образ Raspbian с официального сайта
2. Копируем его на внешний диск при помощи программы balenaEtcher или Raspberry Pi Imager
3. Теперь нам нужно подготовить загрузочную SD-карту. Операцию будем проводить из Linux с помощью утилиты parted. Подойдет карта размером 4 Гб — меньше уже трудно найти. Если нет машины с linux, можно использовать raspberry pi с USB-картридером.
С помощью команды lsblk выводим список всех носителей и ищем там нашу карту.
root@mainframe:~$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:32 0 55,9G 0 disk └─sda1 8:33 0 55,9G 0 part / sdb 8:64 1 14,6G 0 disk ├─sdb1 8:65 1 256M 0 part /media/mainframe/boot └─sdb2 8:66 1 14,3G 0 part /media/mainframe/rootfs sdc 8:64 1 3,7G 0 disk └─sdc1 8:65 1 3,7G 0 part
Обнаружить карту можно по размеру. При написании этой статьи была использована карта размером 4Гб. Вот она, в самом низу списка — sdc.
Создаем новую таблицу разделов (disk label):
root@mainframe:~$ sudo parted /dev/sdc --script -- mklabel msdos
Затем создаём раздел с файловой системой fat32:
root@mainframe :~$ sudo parted /dev/sdc --script -- mkpart primary fat32 1MiB 100%
Форматируем созданный раздел:
root@mainframe:~$ sudo mkfs.vfat -F32 /dev/sdc1
Наконец, копируем файлы из директории /boot внешнего диска на SD карту с помощью команды rsync:
root@mainframe:~$ sudo rsync -rt /dev/sdb1/boot /dev/sdc1/boot
Готово. Теперь у нас есть SD-карта с загрузочным разделом.
4. Выясняем UUID внешнего диска и SD карты с помощью команды
sudo blkid
В ответ получим список разделов, подключенных к машине, например:
root@mainframe:~ $ sudo blkid /dev/sda1: UUID="f2b548cd-ef9b-4711-8e05-633ed612808d" TYPE="ext4" PTTYPE="dos" PARTUUID="035e035e-01" /dev/sdb1: LABEL="boot" UUID="6341-C9E5" TYPE="vfat" PARTUUID="ea7d04d6-01" /dev/sdb2: LABEL="rootfs" UUID="80571af6-21c9-48a0-9df5-cffb60cf79af" TYPE="ext4" PARTUUID="ea7d04d6-02" /dev/sdc1: UUID="331E-081B" TYPE="vfat" PARTUUID="7c077b54-01"
Нам нужны идентификаторы PARTUUID. Здесь идентификатор boot раздела SD-карты: 7c077b54-01, а PARTUUID раздела rootfs внешнего USB-накопителя: ea7d04d6-02
5. Редактируем файл /boot/cmdline.txt на SD карте:
5.1. В строке запуска заменим идентификатор хранилища rootfs, подставив туда UUID USB-диска из пункта №4.
root=PARTUUID=ea7d04d6-02
5.2. В конце добавим rootdelay=5 (чтобы у Kernel было больше времени на ожидание готовности USB устройства)
6. На внешнем USB диске редактируем /etc/fstab:
6.1. Удаляем строчку, в которой директория /boot ассоциируется с USB диском, например, такую:
PARTUUID=ea7d04d6-01 /boot vfat defaults 0 2
6.2.Вместо этой строчки добавляем свою:
PARTUUID=7c077b54-01 /boot vfat defaults 0 2
Здесь 7c077b54-01 — это PARTUUID SD-карты из пункта №4.
Готово. Перезапускаем Raspberry Pi и пользуемся.
Важно! Все описанные работы потенциально опасны для ваших данных, рекомендуем сделать резервные копии.
Алгоритм настройки позаимствован отсюда: Raspberry 4B — Boot from SD and rootfs on USB