Сказ о 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 ~ $ reboot

После перезагрузки придётся переконнектитьться по SSH. Дальше нам нужно знать имя раздела для монтирования, узнаём так:

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 "sudo python /home/pi/shrdsk.py"

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

ссылка на оригинал статьи http://habrahabr.ru/post/191760/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *