Автомонтирование через udev

Автор:
Андрей Власовских
Источник:
http://vlan.tumblr.com/post/275906821/udev-automount

На днях настроил автомонтирование накопителей USB через udev в Arch Linux и Ubuntu. Ниже я буду описывать детали для Arch Linux и udev версии 146. В каждом дистрибутиве немного свои правила /etc/udev/rules.d, а в версиях udev менялись названия утилит и опций.

Сначала я расскажу о том, как работает udev, а затем приведу мои файлы конфигов и программки для монтирования накопителей USB.

Вкратце udev работает так. В ядро Linux 2.6 входит файловая система информации об устройствах sysfs. Она обычно монтируется в скриптах загрузки системы в каталог /sys. Эта система отображает объекты ядра, называемые kobjects. Объекты отражают устройства и драйверы. Каталоги представляют собой объекты, а файлы — их атрибуты, хранящиеся обычно в текстовом виде. Некоторые атрибуты можно менять.

В принципе, смонтированной системы sysfs было бы достаточно для обнаружения подключения и отключения устройств, особенно если бы в ней был динамический файл с событиями на манер Plan 9 или wmii. Но разработчики решили использовать для извещения сокеты семейства netlink(7). Замечу, что inotify(7) здесь не помог бы из-за большого числа файлов в /sys (порядка 10000). Ниже я ещё скажу об исходниках моей программы, показывающей, что же там посылает ядро в пользовательское пространство.

Итак, через специальный сокет с помощью группового вещания ядро рассылает уведомления об изменениях в sysfs. Эти события обрабатываются демоном udevd(8) с помощью языка правил udev(7). Правила обычно лежат в каталоге /etc/udev/rules.d в виде специальных файлов.

Каждое событие активизирует несколько правил. Начальные правила обычно создают нужные файлы устройств в /dev, символьные ссылки на устройства. Следующие правила запускают внешние программы для пополнения информации события. Например, при добавлении блочного устройства на USB запускается программа определения файловой системы, метки диска и т. д. Информация от программ попадает в переменные окружения, доступные последующим правилам.

Для автомонтирования, собственно, достаточно написать новый файл правил udev, который на основании собранной информации о подключаемом накопителе выдаст команды монтирования и создания удобных символьных ссылок.

За основу при написании правил я взял этот пост, но кое-что пришлось дохачить. Я столкнулся с такими сложностями:

  • Некоторые из моих флешек имели файловую систему на всём диске, а не на разделе
  • Один из моих компьютеров грузится с флешки, так что её нужно игнорировать, чтобы не испортить процесс загрузки
  • В разных дистрибутивах Linux и версиях udev отличаются переменные и программы получения информации для правил udev
  • Нужно было обеспечить монтирование ФС vfat с файлами от UID текущего пользователя
  • Я хотел разобраться в деталях написания правил, чтобы можно было писать правила самому для любых задач, связанных с udev

Все эти сложности удалось решить. Ниже приводится само решение, а если нужны какие-то пояснения — пишите.

Но вначале всё же пара советов. Методика отладки udev — используйте udevadm(8): udevadm monitor, udevadm info, udevadm test. Ими можно посмотреть почти всё необходимое. Если что-то не понятно — то тогда strace(1). Накопители с файловыми системами на всём диске использовать можно, но лучше переформатировать системы на разделы, например, с помощью fdisk(8). Наконец, очень удобно иметь пользовательское имя-метку диска. Изменить метку ext2 можно с помощью e2label(8), а для изменения метки vfat потребуется форматирование с помощью mkdosfs(8).

Итак, сами файлы автомонтирования. Вначале файл правил 70-mount-usb-storage.rules (заметьте отсутствие переносов строк в правилах), который кладётся в /etc/udev/rules.d:

# Добавление
ACTION=="add", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", RUN+="/bin/mkdir -p /mnt/%k", IMPORT{program}="/usr/local/bin/active_uid"
ACTION=="add", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", ENV{ID_FS_TYPE}=="vfat", RUN+="/bin/mount -t vfat -o rw,users,exec,noauto,noatime,fmask=113,dmask=002,uid=$env{ACTIVE_UID},gid=100,utf8 /dev/%k /mnt/%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", ENV{ID_FS_TYPE}=="ext2", RUN+="/bin/mount -t ext2 -o rw,nosuid,noatime /dev/%k /mnt/%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", RUN+="/bin/ln -s /mnt/%k /media/$env{ID_FS_LABEL_ENC}"

# Удаление
ACTION=="remove", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", RUN+="/bin/umount /dev/%k"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", RUN+="/usr/bin/unlink /media/$env{ID_FS_LABEL_ENC}"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", ENV{ID_USB_DRIVER}=="usb-storage", ATTRS{serial}!="0123456789012", RUN+="/bin/rmdir /mnt/%k"

Этот файл обеспечит монтирование накопителя в /mnt/<имя-устройства> и создание символьной ссылки в /media/<метка-диска>, а также удаление всего этого при отключении накопителя.

Файл использует мой скрипт active_uid, определяющий имя активного пользователя в системе. Он очень простой и делает следующее. Если имена всех вошедших пользователей совпадают, то этот пользователь и есть активный. Иначе это UID root. Скрипт кладётся куда угодно и прописывается в правилах выше:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash

uids () {
    users | tr " " "\n" | uniq
}

if [ `uids | wc -l` == 1 ]; then
    uid=`uids`
else
    uid="0"
fi

echo ACTIVE_UID="$uid"

Наконец, поскольку всё же интересно, как работает udevd и что сообщает ему ядро, я написал программу, выводящую дамп разобранных сообщений ядра. Исходники программы лежат в pastebin.org. Запускать её нужно от root, т. к. нужна привилегия CAP_NET_ADMIN.

blog comments powered by Disqus

Options

Tags

  • hardware
  • udev
  • usb
  • flash

Content view

  • Source

Navigation

  • Index
  • Blog
  • All pages
  • Tags
  • Mercurial repo

Search page names

nqw powered

Creative Commons License Copyright © 2008-2010 spb-archlinux Group. Материалы вики доступны по лицензии Creative Commons.