如何在插入时自动将可移动媒体挂载到/media/中,而不需要任何桌面环境?

如何在插入时自动将可移动媒体挂载到/media/中,而不需要任何桌面环境?

我有一个 Debian sid 系统(Wheezy)(与 arch 相同),没有任何桌面环境(根本没有 Xorg)。

/media/我可以使用mount/中的标签手动将我的 SD 卡、USB 记忆棒、外部硬盘安装到指定目录中,umount并在 中添加合适的条目/etc/fstab,或者在启动时自动安装,但这是引人注目的,限制性的并且不够动态以满足我的需求:如果我希望将它们安装在 中/media/<LABEL>,则每个具有不同的设备都<LABEL>需要自己的条目,并且每个子目录也<LABEL>需要手动创建/删除)。/media/

那么,安装它们的最佳方法是什么自动地/media/<LABEL> 插入时(并在拔掉它们后立即将它们从文件系统中卸载无论数据的风险有多大)?

理想的解决方案是:

  1. 检测可移动媒体何时插入(即当添加/dev/sdax, sdbx, ... by 时udev
  2. /media/根据其标签(可移动媒体的标签)创建一个目录
  3. 使用选项(对于 a )将其挂载到模式目录中/media/<LABEL>RW如果文件系统支持该模式)flushvfat
  4. 检测媒体是否已拔出
  5. 如果是的话,从文件系统中卸载它
  6. 删除对应的目录/media/

(显然,设备应该以同步模式挂载,以避免由于缓存而热拔出时造成任何数据丢失编辑: syncvfat对于可移动媒体来说太多了所以flush 是作为一种妥协而创建的,安全性低于sync,但根据闪存的生命周期风险较小)

我找到了一些有关autofsHAL、、等udisks的信息,但不清楚哪一个已被弃用或首选,而且无论如何,到目前为止,我还没有弄清楚如何在我的系统上轻松配置它们来做到这一点......udisks2usbmount

答案1

我想你正在寻找pmount

如果您希望在插入时自动安装,请参阅在 Debian 上自动挂载 USB 记忆棒

如果您的系统使用优盘2,这是对插入可移动存储设备做出反应的首选方式。请参阅拱门维基有关 U 盘的配置提示。

否则,当新设备出现时做出反应的程序是乌德夫,因此自动安装是由udev规则。这USB挂载软件包提供了 udev 规则来自动挂载 USB 存储设备和其他一些设备。mount从 udev 规则调用不适用于 FUSE 文件系统(例如 ntfs-3g),因此如果需要,请使用 udisk。

当介质被移除时,您无法自动卸载它们,因为因果关系不是这样的。必须卸载介质它被删除。对于只读介质,您可以在删除后卸载,尽管如果某些应用程序在突然消失的文件系统上打开了文件,这可能会使某些应用程序感到困惑。对于可写媒体,如果拔出已安装的文件系统,则可能会损坏数据。

答案2

这是我最近的做法,我现在对这种方法非常满意。这是针对 Ubuntu 12.04 + gentoo 的,但我想任何允许安装 udev 和 autofs 的发行版都应该可以工作。

先决条件:您必须安装 udev + autofs。

步骤1)

创建以下“/etc/udev/rules.d/90-usbsd-auto.rules”文件(当然,您可以使用任何名称,只要它以“.rules”结尾即可)。 :

# Add symlink /dev/usbdisks/<label> to /dev/sd[a-z][1-9] 
# if partition has a label
# Add symlink /media/usb/<label> to /media/autousb/<label>
# for automounter support
ACTION=="add", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}=="?*", \
    SYMLINK+="usbdisks/$env{ID_FS_LABEL_ENC}", MODE:="0660", \
    RUN+="/bin/rm /media/usb/$env{ID_FS_LABEL_ENC}", \
    RUN+="/bin/ln -sf /media/autousb/$env{ID_FS_LABEL_ENC} /media/usb/$env{ID_FS_LABEL_ENC}"

# Fallback: If partition has a NO label, use kernel name (sd[a-z][1-9])
ACTION=="add", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}!="?*", \
    SYMLINK+="usbdisks/%k", MODE:="0660", \
    RUN+="/bin/rm /media/usb/%k", \
    RUN+="/bin/ln -sf /media/autousb/%k /media/usb/%k"

