- Uwaga dla Ubuntu Server 11.10: Ten skrypt nie działa na Ubuntu Server 11.10 z powodu przestarzałego
vol_id
polecenia. vol_id
został zastąpiony przez blkid
. Aby naprawić skrypt, zamień „vol_id” na „blkid -o udev” w udev-auto-mount.sh
skrypcie.
Od jakiegoś czasu macham głową i myślę, że znalazłem działające rozwiązanie. Jest to rozwijane i testowane na systemie opartym na Debianie, więc powinno działać na Ubuntu. Zwrócę uwagę na przyjęte przez niego założenia, dzięki czemu można go dostosować również do innych systemów.
- Automatycznie zamontuje dyski USB na wtyczce i nie powinno wiele wymagać adaptacji do Firewire.
- Używa UDEV, więc nie ma małpowania z HAL / DeviceKit / GNOME-Anything.
- Automatycznie tworzy
/media/LABEL
katalog, w którym można zamontować urządzenie.
- Może to jednak zakłócać działanie innych automatów liczących; Nie mogę tego przetestować. Spodziewam się, że przy aktywnym Gnome-VFS obaj mogą próbować wykonać podłączenie ... jeśli Gnome-VFS nie powiedzie się, nie może skonfigurować ikony pulpitu. Odłączanie od Gnome powinno być możliwe, ale może wymagać
gksudo
lub podobnie.
Nie testowałem tego podczas uruchamiania systemu, ale widzę, że może nie działać, jeśli spróbuje zamontować dysk USB, zanim system będzie gotowy do zamontowania. W takim przypadku prawdopodobnie potrzebna będzie dodatkowa modyfikacja skryptu montowania. ( Sprawdzam za pomocą ServerFault, czy jest jakaś rada, ale nie ma tam większego zainteresowania).
A więc do tego.
Referencje UDEV:
Tło (UDEV? Whuzzat?)
UDEV to system hotplug jądra. To właśnie automatycznie konfiguruje odpowiednie urządzenia i dowiązania symboliczne urządzeń (np. /dev/disk/by-label/<LABEL>
), Zarówno w czasie uruchamiania, jak i dla urządzeń dodawanych podczas działania systemu.
D-Bus i HAL są używane do wysyłania zdarzeń sprzętowych do słuchaczy, takich jak środowiska pulpitu. Kiedy więc zalogujesz się do GNOME i włożysz płytę CD lub podłączysz napęd USB, zdarzenie to będzie przebiegać następująco:
kernel -> udev -> dbus -> hal -> gnome-vfs/nautilus (mount)
I presto, twój napęd zostanie zamontowany. Ale w systemie bezgłowym nie chcemy się logować, aby uzyskać korzyści z automatycznego montażu.
Zasady Udev
Ponieważ UDEV pozwala nam pisać reguły i uruchamiać programy podczas wstawiania urządzeń, jest to idealny wybór. Wykorzystamy istniejące zasady Debian / Ubuntu, pozwolimy im skonfigurować /dev/disk/by-label/<LABEL>
dla nas dowiązanie symboliczne i dodamy kolejną regułę, która zamontuje dla nas urządzenie.
Reguły UDEV są przechowywane w /etc/udev/rules.d
(i /lib/udev/rules.d
Karmic) i są przetwarzane w kolejności numerycznej. Każdy plik, który nie zaczyna się od numeru, jest przetwarzany po plikach numerowanych. W moim systemie reguły HAL znajdują się w pliku o nazwie 90-hal.rules
, więc umieszczam je w regułach, 89-local.rules
aby zostały przetworzone, zanim dotrą do HAL. Przede wszystkim musisz upewnić się, że te reguły pojawią się po 60-persistent-storage.rules
. local.rules
może być wystarczająco dobry.
Umieść to w swoim nowym pliku reguł:
# /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"
Upewnij się, że nie ma spacji po \
, tylko a newline
( \n
).
Zmieni SUBSYSTEMS=="usb"
się SUBSYSTEMS=="usb|ieee1394"
o wsparcie Firewire.
Jeśli chcesz, aby urządzenie zawsze było własnością konkretnego użytkownika, dodaj OWNER="username"
klauzulę. Jeśli potrzebujesz tylko plików należących do określonego użytkownika, dostosuj skrypt montowania.
Czytanie reguły
Dodaje to program do uruchomienia do listy programów do uruchomienia na urządzeniu. Identyfikuje urządzenia partycji USB <LABEL>
, a następnie przekazuje te informacje do skryptu, który wykona podłączenie . W szczególności ta reguła jest zgodna:
ENV{ID_FS_LABEL_ENC}=="?*"
- zmienna środowiskowa ustawiona na podstawie wcześniejszej reguły systemowej. Nie istnieje dla systemów innych niż pliki, dlatego to sprawdzamy. Właściwie chcemy użyć ID_FS_LABEL
dla punktu montowania, ale nie przekonałem UDEV, aby uciec z niego, więc pozwolimy skryptowi montować sobie z tym poradzić.
Ta i inne zmienne środowiskowe są uzyskiwane przez udev za pomocą vol_id
polecenia ( przestarzałe ). Jest to przydatne narzędzie, aby zobaczyć ładne szybkie szczegóły na partycji:
$ 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"
- dopasowuj tylko add
wydarzenia ...
SUBSYSTEMS=="usb"
- pasuj tylko do urządzeń znajdujących się na magistrali USB. Używamy SUBSYSTEMS
tutaj, ponieważ odpowiada to rodzicom naszego urządzenia; urządzeniem, którym jesteśmy zainteresowani, w rzeczywistości będzie SUBSYSTEM == "scsi". Dopasowywanie do nadrzędnego urządzenia USB pozwala uniknąć dodawania naszego programu do dysków wewnętrznych.
RUN+="..."
- nie pasuje, ale akcja: dodaj ten program do listy programów do uruchomienia. W argumentach programu %k
zostaje rozwinięty do nazwy urządzenia (np. sdc1
Nie /dev/sdc1
) i $env{FOO}
otrzymuje zawartość zmiennej środowiskowej FOO.
Testowanie reguły
Pierwszy odnośnik (powyżej) to doskonały samouczek UDEV, ale jest nieco nieaktualny. Programy, które uruchamia do testowania twoich reguł ( udevtest
w szczególności) zostały zastąpione narzędziem catch-all udevadm
.
Po dodaniu reguły podłącz urządzenie. Daj mu kilka sekund, a następnie sprawdź, do którego urządzenia zostało przypisane:
$ 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
Jeśli twój dysk wymienny zawiera label_Baz
, jest na urządzeniu sdc1
. Uruchom to i spójrz na wynik pod koniec:
$ 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'
Poszukaj nazwy skryptu z naszej RUN+=
reguły w ostatnich kilku wierszach (3 od dołu w tym przykładzie). Możesz zobaczyć argumenty, które byłyby użyte dla tego urządzenia. Możesz teraz uruchomić to polecenie, aby sprawdzić, czy argumenty są prawidłowe; jeśli działa w linii poleceń, powinien działać automatycznie po włożeniu urządzenia.
Możesz także monitorować zdarzenia UDEV w czasie rzeczywistym: uruchom sudo udevadm monitor
(zobacz man udevadm
szczegóły na temat przełączników). Następnie wystarczy podłączyć nowe urządzenie i oglądać przewijane wydarzenia. (Prawdopodobnie przesada, chyba że interesują Cię szczegóły niskiego poziomu ...)
Ponowne ładowanie reguł
Po upewnieniu się, że reguła jest poprawnie czytana, musisz powiedzieć UDEV, aby przeładowała swoje reguły, aby nowa zaczęła obowiązywać. Użyj dowolnej z tych metod (jeśli pierwsza nie działa, druga powinna ... ale wypróbuj pierwszą pierwszą):
Scenariusz! Właściwie 2 skrypty ...
Oto pierwszy skrypt. Ponieważ program, który uruchamiamy, musi się szybko zakończyć, powoduje to jedynie wyłączenie drugiego skryptu w tle. Umieść to w /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} &
Oto drugi skrypt. Robi to nieco więcej sprawdzania danych wejściowych. Włóż to /usr/local/sbin/udev-auto-mount.sh
. Możesz dostosować poniższe opcje montowania. Ten skrypt obsługuje teraz samodzielne wyszukiwanie LABEL partycji; UDEV wysyła tylko nazwę URZĄDZENIA.
Jeśli podczas uruchamiania wystąpi problem z montażem dysków , możesz sleep 60
w tym skrypcie spędzić niezłą chwilę , aby dać systemowi czas na awans, zanim skrypt spróbuje zamontować dysk.
W komentarzach podałem sugestię dotyczącą sposobu sprawdzania (uruchom, ps
aby sprawdzić, czy serwer WWW działa), ale będziesz chciał dostosować go do swojego systemu. Myślę, że większość serwerów sieciowych, których używasz, wystarczyłaby do tego celu - nfsd, smbd, apache itp. Ryzyko polega oczywiście na tym, że skrypt montowania zawiedzie, jeśli usługa nie działa, więc może testowanie istnienie konkretnego pliku byłoby lepszym rozwiązaniem.
#!/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
Skrypt czyszczenia super bonusów!
Jeszcze jeden skrypt. Wszystko to polega na odmontowaniu urządzenia i usunięciu katalogów mountpoint. Zakłada, że ma do tego uprawnienia, więc musisz go uruchomić sudo
. Ten skrypt przyjmuje teraz pełny punkt montowania w wierszu poleceń, np .:
$ /usr/local/sbin/udev-unmounter.sh "/media/My Random Disk"
Umieść to w /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