Saturday, December 17, 2016

Малиновый Прог против Интернета Кирпичей, или Raspberry Pi с графикой на read-only microSD / Geektimes

Например-программист 1-ой категории
10,4
рейтинг
сегодня в 00:00

Малиновый Прог против Интернета Кирпичей, или Raspberry Pi с графикой на read-only microSD

Аннотация


Запуск Raspberry Pi с полной поддержкой графики на microSD, навсегда остающейся в режиме read-only после установки системы. Отсутствие какой-либо записи данных на флэш-память повышает надёжность устройства, приближая его к промышленному классу изделий. Пошаговая инструкция. Небольшой театр инженерного абсурда для развлечения аудитории.


Мне понадобилось сетевое устройство с открытым кодом и выходом HDMI, и я решил попробовать Малиновый Прог. Да, я именно так предлагаю переводить Pi: Прог. Понятное дело, даже одноплатнику нужна операционка. И вот, захожу я на официальный сайт, ожидая встретить там подробное руководство по созданию суровой, неломаемой Вещи à la turnkey box. Но народ, как ни в чём не бывало, устанавливает Ubuntu (т.е. Raspbian Jessie) прямо на microSD, размещая и swap там же. Как обычный десктоп, face palm.

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

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

Куда мир катится


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

Неплохой проект, который испортила одна рекомендация
Представьте себе большой телевизор и демонстратор слайд-шоу на базе RPi, но с нейтрализацией скринсейвера аппаратным (!) имитатором ёрзающей мыши. Дескать, в оконном интерфейсе Raspbian тайм-аут скринсейвера больше 720 минут не выставляется. Поэтому, дабы каждые 12 часов не шевелить мышь вручную, народ автоматизирует процесс микроконтроллером, создающим виртуальные «ползки» USB-мыши каждые 4 минуты. Я не шучу, вот реальный проект на RPi, там же ссылка на микроконтроллер ECIO28P, и прошивка взбадривателя имеется.

Ладно, не буду отрицать самостоятельной полезности аппаратного взбадривателя: это реальный лайф-хак для тех, у кого почасовая оплата идёт за сидение перед монитором. Или для поддержания в тонусе какого-нибудь особо тупого сурового промышленного терминала, из-под антивандальной брони которого торчит один разъём для мыши (для PS/2 должен подойти зелёный переходник). Да, если втиснуть раздутый десктоп в одноплатный компьютер, то в руках über-умельцев это грозное оружие, особенно с брутально торчащей из разъёма платой МК. Сразу видно: человек умеет работать руками. Но если нужен вечно включённый экран, на линуксе достаточно головы, резиденты данного ресурса прекрасно это знают. Для гостей портала я всё-таки дам инструкцию, мало ли чего.

Отключение DPMS, скринсейвера и заодно всех GUI-элементов
Для начала примем, что используется минималистичная оболочка LightDM, и отключим X-серверу DPMS в файле /etc/lightdm/lightdm.conf:
...  xserver-command=X -s 0 -dpms -nocursor  ...

Флажок -nocursor убирает долой из центра экрана неподвижную стрелку курсора. А вместо нейтрализации скринсейвера можно просто закомментировать его запуск в файле ~/.config/lxsession/LXDE/autostart. Если это не помогает, можно повесить по cron(8) с интервалом 718 минут команду xscreensaver-command -deactivate.

Я поступил просто: принял LightDM с автовходом, но оставил в файле ~/.config/lxsession/LXDE/autostart лишь вызов feh с префиксом '@' для перезапуска в случае аварии и соотв. параметрами. Т.е. как бы обычная графика, но без lxpanel, без pcmanfm, без xscreensaver, с отключённым DPMS и скрытым курсором несуществующей мыши.

Минимальную графику очень легко получить командами apt-get и правкой файла autostart, причём в системе будет всё необходимое для жизнедеятельности стандартных приложений, включая X-сервер, менеджер окон, менеджер сеансов и менеджер дисплея с автовходом пользователя. Но пока это ещё не Вещь, а всего лишь одноплатный десктоп.

