Увеличиваем потенциал брошенного производителем сетевого хранилища

в 18:12, , рубрики: armel, Debian, dns-325, embedded, nginx, omv, openmediavault, u-boot, uart, Настройка Linux, резервное копирование, хранилища данных

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

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

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

image

Для нетерпеливых: в конце получился полноценный аппарат с актуальной версией загрузчика U-Boot, image Debian Jessie и image OpenMediaVault на борту.

Содержание:

  1. Устройство
  2. Подготовка устройства
  3. Сборка и обновление
  4. Установка и настройка
  5. Заключение

Устройство

Встречайте подопытного — D-Link DNS-325.

image

На устройстве установлен ARM процессор Marvell Kirkwood 88F6281 (EABI) архитектуры armel, NAND память на 128MB, RAM на 256MB. Оснащен двумя отсеками для HDD, сетевым и USB разъемом на задней панели.

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

Глюки

В порядке убывания важности:

  1. Глюки UPnP AV медиа сервера. На хранилище настроен медиа сервер, который индексирует аудио и видео материалы и раздает их по DLNA протоколу. Проблема в том, что некоторые файлы, добавляемые на жесткий диск, не индексируются автоматически и не отображаются при заходе с телевизора/другого DLNA совместимого устройства. Помогает ручное переключение режима медиа сервера, тогда база создается с нуля, но это занимает пару часов. Не самое лучшее решение, когда хочется скачать и посмотреть фильм.

  2. Внезапное пробуждение из состояния "сна" посреди ночи (шуршание диском, шум вентилятора) создает дискомфорт. И ни строчки в логе о том, какая же сервисная задача запустилась. Только событие запуска вентилятора:
    Apr 20 03:55:09 Set Fan Speed To "LOW".

  3. Веб-интерфейс. Наблюдаются зависания, отвалы сессии, и т. п.

  4. Дополнения. Есть как официальные, так и неофициальные. Проблема в том, что никто не занимается поддержанием актуальности ПО. В таком виде исправления ошибок и уязвимостей ждать также не стоит.

  5. Система логирования просто ужасна. Мало того, что она малоинформативна, так еще и с какими-то мифическими артефактами.

  6. Linux. Как в основе многих современных кофеварок встраиваемых устройств, в основе лежит Linux. А это значит, что рядом стоят вопросы стабильности, уязвимостей и т. д. В стоковой прошивке крутится ядро Linux 2.6, а на дворе уже Linux 4.11.

  7. Странный баг с USB принтером. Хранилище оснащено USB портом для подключения флешек, USB дисков, принтеров и сканеров. И мой USB принтер отлично расшаривался по сети, пока внутри был установлен 1 HDD на 2 TB. Как только я вставил в правый кейс HDD на 3 TB, принтер переставал работать. После ряда тестов с различными комбинациями различных дисков я выяснил, что работает он только с одним, установленном в левом кейсе.

Выбор альтернативной ОС

Alt-F

Первым, что нашлось из адаптированных альтернатив, стала открытая прошивка Alt-F. Функционал не уступает фирменной прошивке, минималистичный веб-интерфейс, обновления выходят стабильно. Даже есть поддержка плагинов fun_plug.

image FreeNAS и image NAS4Free

Проекты интересные, но громоздкие. Основаны на FreeBSD. Слишком высокие системные требования.

Вот, например, системные требования для FreeNAS 10 "Corral":

  • процессор с поддержкой 64-bit
  • система с поддержкой загрузки через legacy BIOS или EFI
  • 8 GB RAM
  • 8 GB USB флешка или другой накопитель
  • хотя бы один диск для хранения данных
  • порт Ethernet для сетевого обмена

Кстати, недавно релиз FreeNAS 10 "Corral" отозвали, в т.ч. и по причине повышения системных требований.

image OpenMediaVault

OMV — система для NAS с открытым исходным кодом. Является ответвлением от FreeNAS, но адаптированного под Debian Linux, в следствие чего мультиплатформенна. В сочетании с относительно невысокими системными требованиями делает себя единственным подходящим кандидатом. Функционал более чем достаточный, расширяемый своими плагинами, но самое главное, что полноценный Debian дает доступ к репозиториям, а значит можно поставить все что угодно установкой пары пакетов.

