在 Debian 上自动挂载 USB 记忆棒

在 Debian 上自动挂载 USB 记忆棒

我在一台即插即用的计算机上运行 Debian Squeeze(因此只有 SSH,没有 GUI),我想要做的就是获取它,以便在插入 USB 记忆棒时,它会自动安装。

我所做的是安装autofs,根据我收集的信息处理自动安装,前提是它知道设备所在的位置/dev

问题是 USB 记忆棒并不总是位于相同的设备名称上。有时是/dev/sdc1,有时/dev/sdd1,等等。

我认为为了解决这个问题,我需要使用它udev来确保 USB 记忆棒始终具有相同的名称。

我从中得到以下信息udevadm

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/block/sdd/sdd1':
    KERNEL=="sdd1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{partition}=="1"
    ATTR{start}=="63"
    ATTR{size}=="129339"
    ATTR{ro}=="0"
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="0"
    ATTR{stat}=="      31      244      275      190        0        0        0        0        0      190      190"
    ATTR{inflight}=="       0        0"

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0/block/sdd':
    KERNELS=="sdd"
    SUBSYSTEMS=="block"
    DRIVERS==""
    ATTRS{range}=="16"
    ATTRS{ext_range}=="256"
    ATTRS{removable}=="1"
    ATTRS{ro}=="0"
    ATTRS{size}=="129439"
    ATTRS{alignment_offset}=="0"
    ATTRS{discard_alignment}=="0"
    ATTRS{capability}=="51"
    ATTRS{stat}=="      56      727      783      520        0        0        0        0        0      520      520"
    ATTRS{inflight}=="       0        0"
    ATTRS{events}=="media_change"
    ATTRS{events_async}==""
    ATTRS{events_poll_msecs}=="-1"

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0/8:0:0:0':
    KERNELS=="8:0:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{device_blocked}=="0"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="3"
    ATTRS{vendor}=="        "
    ATTRS{model}=="Flash Disk      "
    ATTRS{rev}=="2.00"
    ATTRS{state}=="running"
    ATTRS{timeout}=="30"
    ATTRS{iocounterbits}=="32"
    ATTRS{iorequest_cnt}=="0x90"
    ATTRS{iodone_cnt}=="0x90"
    ATTRS{ioerr_cnt}=="0x0"
    ATTRS{modalias}=="scsi:t-0x00"
    ATTRS{evt_media_change}=="0"
    ATTRS{queue_depth}=="1"
    ATTRS{queue_type}=="none"
    ATTRS{max_sectors}=="240"

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0/host8/target8:0:0':
    KERNELS=="target8:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0/host8':
    KERNELS=="host8"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2/1-1.2:1.0':
    KERNELS=="1-1.2:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb-storage"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{bInterfaceClass}=="08"
    ATTRS{bInterfaceSubClass}=="06"
    ATTRS{bInterfaceProtocol}=="50"
    ATTRS{modalias}=="usb:v1976p6025d0100dc00dsc00dp00ic08isc06ip50"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1/1-1.2':
    KERNELS=="1-1.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{urbnum}=="383"
    ATTRS{idVendor}=="1976"
    ATTRS{idProduct}=="6025"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="11"
    ATTRS{devpath}=="1.2"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"

  looking at parent device '/devices/platform/orion-ehci.0/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{urbnum}=="197"
    ATTRS{idVendor}=="1a40"
    ATTRS{idProduct}=="0101"
    ATTRS{bcdDevice}=="0111"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="2"
    ATTRS{devpath}=="1"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="4"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{product}=="USB 2.0 Hub"

  looking at parent device '/devices/platform/orion-ehci.0/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="24"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"
    ATTRS{bcdDevice}=="0206"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="1"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 2.6.38.8 ehci_hcd"
    ATTRS{product}=="Marvell Orion EHCI"
    ATTRS{serial}=="orion-ehci.0"
    ATTRS{authorized_default}=="1"

  looking at parent device '/devices/platform/orion-ehci.0':
    KERNELS=="orion-ehci.0"
    SUBSYSTEMS=="platform"
    DRIVERS=="orion-ehci"
    ATTRS{modalias}=="platform:orion-ehci"

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

我一直在尝试编写udev规则来强制 USB 记忆棒采用该名称/dev/usbstick,但到目前为止我还没有成功。

有人可以帮助我在规则文件中指定什么规则才能使该 USB 记忆棒始终获得相同的名称吗?

-- 或者,是否有更简单的方法来自动安装我完全丢失的 USB 记忆棒?

更新

好的,我已经取得了一些进展。我添加了以下规则:

SUBSYSTEMS=="scsi", ATTRS{model}=="Flash Disk ", DRIVERS=="sd", NAME="usbstick-%k" RUN+="mkdir /mnt/usbstick-%k; mount /dev/usbstick-%k /mnt/usbstick-%k"