Задача


Сферический одноплатник в вакууме — это скучно. Не для того на Малиновом Проге целая гребёнка GPIO с I2C/PWM, а также всякие CSI-DSI и сторожевой таймер. Но я в качестве практического примера использую всё-таки сетевой демонстратор с HDMI-выходом, добавив возможность нескольким пользователям по очереди «захватывать» общий экран-табло и транслировать на него свой рабочий стол, не вставая с кресла. Экран повёрнут лицом в сторону гостей, в состоянии покоя тихонечко перебирает случайным образом картинки, выложенные в сети. Если надо показать гостю продукт, один из сидящих за стойкой администраторов временно превращает табло в «зеркало» своего монитора, но потом освобождает его для другого админинистратора. В моём случае это реальный бизнес-инструмент, висящий в реальном торговом зале. Кстати, благодарю пользователя Sauron за подсказку.

Однако, глянув на размер этой публикации, я решил отложить описание прикладного решения (т.е. собственно видеомодуля) в отдельную статью. Пока позвольте сфокусироваться на изначальной задаче: заставить Raspberry Pi загружаться и работать с microSD в режиме read-only, не боясь отключения питания и не запиливая флэш-память мусором.

Теория вопроса


Даже очень серьёзная файловая система с журналом в конечном итоге не может проконтролировать процессы, происходящие внутри SD-носителя при отключении питания. Например, серьёзные SSD-накопители для использования в ЦОД имеют конденсаторы, разряда которых как раз хватает на закрытие последней транзакции записи, и даже остаётся ещё немного. А что с отключением питания в microSD? Я уверен, там конденсаторов достаточной ёмкости нет, зато есть ненулевая вероятность того, что запись страницы NAND-памяти не успеет завершиться. И потом драйвер файловой системы от прочитанного придёт в такое недоумение, что потребуется ручное вмешательство оператора. Вот вам и фоторамка с fsck.

Насколько сложно перевести microSD Raspberry Pi в режим read-only методом Микеланджело, т.е. убирая лишние службы и пакеты? Достаточно просто, если нет графики (ссылка). Но стоит пустить в систему иксы с этими их многочисленными менеджерами всего, начинается долгий и нудный поединок с непредсказуемым результатом. Это вам не иголка в стоге сена, её хотя бы магнитом можно вытянуть. Представьте, что неизвестное количество иголок спрятаны в клубке из колючей проволоки, да ещё обильно присыпаны гвоздями. Какой там поиск иголок, не убиться бы насмерть.

Лемма: для выполнения даже самой элементарной новой функции линукс-система всегда подтянет кучу ненужных зависимостей, причём даже с «лёгкой» графикой рост системной энтропии получается кратный.

Теорема: в любом конечном наборе программных пакетов всегда найдётся бесконечно малый кусок кода, который попытается записать один бесконечно бесполезный бит на файловую систему, смонтированную в read-only, чем вызовет фатальную ошибку, повалит всю систему и перечеркнёт многочасовые усилия оператора.

Решение: UnionFS


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

Суть в том, что поверх постоянной «подложки» (read-only файловой системы на microSD) при каждом включении создаётся временная «нашлёпка» в ОЗУ, поглощающая всю ненужную энтропию и «сгорающая» при выключении питания устройства. Файловая система на microSD всё время остаётся read-only, и потому риск её повреждения снижается почти до нуля, как и риск преждевременного износа флэшки. Почему не строго до нуля? Знатоки EXT4, поправьте меня, но драйвер файловой системы всё-таки что-то записывает на носитель при каждом монтировании-демонтировании файловой системы, даже если она монтируется в read-only. И noatime не поможет.

Недостатки


