- Примечание для 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? Whuzzat?)
UDEV - это система горячего подключения ядра.  Это то, что автоматически настраивает подходящие устройства и символические ссылки на устройства (например, /dev/disk/by-label/<LABEL>), как во время загрузки, так и для устройств, добавляемых во время работы системы.
D-Bus и HAL используются для отправки аппаратных событий слушателям, таким как Desktop Environments.  Поэтому, когда вы входите в GNOME и вставляете компакт-диск или подключаете USB-накопитель, это событие следует следующей цепочке:
kernel -> udev -> dbus -> hal -> gnome-vfs/nautilus (mount)
И до того, ваш диск будет установлен.  Но в безголовой системе нам не нужно входить в систему, чтобы воспользоваться преимуществами автоматического монтирования.
Правила Удев
Поскольку UDEV позволяет нам писать правила и запускать программы при вставке устройства, это идеальный выбор.  Мы собираемся воспользоваться преимуществами существующих правил Debian/Ubuntu, позволить им настроить для нас символическую ссылку /dev/disk/by-label/<LABEL> и добавить другое правило, которое смонтирует устройство для нас.  
Правила UDEV хранятся в /etc/udev/rules.d (и /lib/udev/rules.d на Karmic) и обрабатываются в числовом порядке.  Любой файл, не начинающийся с цифры, обрабатывается после нумерованных файлов.  В моей системе правила 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 .
После добавления правила подключите устройство.  Дайте ему несколько секунд, затем проверьте, на какое устройство ему назначено:
$ 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+= в последних нескольких строках (в этом примере третье снизу).  Вы можете увидеть аргументы, которые будут использоваться для этого устройства.  Вы можете запустить эту команду сейчас, чтобы проверить правильность аргументов; если он работает в командной строке, он должен работать автоматически при вставке устройства.
Вы также можете отслеживать события 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