Почему подключая диск он не работает в ОС, флешка не читается системой? А сетевой интерфейс отказывается отображаться в списке устройств? Как подключить диски и настроить их работу или разрешить использовать определенный список устройств? На все эти и другие вопросы мы рассмотрим ответ, разобрав архитектуру и принцип работы с устройствами в Linux. После данного руководства вы сможете самостоятельно конфигурировать, управлять состоянием и разрешением на работу устройств в системе.
Как работает подключение дисков в Linux?
Разберем полный цикл подключения диска в Linux, для того чтобы понять, как это работает в системе. И что можно сделать для решения возникающих проблем?

Физически или виртуально подсоединяем диск к нашей системе, после чего информация о новом устройстве поступает в ядро. Происходит выбор драйвера для его работы и сбор информации об устройстве. В Linux любое устройство “представляет собой файл” и это значит, что ядро собрав информацию заносит данные в файл папки /dev. Но это не обычный файл описание подключенного устройства, а точка обращения к диску!
Программы могут открывать, читать, записывать и управлять этими файлами устройств с помощью стандартных системных вызовов, таких как open(), read(), write() и ioctl(). Эти вызовы передаются через файл устройства в драйвер устройства, который затем взаимодействует с аппаратным обеспечением через ядро.
Драйвер устройства преобразует системные вызовы в аппаратные команды, которые ядро передает устройству. Обратная связь от устройства также проходит через драйвер обратно в программу.
После чего ядро создает событие uevents управление переходит Udev, который представляет собой менеджер устройств с подготовленным набором правил. Они используются для изменение имени устройства, прав доступа от пользователей, блокирования, а так же выполнения скриптов, при подключении или отключении устройств. Если существуют критерии, по которым необходимо внести изменения, то Udev обратиться в директорию /dev и произведет необходимые действия.
Как подключить диск к Linux?
Все действия были выполнены в среде облачного сервера от Serverspace, для этого перейдем к созданию сервера, на любой из двух платформ vStack cloud или же VMware cloud. Нажмем на кнопку Создать сервер и выберем конфигурацию, подходящую под наши задачи, затем нажмем кнопку Создать:

Потребуется некоторое время для развертывания серверных мощностей. После чего вы можете подключиться любым из удобных способов. На основе предлагаемы VPS и VDS серверов, так же можно развернуть уже свою виртуальную инфраструктуру.
Теперь рассмотрим ситуацию на практике, нам необходимо подключить диск и задать ему специальное имя, запретить подключение устройств с определенным UUID, а так же выполнить скрипт для автоматизации наших задач. Это может быть что угодно: разметка нового диска, ротация старых файлов или же оповещение администратора.
Подключим диск и проведем базовые действия по его настройке: разметим и зададим файловую систему. С помощью команды lsblk рассмотрим подключенные диски:
lsblk 
Новый диск отобразился, как vdb без логических томов и разметки. Для того, чтобы начать пользоваться им необходимо создать таблицу и тома, а затем и выбрать файловую систему для логического раздела, которая будет поддерживаться ОС. После чего смонтировать диск в ОС. Для этого перейдем в утилиту fdisk и пропишем команду:
fdisk /dev/vdb 
По умолчанию, для диска создается MBR таблица, которую можно перезаписать и желательно использовать вместо нее разметку GPT. Для этого укажите букву g, после этого таблица будет пересоздана и диск заново размечен. Для создания в текущей таблице нового тома нажмем n, что позволит определить его параметры:

Выберем тип для раздела и укажем первый, и последний сектор для создания одного тома. После чего увидим результат, что был создан том на 10 Гб, осталось записать полученные изменения и сохранить с помощью команды w. Для того чтобы диск мог обрабатываться ОС необходимо инициализировать файловую систему для тома. Для этого используем утилиту mkfs.ext4:
mkfs.ext4 /dev/vdb1 
Для временного монтирования диска можем использовать команду mount, где необходимо сначала указать сам диск и точку монтирования. Но данное решение будет действовать до перезагрузки, для того, чтобы монтировать новый диск каждый раз автоматически – перейдем к папке /etc/fstab и внесем изменения:
nano /etc/fstab /dev/vdb1 /home ext4 defaults,noexec 0 2 
Для инициализации диска необходимо указать его UUID или же прямой путь в нашем случае /dev/vdb1. Для просмотра текущих дисков пропишите lsblk.