Для данной модели есть несложный способ запустить Debian с помощью хака с fun_plug, но это всего лишь real-time расширение, к тому же не удастся запустить Debian версии старше Wheezy.

К сожалению, у OMV нет готовой сборки Debian со своим пакетом для архитектуры armel. Более того, разработчики пока признают стабильными только i386 и amd64 сборки. Поддержка ARM экспериментальная:

Support for OpenMediaVault on Arm is experimental. In most situations you will need to determine how to install Debian Wheezy on you device.

Подготовка устройства

Встроенная NAND память не подходит для нашей задумки — слишком маленькая. Хранить систему на вставляемых в хранилище дисках желания нет совсем. Получится смешивание мозгов устройства с периферийными составляющими. А если я захочу диск поменять, или он сломается?

Остался единственный адекватный вариант — установить USB-флеш-накопитель, на котором и будет установлена вся система. При таком подходе проще делать резервные копии системы, а флешку в случае поломки легко заменить.

Для USB устройств было решено взять отдельный USB Network Hub, все равно одного слота нехватает :)

Дополнительное железо

Для доступа к мозгам из вне на плате есть последовательный UART порт. Вместо того, чтобы перепрошивать ROM специальными программаторами, можно подключиться к контактам на плате и через специальный преобразователь общаться с устройством через эмулятор терминала.

Тема UART во встраиваемых устройствах довольно обширна, кому интересно, можете прочесть хорошую обзорную статью: https://geektimes.ru/post/253786/

Были выбраны и куплены следующие комплектующие:

  • Преобразователь USB — UART на PL2303HX
  • Провода "мама-мама" 20см, 20 шт.
  • Вилка штыревая PLS-40 (DS1021-1x40), прямая черная
  • SanDisk Ultra Fit USB 3.0 16GB

Подключение преобразователя

Вскрываем устройство, достаем плату

image

Ищем UART порт (4 пина слева)

image

Распиновка такая (в обратном порядке): { RXD, (пусто), 3.3v, GND, TXD }

Припаиваем вилку, вставляем провода

image

Собираем корпус, оставляем снятой только крышку

image

Теперь для доступа к встроенному микрокомпьютеру не надо будет доставать плату — провода уже выведены, останется снять переднюю крышку сетевого хранилища.

Так как это последовательный порт, то и соединяем последовательно.

RX на TX, TX на RX

image

На этом вся механическая работа с оборудованием закончена.

Пробный запуск

Для общения по протоколу UART нам понадобятся:
kwboot — утилита для запуска загрузчика на устройстве "на лету"
minicom — эмулятор терминала для UART протокола

Запускаем minicom на хост системе:

# minicom -D /dev/ttyAMA0 -b 115200 -8

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

Лог загрузки

** MARVELL BOARD: DB-88F6281A-BP LE 

U-Boot 1.1.4 (Jan 21 2011 - 09:42:39) Marvell version: 3.4.14.DNS-325.02

U-Boot code: 00600000 -> 0067FFF0  BSS: -> 006CEE80

Soc: MV88F6281 Rev 3 (DDR2)
CPU running @ 1200Mhz L2 running @ 400Mhz
SysClock = 400Mhz , TClock = 200Mhz

DRAM CAS Latency = 5 tRP = 5 tRAS = 18 tRCD=6
DRAM CS[0] base 0x00000000   size 256MB
DRAM Total size 256MB  16bit width
Flash:  0 kB
Addresses 8M - 0M are saved for the U-Boot usage.  
Mem malloc Initialization (8M - 7M): Done
NAND:128 MB

***

NAND read: device 0 offset 0x100000, size 0x300000
load addr ....  =a00000

 3145728 bytes read: OK

NAND read: device 0 offset 0x600000, size 0x300000
load addr ....  =f00000

 3145728 bytes read: OK 