# Some FileSystems emit a "change" event when they are unmounted.
# UDEV seems to delete the device symlink in this case :-(
# So we need to re-create it here
ACTION=="change", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}=="?*", \
    SYMLINK+="usbdisks/$env{ID_FS_LABEL_ENC}", MODE:="0660"

# Fallback: If partition has NO label, use kernel name
ACTION=="change", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}!="?*", \
    SYMLINK+="usbdisks/%k", MODE:="0660"


# When device is removed, also remove /media/usb/<label>
ACTION=="remove", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}=="?*", \
    RUN+="/bin/rm /media/usb/$env{ID_FS_LABEL_ENC}"

# Fallback: If partition has no label, remove /media/usb/%k
ACTION=="remove", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", ENV{ID_FS_LABEL_ENC}!="?*", \
    RUN+="/bin/rm /media/usb/%k"

这是做什么的:它创建两个符号链接,一个用于“/dev/usbdisks/<...>”下的 USB 存储设备分区。如果没有标签,它将使用 USB 存储分区的标签或内核名称。第二个符号链接将从“/media/usb/<...>”链接到“/media/autousb/<...>”,这是为了自动安装程序支持(请参阅步骤 2)。

注意:我最初没有将规则与 ID_FS_LABEL_ENC 变量一起使用,因为我认为这很危险。如果插入两个使用相同标签的 U 盘会发生什么情况?

但发帖者特意想使用U盘的标签,所以我相应修改了规则。

为了确保 udev 读取这些规则,请使用

sudo udevadm control --reload-rules

使用此 udev 规则文件,一切都已设置为自动挂载 USB 存储设备分区。但请注意,现在该设备不会(故意)自动安装。一旦您使用它,它将自动安装

第2步)

将 autofs 设置为 automount /media/autousb/<...> :我将以下行添加到我的“/etc/auto.master”文件中(对于 Ubuntu 12.04):

/media/autousb /etc/auto.usb --timeout=60

这意味着 AutoFS 将在 60 秒不活动后卸载设备。您可能需要少用或多用,具体取决于您的口味。

对于 Gentoo,你必须修改“/etc/autofs/auto.master”,这样使用才有意义

/media/autousb /etc/autofs/auto.usb --timeout=60

现在我创建了“auto.usb”,内容如下:

#!/bin/bash

key=${1}
fstype=$(/sbin/blkid -o value -s TYPE /dev/usbdisks/${key})
if [ "${fstype}" = "vfat" ] ; then
  echo "-fstype=vfat,sync,uid=0,gid=plugdev,umask=007 :/dev/usbdisks/${key}"
  exit 0
fi
if [ "${fstype}" = "ntfs" ] ; then
  echo "-fstype=fuse.ntfs-3g,sync,uid=0,gid=plugdev,umask=007 :/dev/usbdisks/${key}"
  exit 0
fi
if [ "${fstype}" = "ext4" ] ; then
  echo "-fstype=ext4,sync,nocheck :/dev/usbdisks/${key}"
  exit 0
fi

exit 1

此 auto.usb 需要可执行,以便 autofs 将其用作(bash)脚本。例如

sudo chmod 0755 /etc/auto.usb

这是做什么的:这个脚本将告诉 AutoFS (/usr/sbin/automount) 如何挂载 USB 存储设备分区。

该脚本将首先使用“/sbin/blkid”来查找分区上的文件系统类型。

然后,该脚本将根据设备分区提供正确的安装选项。

注意:我包含了“vfat”(可能最常见的 USB 记忆棒)、“ntfs”和“xfs”文件系统的示例代码。当然,扩展它以支持更多文件系统是很容易的。

步骤 3) 可选...要“弹出”==卸载您的 USB 记忆棒(或 USB 记忆棒上的分区),请在 /sbin/usbeject 下创建一个脚本:

#!/bin/bash
killall -s SIGUSR1 /usr/sbin/automount

通过此脚本,您可以使用“sudo usbeject”卸载所有已安装的 USB 设备分区(通过告诉 automount 卸载它们)。

