Информационная безопасность, программирование
0,0
рейтинг
28 августа 2013 в 21:56

Разработка → Сказ о Raspberry и внешнем HDD. Первый опыт разработки под платформу из песочницы

Доброго времени суток, Хабр! Пару недель назад зачесались руки гика — захотелось мне приобрести довольно нашумевший и всем известный одноплатный мини-компьютер Raspberry Pi. Модель была выбрана самая «крутая» — версия «B» с 512Mb ОЗУ на борту. История о покупке и первичной настройке не подходит к теме этого поста, тем более, что её можно прочитать вот здесь.

Этот пост о другом. После всех манипуляций с настройкой захотелось попробовать машинку, так сказать, «в деле». Идея возникла практически сразу. Дома у меня имеется 3 компьютера, 2 смартфона, бюджетный роутер, и внешний жёсткий диск на 2Tb — Seagate Expansion External. Интерфейс подключения у HDD — USB. Роутер из разъёмов имеет только Ethernet и дырку для шнура электропитания. Все мои устройства соединяются с роутером только по WiFi, и ни одно не может работать в постоянном режиме. Но тут появляется Raspberry. Миниатюрные размеры платы позволяют разместить систему вида [HDD<=USB=>RPi<=Ethernet=>DIR300NRU(роутер)<=WiFi=>LAN] прямо на подоконнике и использвать диск в локальной сети, а её мизерное энергопотребление позволяет держать включенной практически постоянно. RPi работает под управлением семейства ОС Linux, а именно я на неё установил Raspbian. Казалось бы, поставить сервер samba и расшарить диск… но это было бы слишком просто. Конечная задача усложнилась: необходимо делать внешний диск доступным в локальной сети, только в том случае, если мой смартфон к этой сети в данный момент подключён, иначе диск размонтировать, тем самым снижая на него нагрузку и его энергопотребление. Значит писать будем демон, и писать будем на Python. Поехали!

Первым делом, первым делом...samba!


Сначала нужно настроить самбу и железо. Цепляем хард к Малине через USB, Малину к роутеру по Ethernet. Всё включаем в розетку. Коннектимся по SSH к RPi, я использую PuTTY под Windows в качестве клиента.
В Raspbian «из коробки» нет возможности подключить NTFS-раздел диска для записи, монтируется он только как Read-Only и не пускает к себе по локальной сети.
Не беда, сейчас установим нужный драйвер:
pi@raspberrypi ~ $ sudo apt-get install ntfs-3g

Дальше нам нужно знать имя раздела для монтирования, узнаём так:
pi@raspberrypi ~ $ sudo fdisk -l

И получаем примерно такой вывод:
Disk /dev/sda: 2000.4 GB, 2000398931968 bytes
255 heads, 63 sectors/track, 243201 cylinders, total 3907029164 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0006573a

Device Boot Start End Blocks Id System
/dev/sda1 2048 409602047 204800000 83 Linux
/dev/sda2 409602048 419842047 5120000 82 Linux swap / Solaris
/dev/sda3 419842048 3907028991 1743593472 7 HPFS/NTFS/exFAT

Внешний HDD у меня имеет имя sda, раздел обзывается sda3, у вас может быть другое. Запоминаем его.
Дальше смотрим куда монтировать. По умолчанию диск автоматически монтируется в /media/Имя_тома. Я решил не заморачиваться и оставить его там. Путь к директории у меня: /media/DataR.

Теперь настраиваем сам сервер samba. Открываем файл конфигурации для записи:
pi@raspberrypi ~ $ sudo nano /etc/samba/smb.conf

Про настройку можно подробно прочитать в сети, я лишь приведу свой файл конфигурации:
[global]

workgroup = WORKGROUP
server string = RPi Fileserver
netbios name = fileserver
dns proxy = no

log file = /var/log/samba/log.%m
max log size = 1000
syslog = 0
panic action = /usr/share/samba/panic-action %d

encrypt passwords = true
passdb backend = smbpasswd
obey pam restrictions = yes
unix password sync = yes
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssucce$
pam password change = yes
map to guest = bad user

#======================= Share Definitions =======================
[ExternalHDD]
comment = HDD Seagate Expansion External 2Tb
path = /media/DataR
writable = yes
printable = no
guest ok = yes
read only = no