## Booting image at 00a00000 ...
   Image Name:   Linux-2.6.31.8
   Created:      2012-06-26   3:38:43 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2565784 Bytes =  2.4 MB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
OK
## Loading Ramdisk Image at 00f00000 ...
   Image Name:   Ramdisk
   Created:      2014-01-21   4:33:41 UTC
   Image Type:   ARM Linux RAMDisk Image (gzip compressed) 
   Data Size:    1581012 Bytes =  1.5 MB
   Load Address: 00e00000
   Entry Point:  00e00000
   Verifying Checksum ... OK

Starting kernel ...                                                             

Uncompressing Linux.............................................................
**Linux version 2.6.31.8** (jack@swtest6) (gcc version 4.2.1) #8 Tue Jun 26 11:38:42
CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977
CPU: VIVT data cache, VIVT instruction cache
Machine: Feroceon-KW
Using UBoot passing parameters structure
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 65024
Kernel command line: root=/dev/ram console=ttyS0,115200 :::DB88FXX81:egiga0:none
PID hash table entries: 1024 (order: 10, 4096 bytes) 
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 256MB = 256MB total
Memory: 246528KB available (4828K code, 323K data, 136K init, 0K highmem)

***

NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-b)
Scanning device for bad blocks
Using static partition definition
Creating 6 MTD partitions on "nand_mtd":
0x000000000000-0x000000100000 : "u-boot"
0x000000100000-0x000000600000 : "uImage"
0x000000600000-0x000000b00000 : "ramdisk"
0x000000b00000-0x000007100000 : "image"
0x000007100000-0x000007b00000 : "mini firmware"
0x000007b00000-0x000008000000 : "config"

Если интересно, вот полный вывод:
https://pastebin.com/6SRA6Qgq

Сборка и обновление

Все действия по сборке будут проводиться на основной (хост) системе под управлением Debian Stretch (amd64).

Собирать и обновлять будем:

  1. Загрузчик — U-Boot
  2. Ядро — Linux Kernel 4.10
  3. Корневую файловую систему Debian Jessie
  4. Образ начальной инициализации системы — Initramfs

Основные инструменты для сборки:

  1. Кросс-компилятор для armel архитектуры. В Debian это пакет gcc-arm-linux-gnueabi
  2. Вспомогательные утилиты:
    • git — для скачивания нужных версий с репозиториев проектов
    • make — для выполнения сборочных скриптов
    • debootstrap — для скачивания корневой файловой системы
    • mkimage — утилита для переформатирования файлов в формат, понятный загрузчику
    • BusyBox — набор утилит для начальной инициализации системы
    • сопутствующие зависимости и библиотеки.

Загрузчик

В данном устройстве установлен немного урезанный загрузчик U-Boot 2011 года. Обновлять будем до актуальной стабильной версии.

Скачиваем:

$ git clone --branch v2017.05 git://git.denx.de/u-boot.git

Настраиваем:

$ cd u-boot
$ nano u-boot/include/configs/dns325.h

Добавляем строки:
#define CONFIG_CMD_BOOTZ — для поддержки загрузки zImage ядра.
#define CONFIG_CMD_EXT4 — для поддержки ФС ext4 и связанных команд консоли загрузчика.

$ make dns325_defconfig
#
# configuration written to .config
#
$ make u-boot.kwb CROSS_COMPILE=arm-linux-gnueabi-

На этом этапе нужно знать, сколько весит этот файл:

$ printf "0x%xn" `stat -c "%s" u-boot.kwb`
0x7315c

Выводим размер образа в шестнадцатеричной системе счисления (HEX), в таком виде он пригодится при записи в NAND память.

Записать полученный образ U-Boot в NAND память можно из работающего в памяти загрузчика. Я решил не делать это из текущего стокового загрузчика, так как хотелось сначала убедиться, что новый образ вообще загрузится на железе, да и поддержка ext4 была включена ранее в новом образе загрузчика, так что можно сделать финт ушами: скопировать этот образ на флешку и загрузить с этого же образа при помощи kwboot.