Какие минусы, помимо «сгорания» логов? Устройства без аппаратных часов при старте всегда считают, что на дворе 1 января 1970 года, и пребывают в этом заблуждении вплоть до подъёма сетевого стэка и доступности NTP. Поэтому на момент данной публикации целый ряд файловых объектов «нашлёпки» будут примерно на 46 лет моложе, чем им кажется. С другой стороны, несколько секунд от начала эпохи — уже не ноль.

Обновления безопасности накатывать на такую систему довольно неудобно. Но, опять же, взломать такую Вещь несколько сложнее, чем эксплуатировать уязвимость Adobe Flash в браузере обычного десктопа.

Пошаговая инструкция


Поскольку я впервые в жизни установил Rasbian Jessie и особо не верю в долговечность microSD даже в read-only, то решил записать все шаги подробно. Вдруг понадобится повторить.

DISCLAIMER
Извините за переносы строк. Все команды запускаются с правами root, но аккуратный читатель может использовать каждый раз sudo. Честно говоря, я не понимаю, зачем каждую команду запускать через sudo, будто это защитит от чего-то. Вот скажите, когда вы в последний раз *не были* уверены, что хотите удалить данный файл в корзину? Это как выпить пять бокалов пива по пол-литра, но на дорожку ещё налейте один 0.33, пожалуйста, а то мне уже хватит… Я дам неправильный совет: если уж взялись за эти игрушки, выходите на root командой sudo bash, не занимайтесь самообманом.

1. Инициализация

Установите Raspbian Jessie Lite. Утилитой raspi-config задайте региональные настройки и пароль пользователя pi. Подключите сеть, Debian — дитя широкополосного доступа. Загрузку в графику пока не включайте.

apt-key update  apt-get update

2. Установка и удаление программ

С графикой, установка:

apt-get install --no-install-recommends tightvncserver xtightvncviewer xserver-xorg xinit lxde-core lxappearance lightdm feh xprintidle policykit-1 busybox-syslogd ntpdate watchdog unionfs-fuse

Удаление:

dpkg --purge rsyslog  apt-get remove --purge wolfram-engine triggerhappy cron anacron logrotate dphys-swapfile fake-hwclock  apt-get autoremove --purge


Пакеты tightvncserver, xtightvncviewer, xprintidle и feh понадобились мне для частной задачи, можете обойтись без них.

Если без графики, вам *не* понадобятся также: xserver-xorg xinit lxde-core lxappearance lightdm policykit-1.

3. Создание графического окружения

Теперь утилитой raspi-config можно включить автозапуск в графическом режиме с автовходом, который будет с правами пользователя pi. Чем зацикливаться на sudo, лучше поставить сильный пароль пользователю pi, и не использовать pi для автоматического входа в графический интерфейс. Вместо этого создать пользователя pu и запускать «иксы» с его правами. Причём командный интерпретатор (default shell) этого пользователя лучше либо отключить совсем (поставив /usr/sbin/nologin), либо подменить специальным скриптом типа /usr/local/bin/pu. Об этом я намерен рассказать в другой публикации, посвящённой видеотабло с удалённым управлением по SSH, ради чего и создаётся отдельная учётная запись с пониженными правами. Ещё раз благодарю Sauron et al.

adduser --home /home/pu --shell /usr/local/bin/pu --uid 990 --gecos "RPi p-u" --gid 1000 pu  mkdir -p /home/pu/.config/lxsession/LXDE  cp -p /etc/xdg/lxsession/LXDE/desktop.conf /home/pu/.config/lxsession/LXDE/desktop.conf  touch /home/pu/.config/lxsession/LXDE/autostart  chown -R pu:pi /home/pu  sed -i 's/^#\?xserver-command=.*$/xserver-command=X -s 0 -dpms -nocursor/' /etc/lightdm/lightdm.conf  sed -i 's/^#\?autologin-user=.*$/autologin-user=pu/' /etc/lightdm/lightdm.conf

