Skip to content

Monta automaticamente le unità USB con systemd

Non cercare più su Internet poiché sei nel posto giusto, abbiamo la risposta che devi trovare senza essere coinvolto.

Soluzione:

Soluzione 1:

Dopo diverse false partenze l'ho capito. La chiave è aggiungere un servizio di unità systemd tra udev e uno script di montaggio.

(Per la cronaca, non sono riuscito a farlo funzionare usando udisks2 (tramite qualcosa come udisksctl mount -b /dev/sdb1) chiamato direttamente da una regola udev o da un file unit systemd. Sembra che ci sia una condizione di competizione e il nodo del dispositivo non è ancora pronto, risultando in Error looking up object for device /dev/sdb1. Sfortunatamente, dato che udisks2 potrebbe occuparsi di tutto il disordine del punto di montaggio...)

Il lavoro pesante viene svolto da uno script di shell, che si occupa di creare e rimuovere i punti di montaggio e di montare e smontare le unità.

/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

Lo script, a sua volta, viene richiamato da un file unit systemd. Usiamo la sintassi del nome file "@" in modo da poter passare il nome del dispositivo come argomento.

/etc/systemd/system/[email protected]

[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

Infine, alcune regole udev avviano e interrompono il servizio systemd unit su hotplug/unplug:

/etc/udev/rules.d/99-local.rules

KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/bin/systemctl start [email protected]%k.service"

KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/bin/systemctl stop [email protected]%k.service"

Questo sembra fare il trucco! Un paio di comandi utili per il debug di cose come questa:

  • udevadm control -l debug attiva la registrazione dettagliata a
    /var/log/syslog così puoi vedere cosa sta succedendo.
  • udevadm control --reload-rules dopo aver modificato i file nella directory rules.d (potrebbe non essere necessario, ma non può far male...).
  • systemctl daemon-reload dopo aver modificato i file di unità systemd.

Soluzione 2:

c'è un nuovo, succinto systemd opzione di montaggio automatico che può essere utilizzata con fstab che ti consente di utilizzare tutte le opzioni di autorizzazione di montaggio standardizzate e assomiglia a questo:

  x-systemd.automount

un esempio di esso in un fstab linea:

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

il noauto opzione significherà che non tenterà di essere montato all'avvio, come con il software precedente autofs.

dopo aver aggiunto un nuovo x-systemd.automount linea a fstab è quindi necessario eseguire:

  sudo systemctl daemon-reload

e poi entrambi, o uno, dei seguenti:

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

per maggiori informazioni a riguardo:

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


Soluzione 3:

Usando pmountsystemd e l'approccio di Mike Blackwell, puoi semplificare il tutto:

/etc/systemd/system/[email protected]

[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 [email protected]%k.service"
ACTION=="remove",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl stop [email protected]%k.service"

HTH e grazie Mike.


Soluzione 4:

Ho modificato lo script da @MikeBlackwell a:

  • riconoscere i nomi dei dispositivi che si estendono su più caratteri, non solo /dev/sd[a-z] ma /dev/sd[a-z]*; spesso è il caso di server che hanno un numero maggiore di assi.
  • tenere traccia dell'elenco delle unità montate automaticamente su /var/log/usb-mount.track
  • registrare le azioni in /var/log/messages con etichetta usb-mount.sh
  • prefisso il nome del dispositivo con l'etichetta del dispositivo per il punto di montaggio per non incorrere in problemi con le unità a cui non è stata assegnata un'etichetta (vuota?):/media/sdd2_usbtest, /media/sdd2_
  • includeva script wrapper per posizionare i file in modo appropriato e annullare se necessario

Dato che @MikeBlackwell ha già svolto la maggior parte del lavoro pesante, ho scelto di non riscriverlo; appena apportato le modifiche necessarie. Ho riconosciuto il suo lavoro avvistando il suo nome e l'URI della risposta originale.

Lo trovi su https://github.com/raamsri/automount-usb


Soluzione 5:

Andrei con la risposta di Warren Young a cui ho apportato alcune modifiche

Ho aggiunto un po 'di protezione dello spazio in quanto dava errori dalla valutazione dell'ambiente per l'unità.

Ho aggiunto una sezione a chmod a usb disk in modo che tutti gli utenti abbiano pieno accesso a dischi non ntfs o vfat.

/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

Valutazioni e commenti

Alla fine di tutto puoi trovare le recensioni di altri project manager, hai comunque la libertà di mostrare la tua se padroneggi la materia.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.