Sau vài lần bắt đầu sai tôi đã tìm ra điều này. Điều quan trọng là thêm một dịch vụ đơn vị systemd giữa udev và tập lệnh mount.
(Đối với bản ghi, tôi không thể làm việc này bằng cách sử dụng udisks2 (thông qua một cái gì đó giống như udisksctl mount -b /dev/sdb1
) được gọi trực tiếp từ quy tắc udev hoặc từ tệp đơn vị systemd. , kết quả là Error looking up object for device /dev/sdb1
. Thật không may, vì udisks2 có thể xử lý tất cả sự lộn xộn của điểm gắn kết ...)
Việc nâng vật nặng được thực hiện bởi một tập lệnh shell, đảm nhiệm việc tạo và loại bỏ các điểm gắn kết, và gắn và ngắt kết nối các ổ đĩa.
/usr/local/bin/usb-mount.sh
#!/bin/bash
# This script is called from our systemd unit file to mount or unmount
# a USB drive.
usage()
{
echo "Usage: $0 {add|remove} device_name (e.g. sdb1)"
exit 1
}
if [[ $# -ne 2 ]]; then
usage
fi
ACTION=$1
DEVBASE=$2
DEVICE="/dev/${DEVBASE}"
# See if this drive is already mounted, and if so where
MOUNT_POINT=$(/bin/mount | /bin/grep ${DEVICE} | /usr/bin/awk '{ print $3 }')
do_mount()
{
if [[ -n ${MOUNT_POINT} ]]; then
echo "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
exit 1
fi
# Get info for this drive: $ID_FS_LABEL, $ID_FS_UUID, and $ID_FS_TYPE
eval $(/sbin/blkid -o udev ${DEVICE})
# Figure out a mount point to use
LABEL=${ID_FS_LABEL}
if [[ -z "${LABEL}" ]]; then
LABEL=${DEVBASE}
elif /bin/grep -q " /media/${LABEL} " /etc/mtab; then
# Already in use, make a unique one
LABEL+="-${DEVBASE}"
fi
MOUNT_POINT="/media/${LABEL}"
echo "Mount point: ${MOUNT_POINT}"
/bin/mkdir -p ${MOUNT_POINT}
# Global mount options
OPTS="rw,relatime"
# File system type specific mount options
if [[ ${ID_FS_TYPE} == "vfat" ]]; then
OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
fi
if ! /bin/mount -o ${OPTS} ${DEVICE} ${MOUNT_POINT}; then
echo "Error mounting ${DEVICE} (status = $?)"
/bin/rmdir ${MOUNT_POINT}
exit 1
fi
echo "**** Mounted ${DEVICE} at ${MOUNT_POINT} ****"
}
do_unmount()
{
if [[ -z ${MOUNT_POINT} ]]; then
echo "Warning: ${DEVICE} is not mounted"
else
/bin/umount -l ${DEVICE}
echo "**** Unmounted ${DEVICE}"
fi
# Delete all empty dirs in /media that aren't being used as mount
# points. This is kind of overkill, but if the drive was unmounted
# prior to removal we no longer know its mount point, and we don't
# want to leave it orphaned...
for f in /media/* ; do
if [[ -n $(/usr/bin/find "$f" -maxdepth 0 -type d -empty) ]]; then
if ! /bin/grep -q " $f " /etc/mtab; then
echo "**** Removing mount point $f"
/bin/rmdir "$f"
fi
fi
done
}
case "${ACTION}" in
add)
do_mount
;;
remove)
do_unmount
;;
*)
usage
;;
esac
Kịch bản, lần lượt, được gọi bởi một tệp đơn vị systemd. Chúng tôi sử dụng cú pháp tên tệp "@" để chúng tôi có thể chuyển tên thiết bị làm đối số.
/etc/systemd/system/usb-mount@.service
[Unit]
Description=Mount USB Drive on %i
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/usb-mount.sh add %i
ExecStop=/usr/local/bin/usb-mount.sh remove %i
Cuối cùng, một số quy tắc udev bắt đầu và dừng dịch vụ đơn vị systemd trên hotplug / rút phích cắm:
/etc/udev/rules.d/99-local.rules
KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/bin/systemctl start usb-mount@%k.service"
KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/bin/systemctl stop usb-mount@%k.service"
Điều này dường như để làm các mẹo! Một vài lệnh hữu ích để gỡ lỗi những thứ như thế này:
udevadm control -l debug
bật ghi nhật ký chi tiết để
/var/log/syslog
bạn có thể thấy những gì đang xảy ra.
udevadm control --reload-rules
sau khi bạn sửa đổi các tệp trong dir.d dir (có thể không cần thiết, nhưng không thể làm tổn thương ...).
systemctl daemon-reload
sau khi bạn sửa đổi các tập tin đơn vị systemd.