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