Настроили? Идём дальше. Проверяем работоспособность всей конструкции. Монтируем раздел (сначала размонтируем, на всякий), перезапускаем сервер samba.
pi@raspberrypi ~ $ sudo umount /media/DataR
pi@raspberrypi ~ $ sudo mount /dev/sda3 /media/DataR
pi@raspberrypi ~ $ sudo /etc/init.d/samba restart

Если ошибок не наблюдается, то пробуем найти сервер в сети. Если и тут всё нормально, то идём дальше.

Пишем скрипт


Писать будем на Python. Интерпретатор нам уже доступен предустановленным на Raspbian. Я решил писать сразу в консоли:
pi@raspberrypi ~ $ nano shrdsk.py

Что нам нужно:
  • Проверять, доступен ли IP в локальной сети
  • Выполнять системные команды
  • Ждать некоторое время
  • Зациклить всё это дело

Итак, первым делом импортируем нужные модули:
import socket as s # сократили имя
from time import sleep # функция ожидания
from os import system # функция исполнения консольных команд
from errno import * # модуль с номерами ошибок

Далее всё уместится в маленьком бесконечном цикле:
while 1:
    sock=s.socket(s.AF_INET,s.SOCK_STREAM) # открываем сокет
    try:
        sock.connect(('192.168.0.14',1001)) # пытаемся соединиться с нашим устройством, IP на нём нужно прописать статический, порт выбрать любой свободный
        system('mount /dev/sda3 /media/DataR') # коннект удался, монтируем раздел
        system('/etc/init.d/samba restart') # и расшариваем
    except socket.error, v:
        # произошла ошибка, тут 2 варианта:
        if v[0]==ECONNREFUSED: # 1 - IP существует, но отвергает соединение (НО существует же!)
            system('mount /dev/sda3 /media/DataR') # монтируем
            system('/etc/init.d/samba restart') # шарим
        else: # 2 - такого IP нет
            system('umount /media/DataR') # размонтируем
            system('/etc/init.d/samba stop') # закрываем сервер
    sock.close() # после каждого прогона закрываем за собой сокет
    sleep(60) # и ждём 60 секунд

Это минимально работоспособный вариант, но я решил его чуть модифицировать, добавив возможность настройки и вывод отладочных сообщений в консоль. Готовый вариант выглядит вот так:
# Coding: utf8
# Author: Man197
# Version: 1.0
# !!!!!!!!!!!!!!!!!!!!
# !START ME WITH ROOT!
# !!!!!!!!!!!!!!!!!!!!

###
# socket config:
HOST='192.168.0.14' # host to detect
PORT=1001 # any random port
WAITING=60 # time to wait between connections (in secs)
###
# mount config:
MOUNT=1 # do mount/umount (1/0)
DEV='sda3' # device (without "/dev/")
DIR='/media/DataR' # directory to mount
###

import socket as s
from time import sleep
from os import system
from errno import *

while (1):
        sock=s.socket(s.AF_INET,s.SOCK_STREAM)
        try:
                print "connecting..."
                sock.connect((HOST,PORT))
                print "socket ok"
                if MOUNT:
                        print "mount device"
                        system("mount /dev/%s %s"%(DEV,DIR))
                print "samba restart:"
                system("/etc/init.d/samba restart")
        except s.error, v:
                print "socket err"
                if v[0]==ECONNREFUSED:
                        if MOUNT:
                                print "mount device"
                                system("mount /dev/%s %s"%(DEV,DIR))
                        print "samba restart:"
                        system("/etc/init.d/samba restart")
                else:
                        if MOUNT:
                                print "umount device"
                                system("umount %s"%DIR)
                        print "samba stop:"
                        system("/etc/init.d/samba stop")
        sock.close()
        print "waiting..."
        sleep(WAITING)

Итоги

Получилось, что можно настроить абсолютно всё, а также отключить (раз)монтирование раздела. Осталось прописать на устройстве статический IP для подключения к нашей локальной сети и всё, своеобразный ключ доступа к диску готов! Для полной автоматизации можно добавить скрипт в автозагрузку при старте системы. Открываем системный файл rc.local:
pi@raspberrypi ~ $ sudo nano /etc/rc.local

И дописываем в него следующую строчку:
su pi -c "python /home/pi/shrdsk.py"

Путь, конечно, указываете свой.
Вот и всё, спасибо за прочтение! Это был мой первый опыт разработки под Raspberry Pi, да и под Linux вообще. Готовый файл скрипта можно загрузить с моей странички.