Есть несколько вариантов, как передать файл в память миникомпьютера: через Kermit, через TFTP, а также через физически подключенные накопители (наш выбор).

kwboot позволяет запустить плату с передаваемым ей загрузчиком, не записывая ничего физически (только в RAM) и вообще игнорируя NAND память. Этот механизм позволяет аварийно загружать устройство даже когда оно окирпичилось в следствие порчи NAND памяти или неудачной прошивки.

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

Заливка и загрузка

# tools/kwboot -p -b u-boot.kwb -B115200 -t /dev/ttyUSB0
Sending boot message. Please reboot the target.../
Sending boot image...
  0 % [......................................................................]
  1 % [......................................................................]
  3 % [......................................................................]
***
 96 % [......................................................................]
 98 % [...........................................]
[Type Ctrl- + c to quit]


U-Boot 2017.05-dirty (May 10 2017 - 02:56:44 +0300)
D-Link DNS-325

SoC:   Kirkwood 88F6281_A1
DRAM:  256 MiB
WARNING: Caches not enabled
NAND:  128 MiB
In:    serial
Out:   serial
Err:   serial
Net:   egiga0
IDE:   ide_preinit failed
Hit any key to stop autoboot:  0 
=>

Загрузились. Далее надо записать наш u-boot.kwb образ в область NAND. Но чтобы записать его в NAND память, надо сначала считать его и записать в RAM память.

Делаем ext4 флешку и даем разделу имя "rootfs" (чтобы монтировать корневую ФС по имени раздела):

# mkfs.ext4 /dev/sdb1
# e2label /dev/sdb1 rootfs

Копируем файл на флешку, вставляем флешку в NAS и инициализируем ее:

=> usb start                 
starting USB...
USB0:   USB EHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found

Записываем образ в память. Адрес (смещение) не имеет значения, главное не выходить за пределы RAM). В данном случае будет 0x1000000.

=> ext4load usb 0:1 0x1000000 /u-boot.kwb
471388 bytes read in 77 ms (5.8 MiB/s)

Очищаем область NAND, в которой хранится загрузчик:

=> nand erase 0x000000 0x7315c

NAND erase: device 0 offset 0x0, size 0x7315c
Erasing at 0x60000 -- 100% complete.
OK

(с начала NAND памяти до смещения, равного размеру файла, который мы высчитали ранее)

Записываем загрузчик из области RAM памяти в область NAND памяти:

=> nand write 0x1000000 0x000000 0x7315c 

NAND write: device 0 offset 0x0, size 0x7315c
 471388 bytes written: OK

0x1000000 — откуда читаем в RAM
0x000000 — куда записываем в NAND
0x73044 — размер

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

U-Boot 2017.05-dirty (May 10 2017 - 02:56:44 +0300)
D-Link DNS-325

SoC:   Kirkwood 88F6281_A1
DRAM:  256 MiB
WARNING: Caches not enabled
NAND:  128 MiB
In:    serial
Out:   serial
Err:   serial
Net:   egiga0
IDE:   ide_preinit failed
Hit any key to stop autoboot:  0       
=>

Если на данном этапе устройство окирпичилось и отказалось загружаться, например как сначала получилось у меня (видимо, опечатался, когда вводил размер образа загрузчика при записи из RAM памяти в NAND), не спешите паниковать. Вы также можете загрузить устройство при помощи kwboot и повторить запись.

Корневая система (этап первый)

Воспользуемся инструментом debootstrap. Обычно формирование rootfs для систем с другой архитектурой делается в 2 этапа: скачивание в каталог с флагом --foregin, а потом настройка qemu и запуск в нем "debootstrap --second-stage". Мне не хотелось возиться с qemu и я решил делать второй этап сразу на работающем NAS-е.

Скачиваем содержимое на флешку (примонтирована в /mnt/usb/):

# debootstrap --variant=minbase --foreign --arch=armel --include=dbus,nano jessie /mnt/usb/ http://ftp.ru.debian.org/debian/ 

Переименуем на время init файл, чтобы наполовину установленая система не запустилась:

