eject /dev/sdb1 有时不生效,因其仅对可弹出设备有效,依赖scsi指令,而多数usb设备(尤其uas协议)不响应;且eject会先尝试umount,若设备被进程、shell工作目录或桌面环境占用则失败。

直接用 eject 命令最可靠,但必须先确保设备没被进程占用、没挂载在关键路径下,否则会失败或静默无效。
为什么 eject /dev/sdb1 有时不生效?
因为 eject 默认只对“可弹出设备”起作用——它依赖 SCSI 层的 START_STOP 或 ALLOW_MEDIUM_REMOVAL 指令,而很多 USB 设备(尤其是 UAS 协议设备)并不响应这些指令。更常见的是:eject 会尝试先 umount,但若设备正被 shell 当前工作目录、tail -f、编辑器缓存、或 systemd-udevd 扫描占用,umount 就会失败,eject 随即中止。
- 运行
lsof +D /mnt/usb或fuser -v /mnt/usb查占用进程(替换为你的挂载点) - 切出当前目录:
cd /,避免 shell 把挂载点当工作路径锁住 - 如果挂载点是
/media/xxx,注意 GNOME/KDE 可能后台扫描缩略图,需等几秒再试
udisksctl power-off 是更现代的替代方案
Ubuntu/Debian/Fedora 等主流发行版默认启用 udisks2,它比 eject 更懂 USB 存储的物理断电逻辑,尤其对 UAS 设备支持更好。它会先卸载、同步缓存、再向内核发电源关闭请求。
- 查设备路径:
lsblk -o NAME,TRAN,MOUNTPOINT,找TRAN=usb且有挂载点的项(如sdb1) - 执行:
udisksctl power-off -b /dev/sdb(注意:传整个磁盘/dev/sdb,不是分区/dev/sdb1) - 成功后,
ls /sys/block/里将看不到sdb,dmesg | tail会显示 “power off” 相关日志
遇到 “Target is busy” 怎么强制清理?
这不是该硬上 -f,而是要定位并释放真实占用源。常见陷阱包括:
-
mount | grep sdb看是否还有子挂载(比如 LVM 逻辑卷、bind mount)未卸载 -
cat /proc/mounts | grep sdb比mount更底层,可能发现已隐藏的挂载 - 某些备份工具(如
rsync --delete进程)或 Docker 卷会保持文件描述符打开,需kill对应 PID - 别忽略
/dev/sdb本身被dd、fdisk或hdparm类工具打开的情况——哪怕没挂载,设备文件被 open 就无法弹出
真正安全的弹出,从来不是靠一个命令搞定;它取决于你是否确认缓存已刷写、所有句柄已关闭、内核已放弃该设备。图形界面点一下“弹出”,背后也是调用 udisksctl 并等待完整流程结束——手动操作时,少跳过任何一步检查,就是最省时间的做法。