我知道这在处理添加/删除方面仍然需要一些工作,但这只是现在的基本测试。

这样做的效果是,我现在设法在 中获得三个新的设备节点/dev,即/dev/usbstick-sdc/dev/usbstick-sdc1usbstick-sg2

但是,我发现该RUN部分中的代码仅执行一次并且仅创建一个目录mnt/usbstick-sdc。我还发现该目录始终是空的,所以显然仍然出了问题! (尽管我正在取得进步)。

答案1

我认为应该有一种更简单的方法来解决这种常见问题,而且确实存在。这是我在 wheezy/sid 服务器上尝试过的:

sudo apt-get install usbmount

插入U盘,完成!我的手杖现在可以通过 访问/media/usb

顺便说一句,usbmount 没有手册页,请阅读/usr/share/doc/usbmount/README.gz。默认情况下,usbmount 似乎使用同步选项安装你的棒。对于你的棒来说,异步安装并运行sync或拔掉它之前运行可能会更好umount。这是可配置的。

答案2

请注意,您不能只用一个设备节点来表示任何可能已连接随身碟。如果插入两个怎么办?或者当随身碟有多个分区时?

通常,您用来创建自定义命名的设备节点的是SYMLINK+=.在规则中 grep 查找它,看看它是如何使用的:grep SYMLINK /etc/udev/rules.d/*.与所有 udev 触发的命令一样,您可以使用 中描述的一些有意义的变量man udev。您可能会意识到您实际上并不需要为设备指定自定义名称,因为您可以将其名称提供给脚本(通过变量%k)。

至于自动挂载的解决方案,看看城市空中交通管理局,我已经在其中描述了一点这个问题的答案

答案3

这是我最近的做法,我现在对这种方法非常满意。这是针对 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] 
# for automounter support

ACTION=="add", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", \
    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", \
    SYMLINK+="usbdisks/%k", MODE:="0660"


# When device is removed, also remove /media/usb/<...>
ACTION=="remove", KERNEL=="sd*", ENV{DEVTYPE}=="partition", \
    ENV{ID_BUS}=="usb", \
    RUN+="/bin/rm /media/usb/%k"

这是做什么的:它创建两个符号链接,一个用于“/dev/usbdisks/<...>”下的 USB 存储设备分区。

第二个符号链接将从“/media/usb/<...>”链接到“/media/autousb/<...>”,这是为了自动安装程序支持(请参阅步骤 2)。

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

sudo udevadm control --reload-rules

注意:同一个 U 盘具有相同的名称:可能但可能危险:您可以使用例如“$env{ID_FS_LABEL_ENC}”,而不是上述 UDEV 规则中的“%k”。这将使用卷标创建 /media/usb/<...>,但是如果您插入两个 USB 记忆棒并且都使用相同的卷标,会发生什么情况...

使用此 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”和“ext4”文件系统的示例代码。当然,扩展它以支持更多文件系统是很容易的。

步骤3)

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

#!/bin/bash
# make sure everything is written to USB disk(s)
sync
# sending SIUGSR1 to automount will unmount the media
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 记忆棒,即使这些分区使用不同的文件系统类型。

答案4

我发现最好的答案实际上已被弃用,因为它没有得到维护,并且无法在 Jessie 上/从 Jessie 上工作(请参阅 malat 的评论)

对我(杰西)来说,解决方案是这个博客就像魅力一样。

感谢“ddumont”,但在这里发布了他的博客/答案的概述,以应对将来可能出现的链接失效问题。

将以下行添加到/etc/fstab

/dev/sr0 /media/bluray auto defaults,nofail,x-systemd.automount 0 2

您可以使用 nano 来做到这一点:

sudo nano /etc/fstab

解释:

/dev/sr0是设备文件。您还可以使用 udev 在 /dev/disk/by-id 中设置的符号链接之一。您必须根据您的设备文件更改此设置(sudo fdisk -l以列出设备)

/media/bluray是挂载点。您可以选择其他挂载点

nofail需要避免在光驱中无光盘启动时出现故障报告

x-systemd.automount是配置 systemd 自动挂载插入的光盘的选项

不要指定 noauto:这会阻止 systemd 自动挂载光盘,从而达不到目的。

测试

journalctl -x -f在终端中运行命令来检查 systemd 发生了什么

使用 重新加载 systemd 配置sudo systemctl daemon-reload

将光盘放入光驱中

然后,journalctl 应该显示如下内容:

Sept. 27 16:07:01 frodo systemd[1]: Mounted /media/bluray.

更远

为了成功挂载 NTFS 驱动器,我必须安装 ntfs-3g(旧的 ntfsprogs)

sudo apt-get install ntfs-3g

我不必安装 hfsprogs 即可使 OSX 格式的 USB 工作,但您应该自己检查一下。

相关内容