Вместо двух последних команд можете открыть редактором /etc/lightdm/lightdm.conf и задать значения двух параметров, первый я уже упоминал выше, второй говорит сам за себя:

...  xserver-command=X -s 0 -dpms -nocursor  ...  autologin-user=pu  ...

4. Сторожевой таймер (по желанию)

У меня Raspberry Pi 3 Model B, поэтому ядерный модуль сторожевого таймера зовут так:

modprobe bcm2835_wdt  echo "bcm2835_wdt " | sudo tee -a /etc/modules

Затем добавляем следующую строку в секцию [Install] в конце файла /lib/systemd/system/watchdog.service:

[Install]  WantedBy=multi-user.target

После этого включаем службу:

systemctl enable watchdog.service

Сторожевой таймер в минимальной конфигурации должен сработать, если зависло ядро. Но есть ещё много других вариантов, например, по чрезмерной нагрузке на систему, по истечению памяти, по перегреву системы, по отсутствию сигнального файла и т.д. См. также watchdog(8) и watchdog.conf(5)

5. Параметры старта

Я отключил отображение малинового лого и swap-файл, включил быструю загрузку. Для этого добавил в /boot/cmdline.txt буквально три слова logo.nologo fastboot noswap. У меня в итоге получилось так:

logo.nologo dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait fastboot noswap

6. Запечатывание корневой файловой системы Raspberry Pi в read-only

Вот теперь мы добрались, наконец, до главного.

Ниже скрипт, который следует расположить под именем mount_unionfs где-нибудь в /usr/local/bin. Не забудьте включить биты выполнимости +x (chmod 755 или 555). Обратите внимание на суффиксы .orig и .rw, они должны совпадать с подготовкой (далее):

#!/bin/sh  DIR=$1  ROOT_MOUNT=$(awk '$2=="/" {print substr($4,1,2)}' < /etc/fstab)  if [ $ROOT_MOUNT = "rw" ]; then  	/bin/mount --bind ${DIR}.orig ${DIR}  else  	/bin/mount -t tmpfs ramdisk ${DIR}.rw  	/usr/bin/unionfs-fuse -o cow,allow_other,suid,dev,nonempty ${DIR}.rw=RW:${DIR}.orig=RO ${DIR}  fi

Из других инструкций я решил воспользоваться советом и сделать следующее:

insserv -r bootlogs  insserv -r alsa-utils    rm -rf /var/lib/dhcp/  ln -s /tmp /var/lib/dhcp

Графические приложения очень любят записывать в /home что-нибудь ненужное, поэтому в дополнение к /etc и /var я включил ещё и /home. Подготовим разделы к переключению в режим UnionFS (внимание на суффиксы .orig и .rw):

  cp -al /etc /etc.orig  mv /var /var.orig  mv /home /home.orig  mkdir /etc.rw /var /var.rw /home /home.rw

Наконец, файл fstab(5)

proc            /proc           proc    defaults        0       0  /dev/mmcblk0p1  /boot           vfat    ro              0       2  /dev/mmcblk0p2  /               ext4    ro              0       1  mount_unionfs   /etc            fuse    defaults        0       0  mount_unionfs   /var            fuse    defaults        0       0  mount_unionfs   /home           fuse    defaults        0       0  none            /tmp            tmpfs   defaults        0       0

7. Аудит системы и тест

Окиньте взглядом систему, уберите за собой .bash_history, всякие лог-файлы и т.д. Учтите, что они сейчас могут находиться не там, где обычно (например, в /var.orig вместо var).

Перезагрузите систему и посмотрите, что получилось. Если была допущена ошибка, есть большие шансы, что система уйдёт в single user и просто запустит консоль root. Если файловая система цела, перемонтировать её из read-only в read-write довольно просто:

mount -o rw,remount /

Если же система загрузилась нормально в read-only и выполняет все функции, поздравляю!
Это родилась Интернет-Вещь.

8. Распечатывание файловой системы

