Sistemli Automount USB sürücüleri


27

Sunucularımızı, güncel olmayan bir dağıtımdan, lightdm / xfce ve tabii ki systemd (ve udisks2) dahil olmak üzere modern bir Debian Jessie tabanlı sisteme yükseltiyoruz. Bir yapıştırma noktası USB sürücülerin otomatik olarak ayarlanmasıdır. Bunu bazı udev kurallarıyla başardık. Eski kurallar neredeyse işe yaramaktadır - montaj noktası oluşturulur ve sürücü iyi monte edilir, ancak birkaç saniye sonra systemd montajı kıran bir şey yapar, bu nedenle erişim girişimleri "Aktarma bitiş noktası bağlı değil" hatalarıyla sonuçlanır.

Sürücüyü komut satırı üzerinden elle monte etmek gayet iyi çalışıyor. Bir dosya yöneticisi izin verir (sırayla udisks2 kullanan thunar ve thunar-volman). Ancak bunlar uygulanabilir seçenekler değil - bu sistemler çoğunlukla kafasız çalışıyor, bu nedenle thunar normal şekilde çalışmıyor. Katılımsız cron tabanlı yedeklemeler için disk sürücüleri takabilmemiz gerekir.

Udev betiğini, montajı gerçekleştirmeden birkaç saniye önce bekletilen müstakil bir işi yumurtlayacak şekilde değiştirmek, hile yapabilir, ancak sistemd bunu önlemek için kendi yolundan çıkıyor gibi görünüyor - yine de bir işin bitmeden önce bitmesini beklediğini düşünüyor. devam ediyor.

Belki de udev betiğini udisks2 gıdıklamak bir şekilde doğru yaklaşımdır? Kayboldum, bu yüzden herhangi bir tavsiye çok takdir ediyorum.


1
Sadece teğetsel olarak ilişkili ama ... Sunucuya xfce mı koyuyorsunuz?
Parthian

Ah, "sunucu" terimini oldukça gevşek kullandım ... Sistemle tüm kullanıcı etkileşimi, genellikle ağ üzerinden bir tarayıcı aracılığıyla erişilen bir web uygulaması üzerinden gerçekleştirilir. Ancak bazı müşteriler ağ dışı bir çözümü tercih ediyor, bu yüzden Chrome'u konsolda bir kiosk modunda çalıştırıyoruz. (Bu ayrıca ağ yapılandırma sorunlarını ayıklamak için kullanışlıdır, bir monitör / fare / klavyeyi takabilir ve Linux oturum açma kimlik bilgilerine ihtiyaç duymadan web uygulamasındaki temel tanılama araçlarına erişebilirsiniz). Muhtemelen lightdm / xfce'den daha hafif bir çözüm var, ama bu ayarlanması kolay oldu ...
Mike Blackwell

Doğrudan bir betik çalıştıran systemd-udevd kurallarını isteyen herkes için: Bunu yaptım; Bir süre çalıştı, ancak bir noktada udevd otomatik olarak başlatılmışsa senaryoyu çalıştırmayı bıraktı. Durdur ve komut satırından yeniden başlat, sorun olmaz. Bunun da ötesinde, NTFS + FUSE ile hiçbir zaman iyi çalışmadı, çünkü udev uzun süredir devam eden bir çocuk sürecine (ntfs-3g) sahip olduğunu tespit etti ve 60'lardan sonra öldürdü. Alt satır: udev kuralları doğrudan bir betiği çalıştırmak zaman kaybıdır. Cevaplarda belirtildiği gibi udev kuralları ve bir systemd servisi ile gidin. Öyleyse, ad alanlarıyla (MountFlags = slave) başa çıkmak zorunda değilsiniz.
Mark

Ağ bağlantılarını kuramamak için udev tarafından başlatılan bir betiğin de benzer bir sorunu vardı. Aşağıdaki systemd kullanmanın çözümü de bunun için işe yaradı - teşekkürler!
Quentin Stafford-Fraser

Yanıtlar:


28

Birkaç yanlış başlangıçtan sonra bunu çözdüm. Anahtar, udev ile bir montaj betiği arasında bir sistem birimi hizmeti eklemektir.

(Kayıt için, bu çalışmayı udisksctl mount -b /dev/sdb1doğrudan udev kuralından veya sistemd birim dosyasından çağrılan udisks2 (benzeri bir şeyle ) kullanarak elde edemedim . Bir yarış durumu var gibi görünüyor ve cihaz düğümü oldukça hazır değil , sonuçta Error looking up object for device /dev/sdb1. Maalesef, udisks2 tüm bağlantı noktası dağınıklığıyla ilgilenebildiğinden beri ...)

Ağır kaldırma, montaj noktalarının oluşturulmasına ve çıkarılmasına ve sürücülerin takılmasına ve sökülmesine özen gösteren bir kabuk betiği ile yapılır.

/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

Komut dosyası sırayla systemd unit file tarafından çağrılır. "@" Filename sözdizimini kullanıyoruz, böylece cihaz ismini argüman olarak geçebiliriz.

/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

Son olarak, bazı udev kuralları hotplug / unplug'da systemd birim hizmetini başlatır ve durdurur:

/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"

Bu hile yapmak gibi görünüyor! Bunun gibi şeyleri hata ayıklamak için birkaç yararlı komut:

  • udevadm control -l debugayrıntılı günlüğü açar ve /var/log/syslogneler olduğunu görebilirsiniz.
  • udevadm control --reload-rules rules.d dir'deki dosyaları değiştirdikten sonra (gerekli olmayabilir, fakat zarar veremez ...).
  • systemctl daemon-reload systemd birim dosyalarını değiştirdikten sonra.