# mv /mnt/usb/sbin/init /mnt/usb/sbin/init.bak

Первый этап готов.

Ядро

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

Сначала мне посчастливилось найти уже готовое ядро для Kirkwood, но оно всячески отказывалось монтировать флеш накопитель в любом из режимов (OHCI, EHCI), так что все равно пришлось собирать ядро самостоятельно.

Скачивание:

$ git clone --branch v4.10 git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git

Загружаем предустановленный конфиг для нашей платы (ARMv5). В моем случае это mvebu_v5_defconfig.

$ make ARCH=arm mvebu_v5_defconfig
#
# configuration written to .config
#
$ make ARCH=arm menuconfig

Настраиваем. Настраивать и проверять нужно все, в идеале изучить каждый параметр и решить, нужен он или нет. Мной был выставлен hostname, включена поддержка initramfs/initrd, отключена поддержка звука и USB 3.0, отключены драйвера для ext2 и ext3 (драйвер ext4 умеет монтировать все ранние версии), включены дисковые квоты, включена поддержка плат Kirkwood, Marvell Orion. Также включены обязательные параметры для поддержки systemd. Скорее всего, есть есть что-то, чего я не упомянул, ибо настроек много. Вот мой конфиг ядра: https://pastebin.com/MZrRXnXX

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

Сборка:

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j5 zImage kirkwood-dns325.dtb

Получили само ядро zImage и файл kirkwood-dns325.dtb. Последний файл — Device Tree — нужен для правильной работы ядра конкретно с нашей платой.

Копируем эти файлы в каталог /boot на флешке:

# cp arch/arm/boot/zImage arch/arm/boot/dts/kirkwood-dns325.dtb /mnt/usb/boot/

Initramfs

Далее делаем легковесный образ, который будет загружаться в память и инициализировать нашу систему. Его делать вовсе необязательно, загрузчик умеет напрямую стартовать ядро с указанием корневого каталога (root=). Однако полезно, т. к. в случае отсутствия доступа к корневой ФС будет доступна консоль с минимальным набором команд.

Костяк образа составит джентльменский набор BusyBox.

Скачивание:

$ git clone --branch 1_26_2 git://git.busybox.net/busybox/

Настройка:

$ make defconfig
$ make menuconfig

Единственное, что лучше выставить в настройках дополнительно — это статическая линковка библиотеки glibc, чтобы не пришлось запихивать его отдельно в образ.

Статическая линковка glibc

image

Сборка:

$ make ARCH=arm

Далее создаем структуру образа, помещаем в него busybox:

$ mkdir -p initramfs/{bin,sbin,etc,proc,sys,newroot,usr/{bin,sbin}}
$ cp busybox/bin/bisybox initramfs/bin
$ ln -s initramfs/bin/busybox initramfs/bin/sh

Далее необходимо написать init скрипт. Именно тут будет происходить вся магия по инициализации устройств и передаче управлению Debian-у.

init скрипт

#!/bin/sh

/bin/busybox --install -s

#Mount things needed by this script
mount -t proc proc /proc
mount -t sysfs sysfs /sys

#Disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk

#Clear the screen
clear

#Create device nodes
mknod /dev/null c 1 3
mknod /dev/tty c 5 0

#Pause bebore USB Storage init
sleep 3

#Mount devices
mdev -s

#Defaults
init="/sbin/init"

#Mount the root device
mount LABEL=rootfs /newroot

#Check if $init exists and is executable
if [ -h  "/newroot/${init}" ] ; then
    #Unmount all other mounts so that the ram used by
    #the initramfs can be cleared after switch_root
    umount /sys /proc

    #Switch to the new root and execute init
    exec switch_root /newroot "${init}"
fi

#This will only be run if the exec above failed
echo "Failed to switch_root, dropping to a shell"
exec setsid sh
exec <"${console}" >"${console}" 2>&1
exec sh

Пакуем и преобразуем в понятный для U-Boot-а формат:

