Unidades USB automount com systemd

19

Estamos atualizando nossos servidores de uma distro muito desatualizada para um sistema moderno baseado no Debian Jessie, incluindo lightdm / xfce e, claro, systemd (e udisks2). Um ponto de atrito é a montagem automática de drives USB. Costumávamos fazer isso com algumas regras do udev. As regras antigas quase continuam funcionando - o ponto de montagem é criado e a unidade é montada corretamente, mas após alguns segundos o systemd está fazendo algo que quebra a montagem, para que as tentativas de acesso subseqüentes resultem em erros "O ponto final do transporte não está conectado". p>

A montagem manual da unidade através da linha de comando funciona bem. Então, deixar um gerenciador de arquivos (thunar e thunar-volman, que por sua vez usa o udisks2). Mas essas opções não são viáveis - na maioria das vezes, esses sistemas são executados sem problemas, portanto, o Thunar não é executado normalmente. Precisamos ser capazes de conectar drives de disco para backups autônomos baseados em cron.

Eu achei que modificar o script do udev para gerar um trabalho desanexado que aguarda alguns segundos antes de executar a montagem, pode fazer o truque, mas o systemd parece sair de seu caminho para evitar isso - de alguma forma ainda aguarda o trabalho desanexado para terminar antes de continuar.

Talvez ter o script udev fazendo cócegas em udisks2 de alguma forma seja a abordagem correta? Estou perdendo, então qualquer conselho muito apreciado.

    
por Mike Blackwell 28.03.2016 / 17:35

3 respostas

19

Depois de vários falsos inícios, percebi isso. A chave é adicionar um serviço de unidade do systemd entre o udev e um script de montagem.

(Para o registro, eu não consegui fazer isso funcionar usando o udisks2 (via algo como udisksctl mount -b /dev/sdb1 ) chamado diretamente de uma regra do udev ou de um arquivo de unidade do systemd. Parece haver uma condição de corrida e o dispositivo nó não está pronto, resultando em Error looking up object for device /dev/sdb1 . Infelizmente, já que o udisks2 pode cuidar de toda a bagunça do ponto de montagem ...)

O trabalho pesado é feito por um script de shell, que cuida da criação e remoção de pontos de montagem e montagem e desmontagem das 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

O script, por sua vez, é chamado por um arquivo de unidade do systemd. Usamos a sintaxe do nome de arquivo "@" para podermos passar o nome do dispositivo como um 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, algumas regras do udev iniciam e param o serviço de unidade do systemd no hotplug / unplug:

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

Isso parece fazer o truque! Um par de comandos úteis para depurar coisas como esta:

  • udevadm control -l debug ativa o registro detalhado para /var/log/syslog para que você possa ver o que está acontecendo.
  • udevadm control --reload-rules depois de modificar os arquivos no rules.d dir (pode não ser necessário, mas não pode ferir ...).
  • systemctl daemon-reload depois de modificar os arquivos da unidade systemd.
por 30.03.2016 / 17:26
9

há uma nova opção de montagem automática systemd sucinta, que pode ser usada com fstab , que permite usar todas as opções de permissão de montagem padronizadas, e é assim:

  x-systemd.automount

um exemplo disso em uma linha fstab :

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

a opção noauto significará que ela não tentará ser montada na inicialização, como no software antigo autofs .

depois de adicionar uma nova linha x-systemd.automount a fstab , você precisa executar:

  sudo systemctl daemon-reload

e depois ambos ou um dos seguintes:

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

para mais informações sobre isso:

link

    
por 20.09.2016 / 14:31
2

Eu modifiquei o script de @MikeBlackwell para:

  • reconhece nomes de dispositivos que abrangem vários caracteres, não apenas /dev/sd[a-z] mas /dev/sd[a-z]* ; geralmente é o caso de servidores com maior número de eixos.
  • acompanhe a lista de unidades montadas automaticamente em /var/log/usb-mount.track
  • registre as ações em /var/log/messages com a tag usb-mount.sh
  • prefixo nome do dispositivo com o rótulo do dispositivo para o ponto de montagem para não entrar em problemas com unidades que não receberam um rótulo (vazio?): /media/sdd2_usbtest , /media/sdd2_
  • scripts wrapper incluídos para colocar os arquivos adequadamente e desfazer se necessário

Como o @MikeBlackwell já fez a maior parte do trabalho pesado, optei por não reescrevê-lo; apenas fiz as alterações necessárias. Eu reconheci seu trabalho avistando seu nome e URI da resposta original.

Encontre-o em link

    
por 04.11.2017 / 21:18