Отлично, диск смонтирован и готов к использованию! Теперь, при каждом перезапуске он будет проходить этап монтирования, однако, что если необходимо его переименовать? Или разрешить ограниченному кругу лиц?
Как управлять диском и использовать udev?
Для управления блочными, символьными устройствами используют udev утилиту, которая общается с ядром через uevent-события. Все настройки для устройств производятся в конфигурационных файлах для каждого устройства отдельно. Для того, чтобы создать символическую ссылку или ограничить доступ необходимо узнать уникальные параметры диска для поиска:
udevadm info -a -p /sys/block/vdb
Для того, чтобы составить правило необходимо найти уникальное значение для диска в данном случае это ATTR{serial} с определенным номером. Для написания правила перейдем в папку rules.d, в которой хранятся все ранее написанные алгоритмы работы с каждым из устройств. Создадим правило под названием:
nano 98-local.rulesПропишем следующий синтаксис, который сначала найдет нужное устройство, за тем применит настройки из udev rules:
SUBSYSTEM=="block", ID_SERIAL="BHYVE-2C94-9746-08F9", SYMLINK+="NewDisk"После чего сохраним файл и перезапустим службу udev:
systemctl daemon-restart && systemctl restart systemd-udevdИ проверим соответствующие параметры через команду:
udevadm test /dev/vdb1 
В файле правила udev вы можете использовать различные условия проверки, такие как:
- SUBSYSTEM: Проверяет подсистему устройства. Пример: SUBSYSTEM==”block” (устройство относится к подсистеме блоков).
- KERNEL:Проверяет имя устройства, заданное ядром. Пример: KERNEL==”sd*” (имя устройства начинается с “sd”).
- ATTR{attribute}:Проверяет атрибут устройства. Пример: ATTR{size}==”1024″ (атрибут размера устройства равен 1024).
- ENV{environment_variable}:Проверяет переменную окружения. Пример: ENV{ID_SERIAL}==”1234567890″ (серийный номер устройства равен 1234567890).
- DRIVER:Проверяет драйвер устройства. Пример: DRIVER==”usb-storage” (устройство использует драйвер usb-storage).
- ACTION:Проверяет действие, выполненное с устройством. Пример: ACTION==”add” (устройство было добавлено) или ACTION==”remove” (устройство было удалено).
- PROGRAM:Выполняет команду и проверяет её результат. Пример: PROGRAM=”/path/to/script” (выполняет скрипт по указанному пути).
- RESULT:Проверяет результат выполнения программы. Пример: RESULT==”1″ (результат выполнения программы равен 1).
- TEST:Проверяет существование файла или директории. Пример: TEST==”/path/to/file” (проверяет наличие файла по указанному пути).
Все выше перечисленные атрибуты можно использовать для фильтрации устройства. Так же для каждого из используются логические элементы, к примеру == или != в условии. После чего указываются параметры действий:
- SYMLINK+=:Создает символьную ссылку на устройство. Пример: SYMLINK+=”mydevice” (создает символьную ссылку /dev/mydevice).
- NAME=:Назначает имя устройству. Пример: NAME=”mydisk” (назначает имя устройства mydisk).
- OWNER=:Устанавливает владельца устройства. Пример: OWNER=”username” (устанавливает владельца устройства username).
- GROUP=:Устанавливает группу устройства. Пример: GROUP=”disk” (устанавливает группу устройства disk).
- MODE=:Устанавливает права доступа к устройству. Пример: MODE=”0660″ (устанавливает права доступа 0660).
- RUN+=:Запускает указанную программу или скрипт. Пример: RUN+=”/path/to/script” (запускает скрипт по указанному пути).
- IMPORT=:Импортирует переменные окружения из указанной программы или файла. Пример:
- IMPORT{program}=”/path/to/program” (импортирует переменные из программы).
- OPTIONS=:Устанавливает дополнительные опции для устройства. Пример: OPTIONS+=”last_rule” (указывает, что это последнее правило для данного устройства).
- ATTR{attribute}=:Устанавливает значение атрибута устройства. Пример: ATTR{power/control}=”auto” (устанавливает значение атрибута power/control в “auto”).
- ENV{environment_variable}=:Устанавливает значение переменной окружения. Пример: ENV{UDISKS_IGNORE}=”1″ (устанавливает переменную окружения UDISKS_IGNORE в 1).
- TEST=:Проверяет существование файла или директории. Пример: TEST==”/path/to/file” (проверяет наличие файла по указанному пути).