https://www.flickr.com/photos/blakespot/6049419030/

Montage Plug-and-Play des clés USB sous Debian sans interface graphique

À la suite de l’article précédent, vous avez peut être choisi d’installer Debian en mode serveur sans interface graphique et de lancer Kodi au démarrage de la machine (encore une fois, un tutoriel sortira bientôt à ce sujet).

Néanmoins vous aurez besoin d’accéder au contenu d’une clé USB dès son branchement à un port USB. Et vous allez être très déçu d’apprendre que nativement sous Linux, les clés USB ne sont pas Plug-and-Play, le montage d’une partition est exclusivement manuel, via /etc/fstab ou via la commande mount.

La raison est toute simple : Linux laisse l’utilisateur libre de choisir les options de montage. Le Plug-and-Play est intégré à plus haut niveau, par les environnements tels que Unity, KDE ou Gnome.

Quand on n’a pas d’environnement de bureau, on doit recourir à un script écoutant les évènements de connexion des périphériques USB et réalisant le montage automatiquement. J’en ai justement trouvé un sur serverfault proposé par Mike Blackwell.

On va créer un fichier /usr/local/bin/usb-mount.sh et lui mettre les droits d’exécution :

#!/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 /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

Puis on créé un fichier /etc/systemd/system/usb-mount@.service pour le service systemd :

[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

On fini en ajoutant des règles au fichier /etc/udev/rules.d/99-local.rules surveillant les évènements de connexion/déconnexion de clés :

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"

Ce script n’est pas parfait, son comportement devient même assez étrange si la partition d’une clé USB n’a pas de nom et qu’on en branche une seconde : les dossiers se mélangent. Arrangez vous pour toujours nommer vos clés, ou proposez moi une correction du script ci-dessus 🙂

Source

Cette série d’articles peut vous intéresser :

  1. Un NAS-médiacenter-seedbox-steambox- PC de salon pour 1000€
  2. Comment prémunir votre NAS contre le maximum de risques
  3. Choix des composants de mon NAS 2017
  4. Montage des composants dans le BitFenix Phenom M version Micro ATX
  5. Mise en place d’un dual-boot en présence d’un RAID
  6. Montage Plug-and-Play des clés USB sous Debian sans interface graphique
  7. Installation de Kodi sur Debian 8 comme interface multimédia
  8. Installation d’OpenMediaVault 3 sur Debian 8 comme interface web d’administration
  9. Installation de Deluge sur Debian 8 comme interface web de téléchargement de torrents
  10. Ruse pour compresser efficacement une image de partition sous Linux

6 commentaires sur “Montage Plug-and-Play des clés USB sous Debian sans interface graphique

  1. J’utilise ce fichier de rules udev 99-automount.rules, trouvée sur le forum debian-fr.org:

    # [b-z] car mon disque dur est en SATA.
    KERNEL!="sd[b-z]*", GOTO="FIN"
    
    # ne jamais laisser une variable d'environnement vide
    ACTION=="add", ENV{mntopt}="-t auto"
    ACTION=="add", ENV{mntpnt}="/media/%k"
    
    # détermination du point de montage et du FS
    ACTION=="add", PROGRAM=="/sbin/blkid -s TYPE -o value %N", RESULT=="vfat",\
            ENV{mntopt}="-t vfat -o uid=1000"
    ACTION=="add", PROGRAM=="/sbin/blkid -s LABEL -o value %N", RESULT!="" \
            ENV{mntpnt}="/media/%c"
    # on vérifie que le point de montage n'est pas déjà utilisé
    # s'il l'est on redéfinit le point de montage à /media/%k qui est unique
    ACTION=="add", PROGRAM!="/bin/mountpoint $env{mntpnt}", \
            GOTO="MONTER"
    ACTION=="add", ENV{mntpnt}="/media/%k"
    
    
    LABEL="MONTER"
    
    # montage commun
    ACTION=="add", KERNEL=="sd[b-z]?", \
            RUN+="/bin/mkdir -p $env{mntpnt}"
    ACTION=="add", KERNEL=="sd[b-z]?", \
            RUN+="/bin/mount $env{mntopt} %N $env{mntpnt}"
    # exception de l'Ipod >.<
    ACTION=="add", SUBSYSTEMS=="usb", ATTRS{product}=="iPod", \
            RUN+="/bin/mkdir $env{mntpnt}"
    ACTION=="add", SUBSYSTEMS=="usb", ATTRS{product}=="iPod", \
            RUN+="/bin/mount $env{mntopt} %N $env{mntpnt}"
    
    # umount commun à tous les périphs
    ACTION=="remove", KERNEL=="sd[b-z]*", \
            RUN+="/bin/umount -l %N"
    ACTION=="remove", KERNEL=="sd[b-z]*", \
            RUN+="/bin/rmdir $env{mntpnt}"
    
    LABEL="FIN"
    
  2. Tu peux faire ça pour éviter le problème des clés non nommées :

    # Figure out a mount point to use
    LABEL=${ID_FS_LABEL}
    if [ -z « $LABEL » ]; then
    LABEL= »USB_$ID_FS_PARTUUID »
    fi

L'espace de discussion de cet article est désormais fermé.