4
Vay. Bu harika. Keşke birden fazla dolar verebilseydim! Ben değiştirmek zorunda tek şey sistemimde, olmasıydı blkidbir ayıklamak için görünmüyor ID_FS_LABELsadece kullanılan bu yüzden, DEVBASEyerine LABELinşaat MOUNT_POINTyerine.
Travis Griggs,

Bu kurulum ATA / SCSI cihazlarıyla çalışmak için değiştirilebilir mi? Bakınız: serverfault.com/q/825779/297059
user339676 2

@Travis - Bunun udevadmyerine kullanabilirsiniz blkid. Ek bilgilerin yanı sıra çok daha fazla ayrıntı verir. (örn. udevadm info --query=property --name=sda1)
kullanıcı339676

zaten bir usb aygıtı bağlıysa bu önyüklemede iyi çalışmaz. Herhangi bir fikir?
Michal Artazov

Nullglobs ayarlanmadığında, unmount'ta, temizleme gibi bir hata üretebilir /usr/bin/find: '/media/*': No such file or directory. Temizleme, if [ "$f" != "/media/*" ]; thençalıştırmadan önce olduğu gibi ek bir kontrol kullanabilir find.
Pro Yedekleme

12

Tüm standart montaj izni seçeneklerini kullanmanızı sağlayan, systemdkullanılabilecek yeni, özlü bir otomatik montaj seçeneği vardır fstabve şöyle görünür:

  x-systemd.automount

bir fstabsatırda buna bir örnek :

  /dev/sdd1   /mnt/hitachi-one     auto     noauto,x-systemd.automount     0 2

Bu noautoseçenek, eski yazılımlarda olduğu gibi önyüklemede takılmaya çalışmadığı anlamına gelir autofs.

size yeni bir x-systemd.automountsatır ekledikten fstabsonra çalıştırmanız gerekir:

  sudo systemctl daemon-reload

ve ardından aşağıdakilerden ikisinin veya ikisinin biri:

  sudo systemctl restart remote-fs.target
  sudo systemctl restart local-fs.target

Bu konuda daha fazla bilgi için:

https://wiki.archlinux.org/index.php/Fstab#Automount_with_systemd


sudo systemctl restart local-fs.targetbenim için hile yaptı
Philippe Gachoud

2

Komut dosyasını @MikeBlackwell'den değiştirdim:

  • sadece /dev/sd[a-z]değil /dev/sd[a-z]*, aynı zamanda birden fazla karakter içeren cihaz adlarını tanır ; çoğu zaman daha büyük sayıda iğ bulunan sunucular için geçerlidir.
  • adresindeki otomatik sürücülerin listesini takip et /var/log/usb-mount.track
  • eylemleri usb-mount.sh/var/log/messages etiketiyle günlüğe kaydet
  • Bir etiket atanmamış olan sürücülerle sorunlara çalıştırılmayan için montaj noktası için cihaz etiketi ile önek aygıt adı (boş?): /media/sdd2_usbtest,/media/sdd2_
  • dosyaları uygun şekilde yerleştirmek ve gerektiğinde geri almak için sarmalayıcı komut dosyaları dahil

@MikeBlackwell ağır yüklerin çoğunu zaten yaptığı için, yeniden yazmamayı seçtim; Sadece gerekli değişiklikleri yaptım. Orijinal cevabın adını ve URI'sını inceleyen çalışmasını kabul ettim.

Adresinden bul https://github.com/raamsri/automount-usb


2

Kullanılması pmount , systemd ve Mike Blackwell yaklaşımını, her şeyi kolaylaştırabilir:

/etc/systemd/system/usb-mount@.service

[Unit]
Description=Mount USB Drive on %i
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/pmount --umask 000 /dev/%i /media/%i
ExecStop=/usr/bin/pumount /dev/%i

/etc/udev/rules.d/99-usb-mount.rules

ACTION=="add",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl start usb-mount@%k.service"
ACTION=="remove",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl stop usb-mount@%k.service"

HTH ve teşekkür ederim Mike.


0

Warren Young’ın cevabına giderdim, bazı değişiklikler yaptım

Disk için ortamın değerlendirilmesinden hatalar verdiği için bir miktar alan koruması ekledim.

Bir usb diski chmod'a bir bölüm ekledim, böylece tüm kullanıcılar ntfs veya vfat disklerine tam erişime sahip olamazlar.

/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
    # added some sed's to avoid space issues
    eval $(/sbin/blkid -o udev ${DEVICE}|sed 's/=/="/'|sed 's/$/"/')

    # 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"
    #added a chmod checker for file systems that don't 
    #understand allow all to read write
    CHMOD=no
    # File system type specific mount options
    if [[ ${ID_FS_TYPE} == "vfat" ]]; then
        OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
    #added options I wanted on ntfs
    elif [[ ${ID_FS_TYPE} == "ntfs" ]]; then
        OPTS+=",user,users,umask=000,allow_other"
    else
       CHMOD=yes
    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} ****"
    if [ "${CHMOD}" = "yes" ];then
        /usr/bin/find "${MOUNT_POINT}" -type f -exec chmod 0666 {} \;
        /usr/bin/find "${MOUNT_POINT}" -type d -exec chmod 0777 {} \;
    fi
}

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

Orijinal cevap ile sizinkiler arasında farklı olanı birkaç kelimeyle açıklamak isteyebilirsiniz, daha kullanışlı hale getirmek için. PS: Warren Young'ın cevabı yoktu; belki de Mike Blackwell'in düzenlenen cevabını kastettin?
Amir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.