Привет, Хабр! Это Виктор Сергеев, автор команды спецпроектов МТС Диджитал. В детстве я очень любил фантастику и обожал представлять себя в кабине космического корабля с кучей экранов, светящихся индикаторов и переключателей. Рабочее место современного радиолюбителя очень похоже на такой корабль, чему мы обязаны развитию недорогих одноплатников. Они же позволяют создавать портативные, но функциональные устройства, вроде хотспотов MMDVM (Multi-Mode Digital Voice Modem).
MMDVM представляет собой самую обычную «малинку» Raspberry Pi Zero W с дополнительной платой (HS shield), на которой реализован радиотракт. В рабочем режиме нагрузка на процессор не слишком велика, а большую часть времени он вообще находится в простое. Именно это обстоятельство позволяет добавить внутрь очень востребованный у радиолюбителей инструмент — HamClock. О нем и расскажу.
Несмотря на то, что MMDVM-хотспот можно с программной точки зрения построить разными способами, большинство радиолюбителей использует готовое решение, которое называется Pi-Star. Это отдельная и сильно доработанная версия Raspbian, предназначенная именно для организации работы хотспота и ни для чего более. Разработчик системы постарался сделать так, чтобы пользователь ничего не мог сломать, и принял целый ряд решений, которые затрудняют запуск стороннего ПО. Но об этом я узнал лишь в процессе настройки.
Начало истории
Все началось с того, что мне такую железку подарили со словами «у меня уже есть нормальный DMR-репитер, а эта игрушка более ни к чему». Решив посмотреть, как это работает, я залил на MicroSD-карту образ Pi-Star и подключил хотспот к сети FreeDMR, которая не требует отдельной регистрации. Погонял в паре с DMR-радиостанцией Anytone AT-D878UVII Plus, о которой я уже рассказывал здесь, на Хабре. Все прекрасно «завелось», и MMDVM-хотспот теперь работает в режиме 24/7, обеспечивая меня собственным крошечным цифровым репитером с небольшим радиусом действия.
Однажды, когда я общался со своим знакомым радиолюбителем, речь как раз зашла об MMDVM, и тот у меня поинтересовался, а можно ли как-нибудь установить на эту железку HamClock. Все равно хотспот работает круглосуточно, процессор у него не слишком занят и вполне может потянуть дополнительную нагрузку. Чтобы ответить на этот вопрос, я зашел на девайс по SSH и ввел команду:
$ cat /etc/os-release PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)" NAME="Raspbian GNU/Linux" VERSION_ID="11" VERSION="11 (bullseye)" VERSION_CODENAME=bullseye ID=raspbian ID_LIKE=debian HOME_URL="http://www.raspbian.org/" SUPPORT_URL="http://www.raspbian.org/RaspbianForums" BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
«Обычный Raspbian», — подумал я и без тени сомнения сказал:
— Да, эта штука там точно заработает. Единственный момент: такая малинка не слишком быстрая, поэтому компиляция, вероятно, займет приличное количество времени. Да и само приложение в процессе работы, скорее всего, будет подтормаживать.
— Ну ты можешь это сделать и написать простую инструкцию?
— Без проблем.
Как вы уже можете догадаться, сложностей возникло приличное количество, иначе я бы вряд ли стал писать об этом на Хабр 🙂
Береги память смолоду
У одноплатных компьютеров вроде «малинки» есть особенность: роль накопителя данных в большинстве случаев выполняет MicroSD-карта. Ее устройство достаточно простое: контроллер и микросхема флеш-памяти типа NAND. Несмотря на развитие технологий, физику обмануть невозможно, и чем чаще вы записываете данные в ячейки, тем быстрее они изнашиваются.
Понятное дело, что количество перезаписей будет зависеть от типа памяти. К примеру, ячейка TLC NAND выдержит 1 000 циклов перезаписи, а SLC NAND спокойно переживет и 100 000. Контроллеры, конечно, тоже умные и умеют маскировать проблему, вовремя перенаправляя данные из сбойных ячеек в резервную область. Но и она не бесконечна, а значит, со временем точно так же деградирует, а накопитель выйдет из строя.
У Raspbian (считай, обычного Debian Linux) есть приличное количество способов убить вашу карту памяти. Ведение системного журнала означает, что ОС перманентно будет записывать события на диск. Ротация такого журнала приводит к постоянной перезаписи одних и тех же ячеек, а значит, повышенному их износу.
Раздел подкачки (swap) тоже весьма губительно сказывается на состоянии накопителя. Когда в процессе работы оперативная память исчерпана, система задействует swap в качестве временного хранилища. Это приводит к повышенному износу ячеек и преждевременной гибели карты. Такое случается очень часто, карты памяти могут легко выходить из строя за 2–6 месяцев, потом их нужно менять на новые.
Есть несколько способов продлить жизнь карты памяти. Можно отключить раздел подкачки и ведение логов. Разработчики встраиваемых систем часто применяют методику ReadonlyRoot — она заключается в том, чтобы монтировать большинство системных директорий только для чтения. С одной стороны, это позволяет минимизировать количество записей в ячейки NAND и продлевает им жизнь. А еще можно не беспокоиться о том, что вы выключили устройство, а оно что-либо не успело дописать из кэша на диск.
Именно этот прием был использован при создании Pi-Star, это звучит очень разумно и логично. С одной стороны, система не станет требовать частой замены SD-карты и спокойно справится с нештатным отключением хотспота. Но вот с другой стороны, чтобы внести любые изменения в систему, потребуется перемонтировать ФС для записи. Привычные приемы автозапуска скриптов и приложений могут вести себя иначе. Но это все в теории, а значит, пора переходить к практике.
Установка HamClock
Нельзя сказать, что она отличается какой-либо сложностью. Авторы создали удобный скрипт, который самостоятельно сделает все за пользователя. Он рассчитан на работу с Raspberry Pi, поэтому учитывает особенности архитектуры. По умолчанию в Pi-Star предусмотрена команда, которая позволяет пользователю перемонтировать корневой каталог на чтение и запись. Выполним ее перед скачиванием скрипта:
$ rpi-rw
Скачиваем скрипт при помощи curl:
$ curl -O https://www.clearskyinstitute.com/ham/HamClock/install-hc-rpi
Сделаем его исполняемым, одновременно игнорируя umask:
$ chmod u+x install-hc-rpi
Запускаем установку. Указываем, что хотим скомпилировать исключительно web-версию, выбираем желаемое разрешение экрана и можем спокойно идти готовить кофе или заниматься другими полезными делами. В ближайшие 30 минут «малинка» займется компиляцией HamClock, написанном на C++:
$ ./install-hc-rpi
После того как все установлено и скомпилировано, скрипт предложит прописать его в автозагрузку при помощи crontab. Соглашаемся, но, забегая вперед, скажу: автостарт не сработает по причине того, что HamClock при запуске попробует записать несколько файлов в директорию /home/pi-star/.hamclock и у него ничего не получится. Переходим к следующему этапу.
Жонглирование разделами
Как только вы записали образ Pi-Star на карту памяти, она занимает совсем немного места. Но при первом запуске система автоматически увеличивает раздел так, чтобы он занял все свободное пространство на диске. В итоге получается два каталога: на одном /boot, а второй будет корневым /. Оба они монтируются в /etc/fstab как ReadOnly, и это не дает возможности писать на них.
Есть немного костыльный, но рабочий способ. Например, уменьшить объем корневого раздела, а на освободившемся месте сделать еще один, который уже можно монтировать для чтения и записи. Если перенести на него директорию пользователя /home/pi-star, то это решит сразу все проблемы с невозможностью записи.
Сложность вышеуказанного метода лишь в том, что эту операцию не получится выполнить на смонтированном разделе. А поскольку он корневой, то реализовать это непосредственно из операционной системы не выйдет. А еще это Raspberry Pi, варианта загрузиться с LiveCD у нас тоже нет. Так что для успешного выполнения следующих операций потребуется отдельный компьютер с Linux. В моем случае я извлек MicroSD-карту из MMDVM и вставил ее в USB-картридер. Тот, в свою очередь, подключил к ноутбуку с установленной Ubuntu.
Первым делом я посмотрел на то, какие устройства присутствуют в системе. Вставленная карта памяти определилась как /dev/sdb. Давайте глянем на то, какие разделы у нас есть:
$ sudo fdisk -l Disk /dev/sdb: 29.81 GiB, 32010928128 bytes, 62521344 sectors Disk model: USB CARD READER 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: 0xc958b717 Device Boot Start End Sectors Size Id Type /dev/sdb1 8192 532479 524288 256M c W95 FAT32 (LBA) /dev/sdb2 532480 62521343 61988864 29.6G 83 Linux
Видно, что корневой раздел занимает 29,6 Гб, начало находится с блока 532480. Запоминаем это значение. Перед тем как изменять размер, нужно в обязательном порядке выполнить проверку ФС на проблемы:
$ sudo e2fsck -f /dev/sdb2
Все прошло хорошо, ошибок нет. Приступаем к изменению размера ФС. Пусть корневой раздел составляет 28 Гб, а оставшиеся 1,6 Гб используем для домашнего каталога:
$ sudo resize2fs /dev/sdb2 -s 28G
После того как размер файловой системы поменялся, нужно модифицировать объем раздела. Вводим команду:
$ sudo fdisk /dev/sdb
В fdisk нет возможности указать уменьшение объема каталога. Но его можно удалить и создать заново. Для этого нужно нажать клавишу d и подтвердить удаление раздела 2 (/dev/sdb2). Появится вопрос — убрать ли метку ext4. Отвечаем отрицательно, ее нужно оставить.
После удаления раздела нажимаем n для создания нового. Тип — Primary, ну а значение стартового блока — 532480. Вместо финального значения пишем +28G и подтверждаем нажатием Enter. В итоге появится /dev/sdb2 с объемом 28 Гб. На диске останется 1,6 Гб нераспределенного пространства.
Создаем еще один раздел через нажатие n. Тип также выбираем Primary. Начальное и конечное значение блоков утилита подставит сама. В итоге мы получаем третий раздел /dev/sdb3 размером 1,6 Гб. Останется только нажать клавишу w и подтвердить с помощью Enter. Это действие запишет изменения на диск.
Проверяем:
$ sudo fdisk -l Disk /dev/sdb: 29.81 GiB, 32010928128 bytes, 62521344 sectors Disk model: USB CARD READER 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: 0xc958b717 Device Boot Start End Sectors Size Id Type /dev/sdb1 8192 532479 524288 256M c W95 FAT32 (LBA) /dev/sdb2 532480 59252735 58720256 28G 83 Linux /dev/sdb3 59252736 62521343 3268608 1.6G 83 Linux
Теперь нужно создать на новом разделе файловую систему:
$ sudo mkfs.ext4 /dev/sdb3 mke2fs 1.46.5 (30-Dec-2021) Creating filesystem with 408576 4k blocks and 102336 inodes Filesystem UUID: dc371ae8-868f-4059-a289-a76593efd0d0 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912 Allocating group tables: done Writing inode tables: done Creating journal (8192 blocks): done Writing superblocks and filesystem accounting information: done
Перед тем как извлекать карту памяти, убеждаемся, что все дисковые операции завершены:
$ sync
После того как команда выполнится, не вызывая никаких сообщений, карту можно извлекать и ставить обратно в MMDVM.
Монтирование пользовательского каталога
Поскольку мы переставили накопитель в другое устройство, его наименование изменилось. Теперь это не /dev/sdb, а /dev/mmcblk0 с тремя разделами:
-
/dev/mmcblk0p1 — /boot;
-
/dev/mmcblk0p2 — /;
-
/dev/mmcblk0p3 — unmounted.
В домашнем каталоге пользователя pi-star уже есть некоторое количество файлов и директорий, так что сначала нужно будет их перенести. Для этого нам нужно смонтировать /dev/mmcblk0p3 в любой временный каталог.
Перемонтируем файловую систему на запись:
$ rpi-rw
Создаем временную директорию в /mnt:
$ sudo mkdir /mnt/ext
Монтируем новый раздел в этот каталог:
$ sudo mount /dev/mmcblk0p3 /mnt/ext
Убеждаемся в том, что все получилось:
$ sudo df -h Filesystem Size Used Avail Use% Mounted on /dev/root 2.9G 2.1G 709M 75% / devtmpfs 111M 0 111M 0% /dev tmpfs 239M 0 239M 0% /dev/shm tmpfs 32M 5.2M 27M 17% /run tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 64M 0 64M 0% /tmp tmpfs 1.0M 32K 992K 4% /var/cache/samba tmpfs 32K 16K 16K 50% /var/lib/dhcpcd tmpfs 16K 0 16K 0% /var/lib/logrotate tmpfs 1.0M 0 1.0M 0% /var/lib/nginx/body tmpfs 64K 0 64K 0% /var/lib/php/sessions tmpfs 4.0M 2.2M 1.9M 54% /var/lib/samba/private tmpfs 16K 0 16K 0% /var/lib/sudo tmpfs 64M 288K 64M 1% /var/log /dev/mmcblk0p1 256M 49M 207M 20% /boot tmpfs 48M 0 48M 0% /run/user/1000 /dev/mmcblk0p3 1.5G 24K 1.5G 1% /mnt/ext
Теперь нужно сделать пользователя pi-star владельцем этого каталога, чтобы тот получил возможность записывать туда данные:
$ sudo chown -R pi-star:pi-star /mnt/ext
Синхронизируем содержимое домашнего каталога с этой директорией при помощи rsync:
$ sudo rsync -a /home/pi-star /mnt/ext
Теперь все готово к тому, чтобы монтировать раздел /dev/mmcblk0p3 в качестве /home/pi-star. Открываем fstab:
$ sudo nano /etc/fstab
Вносим туда строчку:
/dev/mmcblk0p3 /home/pi-star ext4 defaults,rw 0 0
Сохраняем, нажав Ctrl + O, потом выходим с помощью Ctrl + X. Отправляем MMDVM в перезагрузку:
$ sudo reboot
Если все сделано правильно, через пару минут можно вновь подключиться по SSH и убедиться в том, что каталог успешно смонтирован:
$ df -h Filesystem Size Used Avail Use% Mounted on /dev/root 2.9G 2.1G 709M 75% / devtmpfs 111M 0 111M 0% /dev tmpfs 239M 0 239M 0% /dev/shm tmpfs 32M 5.2M 27M 17% /run tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 64M 0 64M 0% /tmp tmpfs 1.0M 32K 992K 4% /var/cache/samba tmpfs 32K 16K 16K 50% /var/lib/dhcpcd tmpfs 16K 0 16K 0% /var/lib/logrotate tmpfs 1.0M 0 1.0M 0% /var/lib/nginx/body tmpfs 64K 0 64K 0% /var/lib/php/sessions tmpfs 4.0M 2.2M 1.9M 54% /var/lib/samba/private tmpfs 16K 0 16K 0% /var/lib/sudo tmpfs 64M 276K 64M 1% /var/log /dev/mmcblk0p3 1.5G 31M 1.4G 3% /home/pi-star /dev/mmcblk0p1 256M 49M 207M 20% /boot tmpfs 48M 0 48M 0% /run/user/1000
Если откроете утилиту top, то увидите, что в списке процессов появился hamclock. Получается, что автозапуск через crontab успешно сработал и все уже функционирует. Но если вы попытаетесь открыть браузер и зайти по адресу приложения, вас ждет неудача:
http://[IP-адрес_MMDVM]:8081/live.html
Соединение не устанавливается, и причина этому в том, что нет соответствующего правила в iptables. Если вы пропишете его руками, оно будет работать исключительно до перезагрузки. Утилиты вроде iptables-persistent в случае с Pi-Star бесполезны. Все дело в том, что у Pi-Star собственное управление файерволом и именно оно контролирует все правила iptables.
Так что делаем так. Переключаемся в консоль суперпользователя:
$ sudo su
Перемонтируем файловую систему на чтение и запись:
# rpi-rw
Создаем новый файл ipv4.fw в каталоге /root:
# nano /root/ipv4.fw
Пишем туда правило iptables:
iptables -I INPUT -p tcp —dport 8081 -j ACCEPT
Сохраняем при помощи Ctrl + O и выходим из редактора Ctrl + X. Остается самая важная часть — вызвать специальный скрипт, который перечитает все действующие правила iptables, обнаружит новое и активирует его:
# pistar-firewall
Отправляем MMDVM на перезагрузку:
# reboot
Через пару минут открываем браузер и наслаждаемся рабочим приложением HamClock:
Что в итоге
Pi-Star — отличный дистрибутив, который хорошо делает свое дело. Но вот если вы захотите установить на него что-то дополнительно, то, вероятнее всего, столкнетесь с трудностями. Основной, разумеется, будет корневая файловая система, смонтированная только для чтения.
Это решение показалось мне самым функциональным. Оно сохраняет возможность работы корневой ФС в том самом режиме ReadOnly, который был предусмотрен автором Pi-Star. При этом есть директория, которая будет всегда доступна для чтения и записи, а значит, сможет выполнять роль хранилища для различных приложений, включая HamClock.
Расскажите о своем опыте общения с устройствами, чья корневая файловая система была смонтирована в режиме ReadOnly? Как вы решали вопрос с автозапуском скриптов и приложений, хранением файлов? Жду в комментариях.
ссылка на оригинал статьи https://habr.com/ru/articles/858156/
Добавить комментарий