Если нужно распечатать систему, сперва верните коневую систему в состояние read-write (см. выше). Затем закомментируйте в fstab(5) строки, начинающиеся со слова mount_unionfs, после чего *обязательно* верните на место каталог /var.orig со всем содержимым (и желательно /home.orig тоже). Если не восстановить /var, потеряете базу установленных пакетов, но ведь именно ради установки обновлений безопасности командой apt-get вы только что распечатали систему, не так ли? Перед apt-get перезагрузите систему и убедитесь в её адекватности. Как запечатывать обратно, знаете;)

Альтернативы


Уважаемых читателей, которые знают готовые промышленные образы операционных систем (с поддержкой read-only) для Raspberry Pi и других одноплатных компьютеров, приглашаю делиться в комментариях. Надеюсь, с вашей помощью я смогу информационно обогатить этот раздел и других читаталей, резидентов и гостей уважаемого портала Geektimes:)

Что касается аппаратных альтернатив самому Малиновому Прогу в контексте прикладной задачи (сетевой HDMI-свисток), то я случайно наткнулся на один обзор, который, впрочем, намерен обсудить отдельно. Чисто экономически Raspberry Pi весьма выгоден, это пока главное:)

Ссылки


Make Raspbian System Read-Only
blog.pi3g.com/2014/04/make-raspbian-system-read-only

How to make RaspberryPi truly read-only, reliable and trouble-free
k3a.me/how-to-make-raspberrypi-truly-read-only-reliable-and-trouble-free

Stopping SD Card Corruption on Raspberry Pi's Raspbian
ideaheap.com/2013/07/stopping-sd-card-corruption-on-a-raspberry-pi

Raspberry Pi как информационное табло — с помощью VNC на localhost
habrahabr.ru/post/212661

*Easy Raspberry Pi Based Screensaver/Slideshow for Exhibitions/Store Front
www.instructables.com/id/Easy-Raspberry-Pi-Based-ScreensaverSlideshow-for-E
*у меня вызвал искреннее недоумение шаг 6

ECIO(TM), a powerful USB programmable single chip computer based on PICmicro microcontroller technology
www.matrixtsl.com/product.php?Prod=ECIO28P
Сколько примерно прожила загрузочная microSD в Вашей Raspberry Pi при регулярном использовании?

Проголосовало 43 человека. Воздержалось 45 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