$ cd initramfs/
$ find . | cpio -H newc -o > ../initramfs.cpio
$ cd ..
$ cat initramfs.cpio | gzip > initramfs.igz
$ mkimage -n 'uInitramfs' -A arm -O linux -T ramdisk -C gzip -d initramfs.igz initramfs.uImage

Копируем initramfs:

# cp initramfs.uImage /mnt/usb/boot/

Со сборкой закончили.

Установка и настройка

Переменные окружения загрузчика

В процессе обновления загрузчика затерлись конфиги, надо настроить загрузку нового ядра, Initramfs, Device Tree, также восстановить настройки сети.

Загружаемся с minicom, выполняем на устройстве в консоли U-Boot:

=> setenv console ttyS0,115200
=> setenv bootargs console=${console}
=> setenv bootcmd usb start; run load_kernel; run load_init; run load_dtree; run boot_system
=> setenv load_kernel ext4load usb 0:1 0x1000000 boot/zImage
=> setenv load_init ext4load usb 0:1 0x1800000 boot/initramfs.uImage
=> setenv load_dtree ext4load usb 0:1 0x2000000 boot/kirkwood-dns325.dtb
=> setenv boot_system bootz 0x1000000 0x1800000 0x2000000
=> setenv ethaddr xx:xx:xx:xx:xx:xx
=> setenv ipaddr 192.168.0.32
=> saveenv

Тут все предельно просто: выставляем параметры консоли, загрузки ядра, прописываем куда будут копироваться (ext4load) в память файлы и откуда считываться (bootz). Прописываем ip и mac адреса (mac адрес можно посмотреть на наклейке устройства).

Вставляем флеш накопитель в NAS, перезагружаемся.

Корневая система (этап второй)

Загрузившись, попадаем в BusyBox. Можем завершить формирование rootfs:

# chroot /newroot
# mv /sbin/init.bak /sbin/init
# /debootstrap/debootstrap --second-stage
# passwd

Перезагружаем устройство, логинимся под root-ом. С этого момента мы загружаемся полностью и работаем в Debian-е.

Настройка сети

Далее следует настроить и включить сеть.

# touch /etc/systemd/network/wired.network
# nano /etc/systemd/network/wired.network

Пишем простой конфиг для статического ip на проводном интерфейсе eth0
[Match]
Name=eth0

[Network]
Address=192.168.0.32/24
Gateway=192.168.0.1

Включаем и запускаем сетевые службы

# systemctl enable systemd-networkd
# systemctl enable systemd-resolved
# systemctl start systemd-networkd
# systemctl start systemd-resolved

Сеть есть.

Настройка вентилятора и кнопок

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

В случае с домашним NAS так делать не стоит, ибо основную долю тепла выделяют жесткие диски, а не процессор.

Проблема вот в чем: fancontrol, служба которая занимается контролем вентилятора, позволяет следить только за датчиками, находящимися непосредственно на плате. На данном устройстве установлен один вентилятор и один датчик температуры.

Выход есть: можно обмануть fancontrol, заставив его считывать информацию из нужного нам места. Для считывания данных с HDD используем пакет smartmontools.

Устанавливаем:

# apt install fancontrol lm-sensors smartmontools

Настраиваем по умолчанию:

# pwmconfig

Тонкости настройки можно почитать, например, здесь.

Далее открываем конфиг /etc/fancontrol, смотрим содержимое. Интересна переменная "FCTEMPS" — она ставит в соответствие устройству место, откуда следует брать температуру:
FCTEMPS=hwmon0/pwm1=hwmon1/temp1_input

Путь относительный, сам файл генерируется в /sys/class/hwmon/hwmon1/temp1_input. Посмотрим в каком формате хранится информация:

# cat /sys/class/hwmon/hwmon1/temp1_input 
41500

Значение в цельсиях, умноженное на 1000 (для точности). Значит нужен файл, в котором периодически будет обновляться значение температуры жестких дисков. Значение допускается одно, а жеских дисков у нас может быть 2. Значит, будем считать максимальное, записывать в файл.

Напишем небольшой скрипт:

#!/bin/bash

