如何卸载繁忙的设备


243

我有一些桑巴驱动器,每天都有多个用户在访问。我已经有代码(从SQL表中)识别共享驱动器,并将它们安装在所有用户都可以访问它们的特殊目录中。

我想知道,如果我从SQL表中删除驱动器(有效地使其脱机),如何甚至没有办法卸载繁忙的设备?到目前为止,我发现任何形式的umount都不起作用。

忽略破坏数据的可能性-是否可以卸载当前正在读取的设备?


3
可以找到更通用的答案,以解决导致umount失败的更多原因的信息,请参见oletange.blogspot.dk/2012/04/umount-device-is-busy-why.html
Ole Tange

2
您好,可能您cd挂载了dir,然后您成为root用户或再次登录,然后又陷入了另一个shell。难道exit所有的炮弹。
Smeterlink

Answers:


455

是!!有一种方法可以立即分离繁忙的设备(即使它很忙并且无法强行卸下)。您可以稍后清除所有内容:

umount -l /PATH/OF/BUSY-DEVICE
umount -f /PATH/OF/BUSY-NFS(NETWORK-FILE-SYSTEM)

注意:

  1. 这些命令可能会破坏正在运行的进程,导致数据丢失或损坏的打开文件。强制卸载后,访问目标DEVICE / NFS文件的程序可能会引发错误或无法正常工作。
  2. 如果不在已安装的文件夹/驱动器/设备中,请尝试执行这些命令。

22
注意:-l这是小写字母L(用于“懒惰卸载”)。(见本相关的答案。)
ジョージ

4
工作了 一个细微的差别,如果您通过FTP客户端登录,则必须注销才能成功卸载文件夹。
亚历山大·金

