- Примітка для Ubuntu Server 11.10: Цей скрипт виходить з ладу на Ubuntu Server 11.10 через застарілу
vol_id
команду. vol_id
було витіснене з blkid
. Щоб виправити скрипт, замініть "vol_id" на "blkid -o udev" у udev-auto-mount.sh
сценарії.
Я вже деякий час стукаю головою про це, і думаю, що знайшов робоче рішення. Це розроблено та протестовано на базі системи Debian, тому він повинен працювати на Ubuntu. Я зазначу припущення, які він робить, щоб його можна було адаптувати і до інших систем.
- Він автоматично монтуватиме USB-накопичувачі на плагін і не повинен займати багато для адаптації до Firewire.
- Він використовує UDEV, тому не маніпулюючи HAL / DeviceKit / GNOME-Anything.
- Він автоматично створює
/media/LABEL
каталог для монтажу пристрою.
- Однак це може заважати іншим автовиробникам; Я не можу на тест. Я очікую, що при активованому Gnome-VFS обидва можуть спробувати виконати кріплення ... якщо Gnome-VFS не вдасться виконати монтування, він може не налаштувати значок робочого столу. Від'єднання від Gnome має бути можливим, але може вимагати
gksudo
або подібного.
Я не перевіряв це на завантаженні системи, але єдина причина, яку я бачу, що це може не спрацювати, це якщо вона намагається встановити USB-накопичувач до того, як система готова до кріплення. Якщо це так, вам, ймовірно, знадобиться ще одне додаткове підключення до сценарію кріплення. (Я перевіряю у ServerFault, щоб побачити, чи є якась порада, але там не дуже великий інтерес.)
Тоді на цьому.
Посилання на UDEV:
Передумови (UDEV? Whzzat?)
UDEV - система гарячої підключення ядра. Це те, що автоматично налаштовує належні пристрої та посилання на пристрої (наприклад /dev/disk/by-label/<LABEL>
), як під час завантаження, так і для пристроїв, доданих під час роботи системи.
D-Bus та HAL використовуються для надсилання апаратних подій слухачам, таких як Desktop Environment. Отже, коли ви входите в GNOME і вставляєте компакт-диск або підключіть USB-накопичувач, ця подія слід за цим ланцюжком:
kernel -> udev -> dbus -> hal -> gnome-vfs/nautilus (mount)
І заздалегідь, ваш привід встановлюється. Але в безголівковій системі нам не хочеться входити в систему, щоб отримати переваги автоматичного управління.
Правила Udev
Оскільки UDEV дозволяє нам писати правила та запускати програми для вставки пристроїв, це ідеальний вибір. Ми збираємось скористатися існуючими правилами Debian / Ubuntu, дозвольмо їм встановити /dev/disk/by-label/<LABEL>
посилання для нас, і додамо ще одне правило, яке монтуватиме пристрій для нас.
Правила UDEV зберігаються в /etc/udev/rules.d
(і /lib/udev/rules.d
в Кармічній) і обробляються в числовому порядку. Будь-який файл, що не починається з числа, обробляється після нумерованих файлів. У моїй системі правила HAL знаходяться у файлі, який називається 90-hal.rules
, тому я вкладаю свої правила, 89-local.rules
щоб вони оброблялися, перш ніж потрапити до HAL. Перш за все, вам потрібно переконатися, що ці правила відбудуться після 60-persistent-storage.rules
. local.rules
може бути досить хорошим.
Помістіть це у новий файл правил:
# /etc/udev/rules.d/local.rules
# /etc/udev/rules.d/89-local.rules
# ADD rule: if we have a valid ID_FS_LABEL_ENC, and it's USB, mkdir and mount
ENV{ID_FS_LABEL_ENC}=="?*", ACTION=="add", SUBSYSTEMS=="usb", \
RUN+="/usr/local/sbin/udev-automounter.sh %k"
Переконайтеся, що після пробілу немає пробілів \
, просто newline
( \n
).
Змініть SUBSYSTEMS=="usb"
на SUBSYSTEMS=="usb|ieee1394"
підтримку Firewire.
Якщо ви хочете, щоб пристрій завжди належав певному користувачеві, додайте OWNER="username"
пункт. Якщо вам просто потрібні файли, що належать певному користувачеві, замініть сценарій монтажу.
Читання правила
Це додає програму для запуску до списку програм, які потрібно запустити. Він ідентифікує пристрої розділів USB за допомогою <LABEL>
, а потім передає цю інформацію сценарію, який виконує монтаж. Зокрема, це правило відповідає:
ENV{ID_FS_LABEL_ENC}=="?*"
- змінна середовища, встановлена попереднім системним правилом. Не існує для нефайлових систем, тому ми перевіряємо її. Ми насправді хочемо використовувати ID_FS_LABEL
для точки монтування, але я не переконав UDEV уникати цього для мене, тому ми дозволимо скрипту монтування впоратися з цим.
Ця та інші змінні середовища отримуються udev за допомогою vol_id
команди ( застаріло ). Це зручний інструмент для перегляду приємних швидких подробиць на розділі:
$ sudo vol_id /dev/sdc1
ID_FS_TYPE=ext2
ID_FS_UUID=a40d282a-4a24-4593-a0ab-6f2600f920dd
ID_FS_LABEL=Travel Dawgs
ID_FS_LABEL_ENC=Travel\x20Dawgs
ID_FS_LABEL_SAFE=Travel_Dawgs
ACTION=="add"
- лише add
події матчу ...
SUBSYSTEMS=="usb"
- відповідають лише пристрої, які знаходяться на шині USB. Ми використовуємо SUBSYSTEMS
тут, оскільки це відповідає батькам нашого пристрою; пристрій, який нас цікавить, насправді буде SUBSYSTEM == "scsi". Узгодження з батьківським USB-пристроєм дозволяє уникнути додавання нашої програми до внутрішніх накопичувачів.
RUN+="..."
- не збіг, а дія: додайте цю програму до списку програм, які потрібно запустити. В аргументах програми %k
розширюється на ім'я пристрою (наприклад sdc1
, немає /dev/sdc1
) і $env{FOO}
отримує вміст змінної середовища FOO.
Тестування правила
Перше посилання (вище) - чудовий підручник з UDEV, але він трохи застарів. Програми, які він запускає для тестування ваших правил ( udevtest
зокрема), були замінені udevadm
утилітою " catch-all" .
Після додавання правила підключіть свій пристрій. Дайте йому кілька секунд, а потім перевірте, на який пристрій призначено:
$ ls -l /dev/disk/by-label/*
lrwxrwxrwx 1 root root 10 2009-10-25 07:27 label_Foo -> ../../sda1
lrwxrwxrwx 1 root root 10 2009-10-25 07:27 label_Bar -> ../../sdb1
lrwxrwxrwx 1 root root 10 2009-10-25 07:27 label_Baz -> ../../sdc1
Якщо ваш знімний диск містить label_Baz
його, він знаходиться на пристрої sdc1
. Запустіть це і подивіться на вихід до кінця:
$ sudo udevadm test /sys/block/sdc/sdc1
parse_file: reading (...) (many lines about files it reads)
import_uevent_var: import into environment: (...) (many lines about env variables)
(...) (many lines tracing rule matches & programs run)
update_link: found 1 devices with name 'disk/by-label/LABEL_BAZ'
update_link: found '/block/sdc/sdc1' for 'disk/by-label/LABEL_BAZ'
update_link: compare (our own) priority of '/block/sdc/sdc1' 0 >= 0
update_link: 'disk/by-label/LABEL_BAZ' with target 'sdc1' has the highest priority 0, create it
udevtest: run: '/usr/local/sbin/udev-automounter.sh sdc1 LABEL_BAZ'
udevtest: run: 'socket:/org/freedesktop/hal/udev_event'
udevtest: run: 'socket:@/org/kernel/udev/monitor'
Шукайте назву сценарію з нашого RUN+=
правила в останніх рядках (3-й знизу в цьому прикладі). Ви можете бачити аргументи, які використовувались для цього пристрою. Ви можете запустити цю команду зараз, щоб перевірити, чи аргументи звучать; якщо він працює у вашому командному рядку, він повинен працювати автоматично, коли вставлено пристрій.
Ви також можете відстежувати події UDEV в режимі реального часу: запустіть sudo udevadm monitor
(див. man udevadm
Подробиці про перемикачі). Потім просто підключіть новий пристрій і спостерігайте за прокручуванням подій. (Можливо, зайвий рівень, якщо ви не отримаєте детальну інформацію про низький рівень ...)
Перезавантаження правил
Після того, як ви переконалися, що правило читається належним чином, вам потрібно сказати UDEV, щоб перезавантажити його правила, щоб нове набрало чинності. Використовуйте будь-який із цих методів (якщо перший не працює, другий повинен ... але спробуйте перший перший):
Сценарій! Насправді, 2 сценарії ...
Ось перший сценарій. Оскільки програму, яку ми запускаємо, потрібно швидко виконати, це просто відкручує другий сценарій у фоновому режимі. Помістіть це /usr/local/sbin/udev-automounter.sh
:
#!/bin/sh
#
# USAGE: usb-automounter.sh DEVICE
# DEVICE is the actual device node at /dev/DEVICE
/usr/local/sbin/udev-auto-mount.sh ${1} &
Ось другий сценарій. Це робить трохи більше перевірки вводу. Покладіть це /usr/local/sbin/udev-auto-mount.sh
. Ви можете налаштувати параметри кріплення нижче. Цей сценарій тепер обробляє пошук розділу LABEL самостійно; UDEV надсилає лише ім'я ПРИЛАДУ.
Якщо під час завантаженняsleep 60
виникають проблеми з монтажем накопичувачів, у цьому сценарії ви можете покласти досить довгий час , щоб дати системному часу піднятися до того, як сценарій намагатиметься встановити накопичувач.
Я дав пропозицію в коментарях щодо того, як перевірити (запустіть, ps
щоб перевірити, чи працює веб-сервер), але ви захочете налаштувати це для вашої системи. Я думаю, що більшості будь-яких мережевих серверів, якими ви користуєтесь, було б достатньо для цієї мети - nfsd, smbd, apache і т. Д. Ризик, звичайно, полягає в тому, що сценарій монтування вийде з ладу, якщо служба не працює, тому можливо тестування тесту існування конкретного файлу було б кращим рішенням.
#!/bin/sh
#
# USAGE: udev-auto-mount.sh DEVICE
# DEVICE is the actual device node at /dev/DEVICE
#
# This script takes a device name, looks up the partition label and
# type, creates /media/LABEL and mounts the partition. Mount options
# are hard-coded below.
DEVICE=$1
# check input
if [ -z "$DEVICE" ]; then
exit 1
fi
# test that this device isn't already mounted
device_is_mounted=`grep ${DEVICE} /etc/mtab`
if [ -n "$device_is_mounted" ]; then
echo "error: seems /dev/${DEVICE} is already mounted"
exit 1
fi
# If there's a problem at boot-time, this is where we'd put
# some test to check that we're booting, and then run
# sleep 60
# so the system is ready for the mount below.
#
# An example to experiment with:
# Assume the system is "booted enough" if the HTTPD server is running.
# If it isn't, sleep for half a minute before checking again.
#
# The risk: if the server fails for some reason, this mount script
# will just keep waiting for it to show up. A better solution would
# be to check for some file that exists after the boot process is complete.
#
# HTTPD_UP=`ps -ax | grep httpd | grep -v grep`
# while [ -z "$HTTPD_UP" ]; do
# sleep 30
# HTTPD_UP=`ps -ax | grep httpd | grep -v grep`
# done
# pull in useful variables from vol_id, quote everything Just In Case
eval `/sbin/vol_id /dev/${DEVICE} | sed 's/^/export /; s/=/="/; s/$/"/'`
if [ -z "$ID_FS_LABEL" ] || [ -z "$ID_FS_TYPE" ]; then
echo "error: ID_FS_LABEL is empty! did vol_id break? tried /dev/${DEVICE}"
exit 1
fi
# test mountpoint - it shouldn't exist
if [ ! -e "/media/${ID_FS_LABEL}" ]; then
# make the mountpoint
mkdir "/media/${ID_FS_LABEL}"
# mount the device
#
# If expecting thumbdrives, you probably want
# mount -t auto -o sync,noatime [...]
#
# If drive is VFAT/NFTS, this mounts the filesystem such that all files
# are owned by a std user instead of by root. Change to your user's UID
# (listed in /etc/passwd). You may also want "gid=1000" and/or "umask=022", eg:
# mount -t auto -o uid=1000,gid=1000 [...]
#
#
case "$ID_FS_TYPE" in
vfat) mount -t vfat -o sync,noatime,uid=1000 /dev/${DEVICE} "/media/${ID_FS_LABEL}"
;;
# I like the locale setting for ntfs
ntfs) mount -t auto -o sync,noatime,uid=1000,locale=en_US.UTF-8 /dev/${DEVICE} "/media/${ID_FS_LABEL}"
;;
# ext2/3/4 don't like uid option
ext*) mount -t auto -o sync,noatime /dev/${DEVICE} "/media/${ID_FS_LABEL}"
;;
esac
# all done here, return successful
exit 0
fi
exit 1
Супер-бонусний сценарій очищення!
Ще один сценарій. Все, що потрібно зробити - це відключити пристрій і видалити каталоги на місце кріплення. Він передбачає, що для цього є приватні особи, тому вам потрібно буде запустити його sudo
. Цей сценарій тепер приймає повну точку монтажу в командному рядку, наприклад:
$ /usr/local/sbin/udev-unmounter.sh "/media/My Random Disk"
Помістіть це /usr/local/sbin/udev-unmounter.sh
:
#!/bin/sh
#
# USAGE: udev-unmounter.sh MOUNTPT
# MOUNTPT is a mountpoint we want to unmount and delete.
MOUNTPT="$1"
if [ -z "$MOUNTPT" ]; then
exit 1
fi
# test mountpoint - it should exist
if [ -e "${MOUNTPT}" ]; then
# very naive; just run and pray
umount -l "${MOUNTPT}" && rmdir "${MOUNTPT}" && exit 0
echo "error: ${MOUNTPT} failed to unmount."
exit 1
fi
echo "error: ${MOUNTPT} does not exist"
exit 1