当然,您可以简单地确保该分区没有在任何地方使用;自动挂载程序将在 60 秒超时后卸载分区...

这里真正的技巧是使用从“/media/usb”到“/media/autousb”的符号链接:

  • “/media/usb”符号链接将由 udev 创建,为用户提供简单的概述,其中有哪些 USB 存储设备分区
  • 如果您通过 /media/usb 使用分区,AutoFS 将按需自动挂载该分区
  • 使用脚本化的“auto.usb”文件,您可以支持任何类型的文件系统,此外您还可以支持任何类型的命名方案。
  • 此方法支持具有多个分区的 USB 记忆棒,即使这些分区使用不同的文件系统类型。

答案3

好吧,已经过去很长时间了,但我仍然会用我目前找到的最佳选择来回答我的问题。总结一下:创建一个udev规则,与一些脚本关联(将创建/删除目录和卸载/安装可移动设备),并附加到udev设备事件 type= partition

1 - 创建添加/删除脚本

将以下脚本保存storage-automount.sh/lib/udev/并使其可执行(sudo chmod a+x /lib/udev/storage-automount.sh):

#!/bin/sh

# set the mountpoint name according to partition or device name
mount_point=$ID_FS_LABEL
if [ -z $mount_point ]; then
    mount_point=${DEVNAME##*/}
fi

# if a plugdev group exist, retrieve it's gid set & it as owner of mountpoint
plugdev_gid="$(grep plugdev /etc/group|cut -f3 -d:)"
if [ -z $plugdev_gid ]; then
    gid=''
else
    chown root:plugdev $mount_point
    gid=",gid=$plugdev_gid"
fi

# create the mountpoint directory in /media/ (if not empty)
if [ -n $mount_point ]; then
    mkdir -p /media/$mount_point
    # other options (breaks POSIX): noatime,nodiratime,nosuid,nodev
    mount -t $ID_FS_TYPE \
      -o rw,flush,user,uid=0$gid,umask=002,dmask=002,fmask=002 \
      $DEVNAME /media/$mount_point
fi

将以下脚本保存storage-autounmount.sh/lib/udev/并使其可执行(sudo chmod a+x /lib/udev/storage-autounmount.sh):

#!/bin/sh

# set the mountpoint name according to partition or device name
mount_point=$ID_FS_LABEL
if [ -z $mount_point ]; then
    mount_point=${DEVNAME##*/}
fi

# remove the mountpoint directory from /media/ (if not empty)
if [ -n $mount_point ]; then
    umount -l /media/$mount_point
    rm -R /media/$mount_point
fi

2 - 创建udev规则以将这些脚本附加到事件

最后,udev在 中添加一条规则/etc/udev/rules.d/,例如85-storage-automount.rules

ENV{DEVTYPE}=="partition", RUN+="/lib/udev/storage-automount.sh", ENV{REMOVE_CMD}="/lib/udev/storage-autounmount.sh"

并使其具有与该目录/文件夹中的其他规则相同的权限

现在,当您插入存储设备时,将根据分区名称创建一个目录/media/(我不记得了,但我认为它也适用于 NTFS 分区),并且您的分区将安装到其中。如果plugdev您的系统上有一个组,那么它对于用户来说是读/写的。此外,这些设备以同步模式安装,以限制热拔插时数据丢失的风险。

当设备被删除时,它被卸载并且目录被删除/media

此外,监视事件的工具udevudevadm monitor,具有以下选项:--env--property

$ udevadm monitor --env

这已经在 debian 和 arch 上经过测试并运行良好,但可能适用于所有依赖udev.

答案4

我认为已经很晚了,但如果有人需要的话我会发布这个:(也是我的第一个 StackExchange 答案)

查了很多地方的解决方案后,我在Arch Wiki中找到了一个简单的解决方案:

链接到拱门维基

我们可以添加 udisks2 规则将默认挂载目录从 更改/run/media/$USER//media/<Label>

添加以下规则,/etc/udev/rules.d/名称如下99-udisks2.rules

ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{UDISKS_FILESYSTEM_SHARED}="1"

然后我们可以安装一个简单的工具,比如乌迪斯基用于自动挂载。

相关内容