他们不工作。他们俩都永远吊死。(Debian 8,cifs-utils 2:
6.4-1

1
-l/ --lazy不会破坏打开的文件,但是在Linux上,
Tom Hale

1
有点吓人。我懒地卸载,然后在仍然有其他进程访问它的同时重新装载。所以我想我到底将它安装了两次到同一位置?不知道那是什么。
sudo

120

如果可能,让我们找到/确定繁忙的进程,终止进程,然后卸下samba共享以最大程度地减少损坏。

  • lsof | grep '<mountpoint of /dev/sda1>' (或任何已安装的设备)

  • pkill target_process(按名称| kill PID| 杀死繁忙的进程。killall target_process

  • umount /dev/sda1 (或任何已安装的设备)


6
那什么也不会返回。我之所以假设它是因为它是网络驱动器,所以看不到其他计算机访问该驱动器的过程。同样处理“ fuser”命令。
马克斯

哦,天哪...您需要使用samba命令... / usr / bin / smbclient服务<密码>:看看是否可以开始使用... tldp.org/HOWTO/SMB-HOWTO-8.html
Frank Tudor

2
smb命令实际上已被弃用,并由“ umount.cifs” ....代替,该命令也不起作用。看来我一直忙于无法卸载。
最多

如果您使用的是Asuswrt-Merlin,则需要安装lsof# opkg install lsof
Tonatio

1
您需要使用sudo lsof才能获得一些结果
aheigins

78

尝试卸载时,请确保您还没有处于已挂载的设备中。


4
确实,只需在终端中打开当前文件夹(位于目标设备上)(通过例如cd命令)就可以停止该进程:)
jave.web

2
是的,我在设备的目录中运行了一个shell。关闭了终端窗口,瞧
sh78 '18

另外,请确保您要尝试的安装点内没有其他安装点umount
胜利

@victe谢谢;我正在Solaris 11上使用pfexec mount -F vboxfs carpetacompartida〜/ Documents替换文件夹;但是文档有子文件夹,这就是问题所在。
Dani Aya

44

请尝试以下操作,但是在运行它之前,请注意该-k标志将终止所有正在运行的进程,从而使设备忙碌。

-i标志使fuser杀害前询问。

fuser -kim /address  # kill any processes accessing file
unmount /address

5
lsof | grep '/dev/<my-device>没有返回任何东西,但是效果很好!可能还想提出一些建议fuser -m /dev/<my-device>,以防您想在杀死进程之前查明该进程。
modulitos '16

3
运行fuser命令立即使我与VPS断开连接。
giorgio79 '16

21

避免 umount -l

在撰写本文时,最受好评的答案建议使用umount -l

umount -l是危险的,或至多是不安全的。综上所述:

  • 它实际上并没有卸载设备,只是从名称空间中删除了文件系统。打开文件的写入可以继续。
  • 可能导致btrfs文件系统损坏

解决/替代

的有用行为umount -l是通过绝对路径名将文件系统隐藏起来,以防止访问,从而最大程度地减少了对moutpoint的使用。

通过装入具有000要卸载目录权限的空目录,可以实现相同的行为。

然后,对安装点下方的文件名的任何新访问都将以零权限进入新覆盖的目录-从而防止了对卸载的新阻止程序。

首先尝试 remount,ro

要解锁的主要卸载成就是只读的重新装载。获得remount,ro徽章后,您将知道:

  1. 所有未决数据已写入磁盘
  2. 所有未来的写入尝试都将失败
  3. 如果您需要物理断开设备连接,则数据处于一致状态。

mount -o remount,ro /dev/device 如果打开了要写入的文件,则肯定会失败,因此请尝试直接进行操作。朋克,您可能会感到幸运!

如果您不走运,请只关注打开了可写文件的进程

lsof +f -- /dev/<devicename> | awk 'NR==1 || $4~/[0-9]+[uw -]/'

然后,您应该能够以只读方式重新安装设备并确保状态一致。

如果此时您无法重新安装只读,请调查此处列出的其他可能原因。

只读的重新安装成就已解锁🔓☑

恭喜,您在挂载点上的数据现在是一致的,并且可以防止将来写入。

为什么fuser不如lsof

为什么不使用fuser更早使用?好吧,您可以拥有fuser一个目录,但可以 在一个设备上运行,而不是在设备上运行,因此,如果您想从文件名空间中删除挂载点并仍然使用fuser,则需要:

  1. 临时将安装点复制mount -o bind /media/hdd /mnt到另一个位置
  2. 隐藏原始安装点并阻止名称空间:

这是如何做:

null_dir=$(sudo mktemp --directory --tmpdir empty.XXXXX")
sudo chmod 000 "$null_dir"

# A request to remount,ro will fail on a `-o bind,ro` duplicate if there are
# still files open for writing on the original as each mounted instance is
# checked.  https://unix.stackexchange.com/a/386570/143394
# So, avoid remount, and bind mount instead:
sudo mount -o bind,ro "$original" "$original_duplicate"

# Don't propagate/mirror the empty directory just about hide the original
sudo mount --make-private "$original_duplicate"

# Hide the original mountpoint
sudo mount -o bind,ro "$null_dir" "$original"

然后,您将拥有:

  1. 原始名称空间被隐藏(无法打开更多文件,问题不会变得更糟)
  2. 要在其上运行的重复绑定安装目录(相对于设备)fuser

这比较复杂[1],但允许您使用:

fuser -vmMkiw <mountpoint>

它会交互地要求打开打开的文件来杀死进程。当然,您可以完全不隐藏挂载点来执行此操作,但是以上这些小技巧umount -l不会带来任何危险。

-w开关仅限于编写过程,并且-i是交互式的,因此在只读重新安装后,如果您急着需要,可以使用:

fuser -vmMk <mountpoint>

杀死所有剩余的进程,并在挂载点下打开文件。

希望此时,您可以卸载设备。(umount如果您已000在顶部将模式目录绑定安装,则需要在安装点上运行两次。)

或使用:

fuser -vmMki <mountpoint>

以交互方式杀死阻止卸载的其余只读进程。

该死,我还是target is busy

打开的文件不是唯一的卸载阻止程序。有关其他原因及其补救措施,请参见此处此处

即使您有一些潜伏的gremlin妨碍了您完全卸载设备,您至少也已使文件系统处于一致状态。

然后,您可以lsof +f -- /dev/device用来列出包含文件系统的设备上带有打开文件的所有进程,然后将其杀死。


[1]使用起来比较费事mount --move,但这需要一定的mount --make-private /parent-mount-point含义。基本上,如果将安装点安装在/文件系统下,则要避免这种情况。


1
如果--lazy是如此危险,为什么umount手册页中没有警告呢?它只说:“ 懒惰卸载。立即从文件层次结构中分离文件系统,并在不再繁忙时立即清除对该文件系统的所有引用。
bitinerant

7

使用exportfs -v检查导出的NFS文件系统。如果找到,请使用exportfs -d share:/ directory删除。这些不会出现在热熔器/ lsof列表中,并且可能阻止卸载成功。


1
感谢您的建议。我必须使用exportfs -ua删除锁。
FuePi

6

签出umount2

Linux 2.1.116添加了umount2()系统调用,该系统调用与umount()一样卸载目标,但允许使用附加标志来控制操作的行为:

MNT_FORCE(从Linux 2.1.116开始)即使在忙时也要强制卸载。(仅适用于NFS挂载。)MNT_DETACH(从Linux 2.4.11开始)执行懒惰卸载:使挂载点不可用于新访问,并在挂载点不再繁忙时实际执行卸载。MNT_EXPIRE(从Linux 2.6.8开始)将安装点标记为已过期。如果当前未使用安装点,则使用此标志的umount2()的初始调用将失败,并显示错误EAGAIN,但会将安装点标记为已过期。只要任何进程都无法访问挂载点,该挂载点就会保持过期状态。第二个umount2()调用指定MNT_EXPIRE来卸载过期的安装点。不能使用MNT_FORCE或MNT_DETACH指定此标志。返回值

成功时,返回零。如果出错,则返回-1,并正确设置errno。


不幸的是,这些不是NFS挂载,而是CIFS。我将尝试MNT_DETACH。但是,如果umount -l不起作用,我无法想象这会有很大不同。不过谢谢!
马克斯

2

有人提到如果您使用终端,并且当前目录位于要卸载的路径内,则会收到错误消息。
作为补充,在这种情况下,您lsof | grep path-to-be-unmounted必须具有以下输出:

bash ... path-to-be-unmounted

1

当一切正常时,另一种选择是编辑/etc/fstab,添加noauto标志并重新启动机器。该设备将不会被挂载,当您完成任何操作后,请移除标志并重新启动。


0

利基答案:

如果该设备上有一个zfs池,至少在它是基于文件的池时,lsof将不会显示使用情况。但是你可以简单地运行

sudo zpool export mypoo

然后卸载。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.