UPD1: спасибо, что подсказали насчёт перезагрузки и автозапуска, первое выкинул, второе поправил
Колесниченко Владислав @Man197
карма
14,0
рейтинг 0,0
Информационная безопасность, программирование
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

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

  • +4
    Если только по какому-то недоразумению диск не должен быть съёмным — переформатируйте его во что-нибудь нормальное.
    ntfs-3g легко положит и куда более мощное железо. А с нормальной ФС малинка вытянет почти всю свою 100мбит/с сеть.

    su pi -c «sudo python /home/pi/shrdsk.py»
    Что за странное нагромождение? rc.local уже от рута выполняется.

    А если некритична небольшая задержка при первом открытии шары — можете на самбу старт и повесить. См. опцию preexec
    • 0
      Спасибо за уточнения и правки, я сам новичок ещё в линуксе, о некоторых вещах не осведомлен:) Кстати, что за такие «нормальные» ФС?
      • 0
        EXT
        • 0
          Против EXT есть 3 аргумента — машины под маздаем. Насколько я знаю, оттуда нормально таким диском не воспользуешься.
          • +3
            Неправда.
            • 0
              Read-Only же вроде, нет? Буду рад, если подскажете решение!
              • 0
                Не нужно ничего решать. Всё просто работает. С чего Вы взяли, что будут какие-то проблемы?
                • +1
                  Windows не видит EXT-разделы. EXT4, точнее.
                  • +2
                    Как это связано с раздачей каталога по сети через CIFS? Вы что, блочное устройство раздаёте? Ну подумайте хоть чуть-чуть же.
                    • +1
                      Диск планируется таскать с собой, не только постоянно держать на этом самом подоконнике. Вот на даче, например, WinXP стоит. Если я своим старикам линь там накачу, то у них голова совсем лопнет. Рядом ставить линь не вариант.
                      • +3
                        Зря. Как раз с линуксами им было бы проще.
                  • +1
                    Проблема будет если диск напрямую подключите к пк. И то есть костыли, чтобы в win читать и писать на ext
              • 0
                Есть драйвер, но его надо ставить.
  • +1
    Следующий топик будет о медленной работе Самбы?))
    А ведь она там не медленная, а очень медленная + питание внешнего hdd желательно внешнее сделать.
    • 0
      Так оно и внешнее, шнурок в розетку втыкается:)
      Со скоростью проблемы есть, да… но дело-то больше в идее, новое — интересное.
  • +2
    Перезагрузка не нужна. Более того, неясно, зачем Вам питон, если Вы в каждой строке шелл зовёте. Почему не написать сразу на нём?
    • +1
      Окна научили, ставишь драйвер — перезагрузись, на всякий:) Спасибо, учту. А с шеллом у меня сразу как-то не заладилось. Базовые команды знаю, а вот программировать… питон теплее и уютнее.
      • +3
        Глупости, для трёх команд городить питон — не комильфо, причём совсем.
  • 0
    Зачем размонтировать? Тогда уж реле на отключение поставить еще :)
    hd-idle. Или бывает USB часть сама отключает кручение по тайм-ауту.

    Raspberry Pi дешев, но медленновато, 1.7 Mbyte/s по самбе удавалось вытянуть (ext, не ntfs!).
    В итоге купил cubieboard2, с разъемом SATA и отдельной микросхемой ethernet. Прирост есть, но не какой хотелось бы (около 3 Mbyte/s).
    • 0
      Странно, что так мало. Rpi подключен через провод к роутеру. По воздуху телефон подключен к роутеру. Скорость копирования на смартфон с rpi 2мбайта/с. При этом у меня на rpi-hdd файловая система ntfs, а не ext
      • 0
        Возможно разница в USB переходнике с SATA
  • +3
    while true; do ping -c 3 192.168.0.14 > /dev/null && /sbin/mount /dev/sda3 /media/DataR || /sbin/umount /media/DataR; sleep 30s; done
    
    • 0
      Самое простое и быстрое. Прекрасно. Только, конечно, надо на роутере телефону статик ip прописать.
  • 0
    Про xinetd не слышали? Как раз бы подошло.
    Но написать самому конечно веселее )
    • 0
      Спасибо за наводку, почитаю про эту штуку:)

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