问题
在我的 USB 驱动器 (/dev/sdd) 上使用以下命令后:
# physically plugging usb-drive in at /dev/sdd
> umount /dev/sdd1
> eject /dev/sdd
我无法撤消最后的操作。如何以编程方式再次安装驱动器?
无法对设备进行物理访问,也无法重新启动。
你尝试了什么?
正如您将看到的,常规的东西不起作用。
> mount /dev/sdd1
mount: /dev/sdd1: can't find in /etc/fstab.
我们可以看到/dev/sdd1
已经不存在了:
> ls /dev/sdd*
/dev/sdd
因此,让我们尝试再次使用相同的实用程序来撤消弹出操作:
> eject --trayclose /dev/sdd
> ls /dev/sdd*
/dev/sdd
这似乎没有做任何事情,所以让我们将 USB 驱动器绑定到驱动程序。
> udevadm info /dev/sdd | grep DEVPATH
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0/block/sdd
> echo -n "1-1:1.0" > /sys/bus/usb/drivers/usb-storage/unbind
> ls -d /sys/bus/usb/drivers/usb-storage/1-1\:1.0
ls: cannot access '/sys/bus/usb/drivers/usb-storage/1-1:1.0': No such file or directory
> echo -n "1-1:1.0" > /sys/bus/usb/drivers/usb-storage/bind
> ls -d /sys/bus/usb/drivers/usb-storage/1-1\:1.0
1-1:1.0
好的,解除绑定和绑定成功了。这不是问题,也不是解决方案。此外,该设备似乎仍然通电。让我们尝试触发一些东西。
> udevadm trigger --name-match=/dev/sdd
这似乎也不能解决问题。现在让我们再次尝试读取分区表,因为/dev/sdd
存在但/dev/sdd1
不存在。我发现了三种不同的方法来实现这一目标:
> partprobe /dev/sdd
Error: Error opening /dev/sdd: No medium found
> hdparm -z /dev/sdd
/dev/sdd:
re-reading partition table
> partx -u /dev/sdd
partx: cannot open /dev/sdd: No medium found
> ls /dev/sdd*
/dev/sdd
仍然没有/dev/sdd1
。也许尝试重新扫描:
> echo 1 > /sys/block/sdd/device/rescan
> ls /dev/sdd*
/dev/sdd
还是什么都没有,让我们验证一下fdisk
这句话是怎么说的:
> fdisk -l | grep sdd
好吧,没什么。然后我们尝试重置 USB 驱动器。
> echo 0 > /sys/bus/usb/devices/1-1\:1.0/authorized
> echo 1 > /sys/bus/usb/devices/1-1\:1.0/authorized
> ls /dev/sdd*
ls: cannot access '/dev/sdd*': No such file or directory
这让事情变得更糟,反复试验失败了。我放弃。我在这里缺少什么?
*捂脸*eject
到底为什么?!
好吧,我实际上需要这个解决方案来解决另一个问题,即 Linux 在发生 I/O 错误后不再希望挂载 USB 驱动器。由于物理地重新插入 USB 驱动器可以解决该问题,因此我需要知道如何以编程方式执行此操作。即使这不能解决我原来的问题,我想知道如何撤消eject
。
编辑:更多细节
这是来自的额外来源kernel.org 关于 USB 热插拔,告诉应该发生什么:
- 找到可以处理该设备的驱动程序。这可能涉及加载内核模块;较新的驱动程序可以使用 module-init-tools 将其设备(和类)支持发布给用户实用程序。
- 将驱动程序绑定到该设备。总线框架使用设备驱动程序的probe()例程来做到这一点。
- 告诉其他子系统配置新设备。可能需要启用打印队列、启动网络、安装磁盘分区等等。在某些情况下,这些将是特定于驾驶员的操作。
看来最后一步可能还需要做。由有关 USB 驱动器“弹出”后状态的进一步信息支持,显示 USB 驱动器已通电并且 Linux 可以与其通信:
> cat /sys/block/sdd/device/state
running
> cat /sys/block/sdd/device/power/runtime_status
active
> cat /sys/block/sdd/device/power/runtime_suspended_time
0
> cat /sys/block/sdd/device/power/control
on
答案1
如果设备不是 CDROM 驱动器,eject
则回退到通用 SCSI“START STOP”命令,并设置选项“eject”。
可以使用“start”选项发送相反的“START STOP” sg_start -s
。 sg_start 在大多数发行版上作为 sg3_utils 包的一部分提供。
在这种情况下,显然sg_start -s
足以重新启动驱动器。 sg_start --load
不需要。(这对我来说很有意义,因为我不认为这是弹出操作已经发生)。
其他用户声称这不起作用。 USB 驱动器控制器(尤其是小型闪存驱动器)可能有点奇怪,因此如果某些驱动器拒绝此命令,我不会感到惊讶。
https://unix.stackexchange.com/a/394961/29483
闪存 ROM 棒中的 USB 控制器通常会通过关闭设备电源并阻止任何进一步的交互来做出反应。这意味着它从 USB 子系统中完全消失,并且必须重新枚举才能再次访问。
例如,当发送到 CD/DVD 驱动器时,相同的命令将弹出磁盘,并且“START STOP”命令的现有“加载”选项将再次加载它。但这种解释仅适用于具有可移动介质的设备。