while sleep 60
do
    TEMP1=`smartctl -A /dev/disk/by-id/ata-Hitachi_HDS723030ALA640_MK0311YHG1ZGJA | grep Temperature_Celsius | awk '{print $10 "000"}'`
    TEMP2=`smartctl -A /dev/disk/by-id/ata-WDC_WD2003FYYS-02W0B1_WD-WMAY05168428 | grep Temperature_Celsius | awk '{print $10 "000"}'`
    echo $(( $TEMP1 > $TEMP2 ? $TEMP1 : $TEMP2 )) > /etc/temp_hdd
done

Каждую минуту считывается S.M.A.R.T. информация с датчиков HDD, из всей информации выделяется только значение температуры, и в нужном формате наиболшее из 2-х записывается в файл /etc/temp_hdd. Диски я указал по id, потому что буквы дисков /dev/sd[a-z] могут меняться в зависимости от порядка и кол-ва вставленных физических дисков.

Записываем скрипт в /etc/temp_hdd.sh. Дальше нужно его каким-то образом запускать при старте. Для этого как раз подойдет файл /etc/rc.local

Прописываем прямо перед "exit 0" строчку
/etc/temp_hdd.sh &

Теперь процесс будет запускаться при старте системы и выполняться в фоне.

Когда есть файл с актуальной температурой, впишем это в конфиг /etc/fancontrol, настроив при этом граничные значения температуры. Получилось как-то так:

# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon0=devices/platform/gpio_fan hwmon1=devices/platform/ocp@f1000000/f1011000.i2c/i2c-0/0-0048
DEVNAME=hwmon0=gpio_fan hwmon1=lm75
FCTEMPS=hwmon0/pwm1=/etc/temp_hdd
FCFANS= hwmon0/pwm1=hwmon0/fan1_input
MINTEMP=hwmon0/pwm1=45
MAXTEMP=hwmon0/pwm1=55
MINSTART=hwmon0/pwm1=4
MINSTOP=hwmon0/pwm1=0

Реакцию на кнопки настроить гораздо проще. Устанавливаем пакет esekeyd и настраиваем:

# apt install esekeyd
# nano /etc/esekeyd.conf

Ставим команды на выключение и перезагрузку:

POWER:/sbin/shutdown -h now
RESTART:/sbin/reboot

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

Установка OMV

Добавим репозиторий OMV и установим основной пакет:

# echo "deb http://packages.openmediavault.org/public erasmus main" > /etc/apt/sources.list.d/openmediavault.list
# apt update
# apt install openmediavault-keyring
# apt install openmediavault

Дальше apt предложит устрановить много пакетов (у меня 457), устанавливаем. В процессе установки будет задано несколько вопросов по настройке пакетов, можно везде оставлять дефолт.

В конце apt может сообщить об ошибке настройки collectd и nginx:

dpkg: dependency problems prevent configuration of openmediavault:
 openmediavault depends on collectd (>= 5.1.0); however:
  Package collectd is not configured yet.
 openmediavault depends on nginx (>= 1.6.2); however:
  Package nginx is not configured yet.

Для nginx надо убрать в файле /etc/nginx/sites-available/default строчку
listen [::]:80 default_server;
Такое происходит в случае невозможности использовать IPv6 протокол.

Для collectd надо добавить строчку с hostname и ip в /etc/hosts. В нашем случае
127.0.1.1 dns325

Исправляем зависимости:

# apt install -f

Скрипт рапортует об успешной установке пакета. Запускаем скрипт инициализации:

# omv-initsystem

Все! Система установлена. Дальше заходим в веб панель по адресу 192.168.0.32, настраиваем все окружение по вкусу.

image

Заключение

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

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

На момент написания статьи устанавливался OpenMediaVault 3.x ("Erasmus"), который еще не вышел из статуса бета-версии. Это означает, что возможны баги в работе, однако связаться с разработчиками OMV намного проще, чем пытаться достучаться по почте до производителя D-Link.

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

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

Enjoy Embedding!

Автор: dudinroman

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js