- Catatan untuk Ubuntu Server 11.10: Skrip ini gagal pada Ubuntu Server 11.10 karena
vol_id
perintah usang . vol_id
telah digantikan oleh blkid
. Untuk memperbaiki skrip, ganti "vol_id" dengan "blkid -o udev" di udev-auto-mount.sh
skrip.
Saya telah membenturkan kepala saya di sekitar ini untuk sementara waktu sekarang, dan saya pikir saya telah menemukan solusi yang berhasil. Ini dikembangkan dan diuji pada sistem berbasis Debian, sehingga harus bekerja di Ubuntu. Saya akan menunjukkan asumsi yang dibuatnya sehingga dapat disesuaikan dengan sistem lain juga.
- Ini akan secara otomatis memasang drive USB pada plugin, dan tidak perlu banyak beradaptasi dengan Firewire.
- Ini menggunakan UDEV, jadi tidak ada monyet dengan HAL / DeviceKit / GNOME-Apa pun.
- Ini secara otomatis membuat
/media/LABEL
direktori untuk memasang perangkat.
- Namun, itu dapat mengganggu pembuat mobil lain; Saya tidak bisa menguji untuk itu. Saya berharap bahwa, dengan Gnome-VFS aktif, keduanya dapat mencoba melakukan mount ... jika Gnome-VFS gagal me-mount, mungkin tidak mengkonfigurasi ikon desktop. Melepas dari Gnome harus dimungkinkan, tetapi mungkin memerlukan
gksudo
atau serupa.
Saya belum menguji ini pada boot sistem, tetapi satu-satunya alasan saya dapat melihat bahwa itu mungkin tidak berhasil adalah jika mencoba untuk memasang drive USB sebelum sistem siap untuk mount. Jika itu masalahnya, Anda mungkin perlu satu tweak tambahan untuk skrip mount. (Saya memeriksa dengan ServerFault untuk melihat apakah ada saran, tetapi tidak banyak minat di sana.)
Kalau begitu, ke sana.
Referensi UDEV:
Latar Belakang (UDEV? Whuzzat?)
UDEV adalah sistem hotplug kernel. Itulah yang secara otomatis mengkonfigurasi perangkat yang tepat dan symlink perangkat (mis. /dev/disk/by-label/<LABEL>
), Baik pada saat boot maupun untuk perangkat yang ditambahkan saat sistem sedang berjalan.
D-Bus dan HAL digunakan untuk mengirim acara perangkat keras ke pendengar seperti Lingkungan Desktop. Jadi, ketika Anda masuk ke GNOME dan memasukkan CD atau mencolokkan drive USB, peristiwa itu mengikuti rantai ini:
kernel -> udev -> dbus -> hal -> gnome-vfs/nautilus (mount)
Dan presto, drive Anda dipasang. Tetapi dalam sistem tanpa kepala, kami tidak ingin harus masuk untuk mendapatkan manfaat dari penghitungan otomatis.
Aturan Udev
Karena UDEV memungkinkan kami menulis aturan dan menjalankan program dengan penyisipan perangkat, ini adalah pilihan yang ideal. Kita akan mengambil keuntungan dari aturan Debian / Ubuntu yang ada, biarkan mereka mengatur /dev/disk/by-label/<LABEL>
symlink untuk kita, dan menambahkan aturan lain yang akan memasang perangkat untuk kita.
Aturan UDEV disimpan di /etc/udev/rules.d
(dan /lib/udev/rules.d
di Karmic), dan diproses dalam urutan numerik. File apa pun yang tidak dimulai dengan nomor akan diproses setelah file bernomor. Di sistem saya, aturan HAL ada dalam file yang dipanggil 90-hal.rules
, jadi saya memasukkan aturan saya 89-local.rules
sehingga mereka diproses sebelum mereka sampai ke HAL. Terutama, Anda perlu memastikan aturan ini terjadi setelah 60-persistent-storage.rules
. local.rules
mungkin cukup baik.
Masukkan ini ke file aturan baru Anda:
# /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"
Pastikan tidak ada spasi setelah \
, hanya a newline
( \n
).
Ubah SUBSYSTEMS=="usb"
ke SUBSYSTEMS=="usb|ieee1394"
untuk dukungan Firewire.
Jika Anda ingin perangkat selalu dimiliki oleh pengguna tertentu, tambahkan OWNER="username"
klausa. Jika Anda hanya perlu file yang dimiliki oleh pengguna tertentu, ubah skrip pemasangan sebagai gantinya.
Membaca Aturan
Ini menambahkan program untuk dijalankan ke daftar program perangkat untuk dijalankan. Ini mengidentifikasi perangkat partisi USB dengan <LABEL>
, kemudian meneruskan informasi ini ke skrip yang melakukan mount. Secara khusus, aturan ini cocok:
ENV{ID_FS_LABEL_ENC}=="?*"
- variabel lingkungan yang ditetapkan oleh aturan sistem sebelumnya. Tidak ada untuk sistem non-file, jadi itu sebabnya kami memeriksanya. Kami sebenarnya ingin menggunakan ID_FS_LABEL
untuk mount point, tetapi saya belum meyakinkan UDEV untuk menghindarinya bagi saya, jadi kami akan membiarkan skrip mount menangani hal itu.
Variabel lingkungan ini dan lainnya diperoleh oleh udev menggunakan vol_id
perintah ( usang ). Ini adalah alat yang berguna untuk melihat detail cepat yang bagus di partisi:
$ 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"
- hanya add
acara pertandingan ...
SUBSYSTEMS=="usb"
- hanya cocok dengan perangkat yang ada di bus USB. Kami menggunakan di SUBSYSTEMS
sini karena ini cocok dengan orangtua perangkat kami; perangkat yang kami minati sebenarnya adalah SUBSYSTEM == "scsi". Menyesuaikan dengan perangkat USB induk menghindari penambahan program kami ke drive internal.
RUN+="..."
- bukan kecocokan, tetapi tindakan: tambahkan program ini ke daftar program yang akan dijalankan. Dalam argumen program, %k
diperluas ke nama perangkat (misalnya sdc1
, tidak /dev/sdc1
) dan $env{FOO}
mendapatkan konten variabel lingkungan FOO.
Menguji Aturannya
Tautan referensi pertama (di atas) adalah tutorial UDEV yang luar biasa, tetapi sedikit kedaluwarsa. Program yang dijalankan untuk menguji aturan Anda ( udevtest
khususnya) telah digantikan oleh udevadm
utilitas catch-all .
Setelah Anda menambahkan aturan, masukkan perangkat Anda. Berikan waktu beberapa detik, lalu periksa untuk melihat perangkat apa yang ditugaskan kepadanya:
$ 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
Jika drive Anda yang dapat dihapus berisi label_Baz
, itu ada di perangkat sdc1
. Jalankan ini dan lihat output menjelang akhir:
$ 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'
Cari nama skrip dari RUN+=
aturan kami di beberapa baris terakhir (ke-3 dari bawah dalam contoh ini). Anda dapat melihat argumen yang akan digunakan untuk perangkat ini. Anda dapat menjalankan perintah itu sekarang untuk memeriksa apakah argumennya benar; jika berfungsi pada commandline Anda, itu akan bekerja secara otomatis ketika perangkat dimasukkan.
Anda juga dapat memantau acara UDEV secara realtime: lari sudo udevadm monitor
(lihat man udevadm
detail tentang sakelar). Kemudian cukup colokkan perangkat baru dan saksikan acara bergulir. (Mungkin berlebihan kecuali kamu benar-benar detail tingkat rendah ...)
Muat Ulang Aturan
Setelah Anda memverifikasi aturan tersebut dibaca dengan benar, Anda perlu memberitahu UDEV untuk memuat ulang aturannya sehingga yang baru berlaku. Gunakan salah satu dari metode ini (jika yang pertama tidak berhasil, yang kedua harus ... tetapi coba yang pertama):
Naskah! Sebenarnya, 2 Script ...
Ini skrip pertama. Karena program yang kita jalankan perlu diselesaikan dengan cepat, ini hanya memutar script kedua di latar belakang. Masukkan ini /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} &
Ini skrip kedua. Ini melakukan sedikit lebih banyak input input. Menempatkan ini dalam /usr/local/sbin/udev-auto-mount.sh
. Anda mungkin ingin mengubah opsi pemasangan di bawah. Script ini sekarang menangani menemukan LABEL partisi sendiri; UDEV hanya mengirim nama PERANGKAT.
Jika ada masalah saat memasang drive saat boot , Anda dapat menaruh banyak waktu sleep 60
dalam skrip ini, untuk memberi waktu bagi sistem untuk melakukan semuanya sebelum skrip mencoba memasang drive.
Saya telah memberikan saran di komentar untuk cara memeriksa (jalankan ps
untuk melihat apakah server web sedang berjalan), tetapi Anda ingin mengubahnya untuk sistem Anda. Saya pikir sebagian besar server jaringan yang mungkin Anda gunakan akan mencukupi untuk tujuan ini - nfsd, smbd, apache, dll. Risikonya, tentu saja, skrip mount akan gagal jika layanan tidak berjalan, jadi mungkin menguji Keberadaan file tertentu akan menjadi solusi yang lebih baik.
#!/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
Skrip Pembersihan Bonus Super!
Satu lagi skrip. Yang dilakukan adalah melepas perangkat dan menghapus direktori mountpoint. Diasumsikan memiliki privs untuk melakukan ini, jadi Anda harus menjalankannya sudo
. Script ini sekarang mengambil titik mount penuh pada commandline, misalnya:
$ /usr/local/sbin/udev-unmounter.sh "/media/My Random Disk"
Masukkan ini /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