GNU/Linux >> Tutoriales Linux >  >> Linux

Unidades USB de montaje automático con systemd

Solución 1:

Después de varios comienzos en falso, descubrí esto. La clave es agregar un servicio de unidad systemd entre udev y un script de montaje.

(Para que conste, no pude hacer que esto funcionara usando udisks2 (a través de algo como udisksctl mount -b /dev/sdb1 ) llamado directamente desde una regla udev o desde un archivo de unidad systemd. Parece haber una condición de carrera y el nodo del dispositivo aún no está listo, lo que da como resultado Error looking up object for device /dev/sdb1 . Lamentablemente, ya que udisks2 podría encargarse de todo el desorden del punto de montaje...)

El trabajo pesado lo realiza un script de shell, que se encarga de crear y eliminar puntos de montaje, y de montar y desmontar las unidades.

/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

El script, a su vez, es llamado por un archivo de unidad systemd. Usamos la sintaxis de nombre de archivo "@" para poder pasar el nombre del dispositivo como argumento.

/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

Finalmente, algunas reglas de udev inician y detienen el servicio de la unidad systemd en 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"

¡Esto parece funcionar! Un par de comandos útiles para depurar cosas como esta:

  • udevadm control -l debug activa el registro detallado en /var/log/syslog para que pueda ver lo que está sucediendo.
  • udevadm control --reload-rules después de modificar los archivos en el directorio therules.d (puede que no sea necesario, pero no hace daño...).
  • systemctl daemon-reload después de modificar los archivos de la unidad systemd.

Solución 2:

hay un nuevo y sucinto systemd opción de montaje automático que se puede usar con fstab que le permite usar todas las opciones de permisos de montaje estandarizados, y se ve así:

  x-systemd.automount

un ejemplo de ello en un fstab línea:

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

el noauto significará que no intentará montarse en el arranque, como con el software anterior autofs .

después de agregar un nuevo x-systemd.automount línea a fstab entonces necesitas ejecutar:

  sudo systemctl daemon-reload

y luego ambos, o uno de los siguientes:

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

para más información al respecto:

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

Solución 3:

Usando pmount , systemd y el enfoque de Mike Blackwell, puede simplificar todo:

/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 y gracias Mike.

Solución 4:

He modificado el guión de @MikeBlackwell a:

  • reconocer nombres de dispositivos que abarcan varios caracteres, no solo /dev/sd[a-z] pero /dev/sd[a-z]*; suele ser el caso de los servidores que tienen una mayor cantidad de ejes.
  • seguimiento de la lista de unidades montadas automáticamente en /var/log/usb-mount.track
  • registrar las acciones en /var/log/messages con la etiqueta usb-mount.sh
  • prefije el nombre del dispositivo con la etiqueta del dispositivo para que el punto de montaje no tenga problemas con las unidades a las que no se les ha asignado una etiqueta (¿vacío?):/media/sdd2_usbtest , /media/sdd2_
  • incluye secuencias de comandos de contenedor para colocar los archivos correctamente y deshacer si es necesario

Dado que @MikeBlackwell ya ha hecho la mayor parte del trabajo pesado, opté por no reescribirlo; acaba de hacer los cambios necesarios. He reconocido su trabajo viendo su nombre y URI de la respuesta original.

Encuéntralo en https://github.com/raamsri/automount-usb

Solución 5:

Iría con la respuesta de Warren Young. Tengo algunos cambios que hice

Agregué algo de protección de espacio ya que estaba dando errores de la evaluación del entorno para la unidad.

Agregué una sección para modificar un disco USB para que todos los usuarios tengan acceso completo a discos que no sean 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

Linux
  1. Administrar recursos con cgroups en systemd

  2. Cómo montar una memoria USB como usuario no root con permiso de escritura

  3. Cómo montar y desmontar unidades en Linux

  4. ¿Montaje automático USB de Debian?

  5. ¿Arranque no gráfico con Systemd?

Cómo crear unidades USB de arranque múltiple con Ventoy en Linux

Cree unidades USB de arranque y tarjetas SD con Etcher en Linux

Ordenar la gestión de procesos con ps o systemd

Administrar cgroups con systemd

Montar una carpeta remota con sshfs

Comando de montaje de Linux con ejemplos