Подключаешь флешку или внешний диск к машине под управлением Linux, а он не появляется сам собой в привычном месте, и приходится монтировать вручную. На рабочем столе с графической оболочкой эту заботу берёт на себя специальный демон, но на сервере, в минималистичной системе или на встраиваемом устройстве такого помощника нет. Здесь на сцену выходит механизм udev, который замечает появление устройства в системе и способен запустить нужное действие в ответ. Настроив его правила с умом, можно добиться, чтобы внешний накопитель монтировался автоматически в удобный каталог с понятным именем.
Звучит просто, но дьявол прячется в технических деталях реализации. Наивная попытка смонтировать диск прямо из правила udev оборачивается странными сбоями, потому что механизм устроен не так, как кажется на первый взгляд. Разобраться в этих подводных камнях, и прежде всего в проблеме состязания процессов, значит получить надёжное автомонтирование вместо капризного, которое работает через раз.
Как udev замечает устройство и запускает действие
Механизм udev живёт в пространстве ядра и пользователя одновременно, отслеживая события подключения и отключения оборудования. Когда в систему добавляется блочное устройство вроде раздела на флешке, udev генерирует событие и проверяет, не подходит ли оно под какое-нибудь из заданных правил. Правила лежат в специальном каталоге и обрабатываются в порядке числовых префиксов в именах файлов, поэтому пользовательские правила обычно называют с высоким номером, чтобы они шли последними.
Каждое правило состоит из условий слева и действий справа. Условия отбирают нужное устройство по подсистеме, имени, типу файловой системы и прочим признакам, а действия предписывают, что с ним сделать. Простейшее правило для отбора первого раздела внешнего диска с определённой файловой системой выглядит так.
SUBSYSTEM=="block", KERNEL=="sd?1", ACTION=="add", ENV{ID_FS_TYPE}=="vfat", RUN+="/usr/local/bin/usb-mount.sh %k"
Здесь условие по подсистеме отбирает блочные устройства, шаблон имени ловит первый раздел любого диска вроде первого или второго, условие действия срабатывает только при подключении, а проверка типа файловой системы ограничивает правило нужным форматом. Действие запуска вызывает вспомогательный сценарий, передавая ему имя устройства через подстановку. После любой правки правил их перечитывают, чтобы изменения вступили в силу.
sudo udevadm control --reload-rules
sudo udevadm trigger
Первая команда заставляет udev перечитать файлы правил, вторая искусственно генерирует события для уже подключённых устройств, чтобы проверить правило без переподключения железа.
Почему монтировать прямо из правила нельзя
Здесь кроется главный подводный камень всей затеи. Современный udev устроен так, что убивает долгоживущие процессы, порождённые директивой запуска, считая их зависшими. Монтирование, особенно сетевого или медленного устройства, может занять заметное время, и udev обрывает его на полпути. В результате диск то монтируется, то нет, а в журнале остаются загадочные обрывки. Прямой запуск команды монтирования из правила это классическая ошибка, ведущая к нестабильному поведению.
Правильное решение состоит в том, чтобы правило не выполняло монтирование само, а лишь поручало эту работу системному менеджеру служб, который живёт по своим правилам и не убивает долгие задачи. Правило запускает службу, а уже служба спокойно монтирует диск в своём темпе, не опасаясь быть прерванной. Это разрывает порочную связь между коротким жизненным циклом процессов udev и длительностью монтирования.
SUBSYSTEM=="block", KERNEL=="sd?1", ACTION=="add", ENV{ID_FS_TYPE}=="vfat", RUN+="/usr/bin/systemctl start external-mount@%k.service"
Здесь правило вместо прямого монтирования запускает шаблонную службу системного менеджера, подставляя имя устройства в её параметр. Служба описывается отдельно и содержит саму логику монтирования. Такой подход стал фактически стандартным способом обойти ограничение udev на долгие процессы, и именно его рекомендуют в современных руководствах.
Как добиться понятных и предсказуемых путей монтирования
Вторая практическая забота это куда монтировать диск, чтобы потом легко его находить. Монтировать всё подряд в один фиксированный каталог неудобно, ведь при подключении второго накопителя возникнет конфликт. Гораздо дружелюбнее собирать путь из метки тома или его уникального идентификатора, чтобы каждый диск оказывался в своём предсказуемом каталоге.
Вспомогательный сценарий, который вызывает служба, как раз и решает эту задачу. Он определяет метку подключённого тома, создаёт под неё каталог в общем месте для съёмных носителей и монтирует туда устройство. Если метки нет, в ход идёт имя устройства или его идентификатор, чтобы путь всё равно остался уникальным.
#!/bin/bash
DEV="/dev/$1"
LABEL=$(lsblk -no LABEL "$DEV")
NAME=${LABEL:-$1}
MOUNTPOINT="/media/$NAME"
mkdir -p "$MOUNTPOINT"
mount "$DEV" "$MOUNTPOINT"
Этот сценарий берёт переданное имя устройства, выясняет метку тома, выбирает в качестве имени каталога либо метку, либо само имя устройства, создаёт каталог и монтирует туда диск. В результате накопитель с меткой появляется по понятному пути с этой меткой, а безымянный по своему техническому имени, и оба не мешают друг другу.
Опираться на уникальный идентификатор тома надёжнее, чем на имя устройства, потому что имена вроде первого или второго диска система раздаёт в порядке подключения, и они меняются от раза к разу. Идентификатор же закреплён за конкретной файловой системой и не зависит от порядка, поэтому привязку к определённому накопителю строят именно на нём.
В чём состоит проблема состязания процессов
Отдельного разбора заслуживает тонкая проблема, которая всплывает, когда правило одновременно запускает и монтирование, и какую-то службу, которая хочет этим смонтированным диском воспользоваться. Возникает состязание: служба-потребитель может стартовать раньше, чем монтирование завершилось, и обратиться к ещё не готовому каталогу. Данные окажутся недоступны, хотя через мгновение диск уже будет смонтирован.
Корень состязания в том, что события udev обрабатываются асинхронно и параллельно, без гарантий порядка. Нельзя просто предположить, что к моменту запуска второго действия первое уже отработало. Если выстроить цепочку наивно, она будет работать в большинстве случаев и неожиданно ломаться в части запусков, что особенно коварно, ведь воспроизвести сбой трудно.
Лечат состязание через явные зависимости системного менеджера служб. Службу, которой нужен смонтированный диск, описывают так, чтобы она запускалась только после успешного завершения службы монтирования, а не параллельно с ней. Менеджер служб умеет выстраивать такие зависимости и гарантирует порядок, чего сам по себе udev не обеспечивает. Перекладывание монтирования и зависящих от него действий на менеджер служб разом снимает и проблему убитых долгих процессов, и проблему состязания, потому что обе они растут из попытки делать слишком многое прямо внутри обработки события udev.
Как отлаживать капризное правило
Когда автомонтирование не работает, помогает методичная диагностика. Прежде всего стоит проверить, что само правило корректно отбирает устройство, для чего udev умеет прогонять правила в тестовом режиме на конкретном устройстве без реального подключения.
sudo udevadm test --action=add /sys/block/sdb/sdb1
Эта команда показывает, какие правила сработали для указанного устройства и какие действия они назначили, помогая поймать опечатку в условиях. Если правило срабатывает, но монтирование не происходит, источник проблемы ищут в журнале системы, куда и udev, и службы монтирования пишут свои сообщения.
journalctl -f
Запущенный в режиме слежения журнал показывает события в реальном времени, и при подключении диска по нему видно, дошло ли дело до запуска службы, удалось ли монтирование и не вылезла ли ошибка прав доступа или неверного типа файловой системы. Поэтапная проверка от срабатывания правила к запуску службы и далее к самому монтированию обычно быстро выявляет, на каком звене цепочки всё рассыпается.
Как правильно отмонтировать диск при извлечении
Автомонтирование решает лишь половину задачи, ведь диск нужно ещё и аккуратно отключить, когда его выдёргивают. Если просто выдернуть накопитель, не отмонтировав, недописанные из кэша данные пропадут, а файловая система может остаться в несогласованном состоянии. Поэтому к правилу подключения добавляют парное правило на отключение, которое срабатывает при удалении устройства и отмонтирует его, а заодно убирает за собой опустевший каталог.
SUBSYSTEM=="block", KERNEL=="sd?1", ACTION=="remove", RUN+="/usr/bin/systemctl start external-unmount@%k.service"
Здесь условие действия ловит именно удаление устройства и запускает службу отмонтирования по тому же принципу, что и при подключении. Служба вызывает отмонтирование и удаляет каталог, чтобы в общем месте для носителей не копились пустые папки от давно отключённых дисков. Тонкость в том, что при резком выдёргивании событие удаления приходит уже после физического отключения, и часть данных могла не успеть записаться, поэтому пользователя всё равно приучают извлекать носитель через явное отмонтирование, а автоматику держат как подстраховку.
Почему важны права доступа и владелец на смонтированном диске
Смонтированный автоматически диск нередко оказывается доступен только суперпользователю, потому что монтирование выполняется от его имени. Обычный пользователь при этом не может ни читать, ни писать на свежеподключённый накопитель, что сводит на нет всё удобство автомонтирования. Поэтому в сценарий монтирования добавляют назначение владельца и прав, чтобы диском мог пользоваться нужный человек.
Для файловых систем без собственной модели прав вроде распространённых форматов флешек владельца и права задают прямо при монтировании через параметры. Для систем с собственными правами владельца меняют отдельной командой после монтирования. В обоих случаях цель одна: чтобы каталог монтирования принадлежал реальному пользователю, а не только администратору, и работа с диском не требовала постоянного повышения привилегий.
Стоит держать в уме и вопрос безопасности. Автоматическое монтирование чего попало с произвольными правами это потенциальная брешь, ведь подсунутый накопитель с вредоносным содержимым смонтируется без спроса. Поэтому правила сужают условиями по типу файловой системы и по конкретным признакам доверенных устройств, а сценарии монтирования пишут так, чтобы они не выполняли ничего лишнего и работали с минимально необходимыми привилегиями.
Что держать в голове
Автомонтирование внешних дисков через udev вполне достижимо, но требует уважения к устройству самого механизма. Главная ошибка новичка это попытка смонтировать диск прямо из правила, которую udev обрывает, считая долгий процесс зависшим. Правильный путь это поручить монтирование системному менеджеру служб, который запускается правилом и спокойно делает работу в своём темпе.
Понятные пути монтирования собирают из метки тома или его уникального идентификатора, чтобы каждый накопитель оказывался в своём предсказуемом каталоге без конфликтов. Проблему состязания процессов, когда потребитель стартует раньше готовности диска, снимают явными зависимостями менеджера служб, выстраивающими надёжный порядок запуска. Соблюдая эти принципы и опираясь на пошаговую отладку через тестовый прогон правил и журнал системы, можно превратить капризное автомонтирование в надёжный механизм, который встречает каждый подключённый диск ровно там, где его ждут.