@teleghost
карма
75,5
рейтинг 10,4
Например-программист 1-ой категории
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (16)

  • +1
    Печально это всё. У нас за два месяца работы над, вероятно, схожим проектом в трёх малинах подохли две карточки. Одна покрылась бэдами, вторая перешла в ридонли. С содроганием ожидаю момента, когда оно релизнется и будет работать автономно D:
    • 0
      всего два месяца?? я даже не подозревал, что всё настолько фигово, добавлю-ка пункт в голосовалку
  • 0
    Не знаю как для Raspberry Pi, а для микроконтроллеров проблема закрытия транзакции записи в flash-память решается например так: Детектор питания настраивается на такой порог, ниже которого в норме напряжение не должно опускаться, но при котором МК и флешка ещё должны нормально работать. Перед началом транзакции записи проверяется, не вышло ли питание за этот порог, и если вышло — начало записи откладывается до нормализации питания. При этом до завершение транзакции записи питание обеспечивается конденсаторами на плате. Если встроенного детектора нет (а в STM32 он есть) — используется внешняя микросхема монитора питания, обычно с жестко заданным порогом. Возможно в Raspberry Pi есть такой детектор? С SD-картами по-моему всё несколько сложнее чем с SPI-флешками — у них похоже есть внутренний кэш страницы с задержанной записью. Причём в тех открытых версиях стандарта, что мне попадались, команда принудительной выгрузки кэша не описаны, но она должна существовать, и её нужно выдавать при просадке питания.
    • 0
      благодарю, неплохо описано; я так понимаю, на рынке МК описанные внутренности просто must have, чтобы этот рынок не прое#@ть :)

      пока же у меня создалось ощущение, что на рынке любительских платформ для Вещей дела обстоят по-детски наивно; а что там с питанием SD-ридера в МалинПроге, я даже боюсь подумать
  • +2
    Лет 8 назад развлекался с read-only centos для небольших телефонных станций на asterisk. Помню, что монтировалось в read-only и так же в памяти всякая временная хрень. Работали по года 2 без проблем. Использовался переходник с IDE на SD. Графики конечно не было никакой.
    Но потанцевать с бубном много пришлось. Практически академию бубна закончил.
    • 0

      да, тогда UnionFS весьма сырой был

  • 0
    Наздоровье. Рад что пригодилось.
    • 0
      приветствую:)
  • 0
    Кстати, нашел тут кое-что по поводу RAM disk-а для Pi: https://www.domoticz.com/wiki/Setting_up_a_RAM_drive_on_Raspberry_Pi

    Люди запускают не инфотабло/слайдшоу а domoticz (решение для «умного дома»), но проблему решают ту же — смерть SD при продолжительном использовании. Правда не так радикально — в RAM диске всего одна папка.

    Возможно есть вариант расширить это на home папку пользователя (а также и на swap и что там еще), и при старте заполнять ее заранее заготовленной копией с SD карты.
    • 0
      + тема на форуме Распбери: https://www.raspberrypi.org/forums/viewtopic.php?f=37&t=63996
      + вариант переноса большей части FS на USB носитель (SD карта все равно требуется, т.к. Распбери загружается ислючительно с SD, но писать на SD он уже не будет, насколько я понял): http://www.instructables.com/id/Boot-the-Raspberry-Pi-from-USB/
    • 0

      про swap шутка, видимо;)

      • 0
        Я на ночь глядя уже не соображу — вроде ж есть swap файл у raspbian: http://raspberrypi.stackexchange.com/questions/70/how-to-set-up-swap-space

        P.S. Пишут что есть, включен по умолчанию
        http://raspberrypimaker.com/adding-swap-to-the-raspberrypi/
        Raspian uses a script dphys-swapfile to manage swap. The standard image includes this turned on by default. The configuration files is located at /etc/dphys-swapfile. Theonly parameter in the file is CONF_SWAPSIZE=100 which creates a 100MB swapfile in /var/swap.
        • 0

          да, но не в RAM же его

          • 0
            Хм, вроде как да — куда в RAM когда swap нужен когда RAM-а не хватает. Но и на SD ж не надо писать. Chicken and egg?

            Но если еще подумать — допустим половину RAM-а мы отрезаем под RAM disk. Когда вторая половина (та, которая так сказать «RAM RAM») переолняется — пусть свопит в первую (ту, которая «RAM disk»), чего уж там. Так что таки swap в RAM, и «это норма» :D

            Иначе прийдется совсем отключить swap. Вероятно наиболее логичный вариант, но надо нагуглить как.
            • +1
              P.S. Прочел что вообще по-хорошему для таких дел используется zRam.
  • 0
    С августа 5 малин показывают браузер круглосуточно. Пока все живы. Из настроек только отключение в конфиге journald записи логов на диск и запуск браузера surf без кеширования. Когда одна из малин помрет, буду делать как у вас, unionfs. Спасибо за статью

    У себя обошелся без дисплейного менеджера. Добавил файл /etc/systemd/system/getty@tty1.service.d/override.conf с таким содержанием:
    [Service]
    ExecStart=
    ExecStart=-/usr/bin/agetty --autologin user --noclear %I $TERM


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

    Все изменения в управляющих скриптах подготавливаю в виде deb-пакета на большой машине, затем массово заливаю и инсталирую по ssh. ssh-agent рулит

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.



Original Page: https://geektimes.ru/post/283802/



Sent from my iPad

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.