Linux 如何卸载繁忙的设备

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7878707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 06:51:09  来源:igfitidea点击:

How to unmount a busy device

linuxumount

提问by Max

I've got some samba drives that are being accessed by multiple users daily. I already have code to recognize shared drives (from a SQL table) and mount them in a special directory where all users can access them.

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

I want to know, if I remove a drive from my SQL table (effectively taking it offline) how, or even is, there a way to unmount a busy device? So far I've found that any form of umountdoes not work.

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

Ignoring the possibility of destroying data - is it possible to unmount a device that is currently being read?

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

采纳答案by Amit Verma

YES!! There is a way to detach a busy device immediately (even if it is busy and cannot be unmounted forcefully). You may cleanup all later:

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

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

NOTE:

笔记:

  1. These commands can disrupt a running process, cause data loss OR corrupt open files. Programs accessing target DEVICE/NFS files may throw errors OR could not work properly after force unmount.
  2. Try to execute these commands when NOT inside mounted Folder/Drive/Device.
  1. 这些命令可能会中断正在运行的进程、导致数据丢失或损坏打开的文件。访问目标 DEVICE/NFS 文件的程序可能会抛出错误或在强制卸载后无法正常工作。
  2. 当不在安装的文件夹/驱动器/设备中时尝试执行这些命令。

回答by chown

Check out umount2:

退房umount2

Linux 2.1.116 added the umount2() system call, which, like umount(), unmounts a target, but allows additional flags controlling the behaviour of the operation:

MNT_FORCE (since Linux 2.1.116) Force unmount even if busy. (Only for NFS mounts.) MNT_DETACH (since Linux 2.4.11) Perform a lazy unmount: make the mount point unavailable for new accesses, and actually perform the unmount when the mount point ceases to be busy. MNT_EXPIRE (since Linux 2.6.8) Mark the mount point as expired. If a mount point is not currently in use, then an initial call to umount2() with this flag fails with the error EAGAIN, but marks the mount point as expired. The mount point remains expired as long as it isn't accessed by any process. A second umount2() call specifying MNT_EXPIRE unmounts an expired mount point. This flag cannot be specified with either MNT_FORCE or MNT_DETACH. Return Value

On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

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,但会将挂载点标记为已过期。只要没有被任何进程访问,挂载点就会一直过期。指定 MNT_EXPIRE 的第二个 umount2() 调用卸载过期的挂载点。此标志不能用 MNT_FORCE 或 MNT_DETACH 指定。返回值

成功时,返回零。出错时,返回 -1,并适当设置 errno。

回答by Frank Tudor

If possible, let's locate/identify the busy the process, kill the process and then unmount the samba share to minimize damage.

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

  • lsof | grep '<mountpoint of /dev/sda1>'(or whatever the mounted device is)

  • pkill target_process(kills busy proc. by name | kill PID| killall target_process)

  • umount /dev/sda1(or whatever the mounted device is)

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

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

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

回答by numberer6

Check for exported NFS file systems with exportfs -v. If found, remove with exportfs -d share:/directory. These don't show up in the fuser/lsof listing, and can prevent umount from succeeding.

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

回答by user3751769

Try the following, but before running it note that the -kflag will kill any running processes keeping the device busy.

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

The -iflag makes fuserask before killing.

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

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

回答by Luci

Make sure that you aren't still in the mounted device when you are trying to umount.

尝试卸载时,请确保您不在已安装的设备中。

回答by jesjimher

Another alternative when anything works is editing /etc/fstab, adding noautoflag and rebooting the machine. The device won't be mounted, and when you're finished doing whatever, remove flag and reboot again.

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

回答by Tom Hale

Avoid umount -l

避免 umount -l

At the time of writing, the top-voted answer recommends using umount -l.

在撰写本文时,最高投票的答案建议使用umount -l.

umount -lis dangerous or at best unsafe. In summary:

umount -l是危险的,或者充其量是不安全的。总之:

  • It doesn't actually unmount the device, it just removes the filesystem from the namespace. Writes to open files can continue.
  • It can cause btrfs filesystem corruption
  • 它实际上并没有卸载设备,它只是从命名空间中删除文件系统。写入打开的文件可以继续。
  • 它可能导致 btrfs 文件系统损坏

Work around / alternative

变通/替代

The useful behaviour of umount -lis hiding the filesystem from access by absolutepathnames, thereby minimising further moutpoint usage.

的有用行为umount -l是隐藏文件系统以防止绝对路径名访问,从而最大限度地减少进一步使用 moutpoint。

This same behaviour can be achieved by mounting an empty directory with permissions 000over the directory to be unmounted.

同样的行为可以通过挂载一个空目录来实现,000该目录对要卸载的目录具有权限。

Then any new accesses to filenames in the below the mountpoint will hit the newly overlaid directory with zero permissions - new blockers to the unmount are thereby prevented.

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

First try to remount,ro

首先尝试 remount,ro

The major unmount achievement to be unlocked is the read-only remount. When you gain the remount,robadge, you know that:

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

  1. All pending data has been written to disk
  2. All future write attempts will fail
  3. The data is in a consistent state, should you need to physcially disconnect the device.
  1. 所有挂起的数据都已写入磁盘
  2. 以后的所有写入尝试都将失败
  3. 如果您需要物理断开设备,数据处于一致状态。

mount -o remount,ro /dev/deviceis guaranteed to fail if there are files open for writing, so try that straight up. You may be feeling lucky, punk!

mount -o remount,ro /dev/device如果有文件打开进行写入则保证会失败,因此请直接尝试。你可能觉得很幸运,朋克!

If you are unlucky, focus only on processes with files open for writing:

如果您不走运,请仅关注打开文件进行写入的进程

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

You should then be able to remount the device read-only and ensure a consistent state.

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

If you can't remount read-only at this point, investigate some of the other possible causes listed here.

如果此时无法以只读方式重新挂载,请调查此处列出的其他一些可能原因。

Read-only re-mount achievement unlocked ?

只读重装成就解锁?

Congratulations, your data on the mountpoint is now consistent and protected from future writing.

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

Why fuseris inferior to lsof

为什么fuser不如lsof

Why not use use fuserearlier? Well, you could have, but fuseroperates upon a directory, not a device, so if you wanted to remove the mountpoint from the file name space and still use fuser, you'd need to:

为什么不fuser早点使用 use呢?好吧,您可以拥有,但 fuser操作的是directory,而不是device,因此如果您想从文件名空间中删除挂载点并仍然使用fuser,则需要:

  1. Temporarily duplicate the mountpoint with mount -o bind /media/hdd /mntto another location
  2. Hide the original mount point and block the namespace:
  1. 临时将挂载点复制mount -o bind /media/hdd /mnt到另一个位置
  2. 隐藏原始挂载点并阻塞命名空间:

Here's how:

就是这样:

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"

You'd then have:

然后你会有:

  1. The original namespace hidden (no more files could be opened, the problem can't get worse)
  2. A duplicate bind mounted directory (as opposed to a device) on which to run fuser.
  1. 原始命名空间隐藏(无法打开更多文件,问题不会变得更糟)
  2. 在其上运行fuser.

This is more convoluted[1], but allows you to use:

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

fuser -vmMkiw <mountpoint>

which will interactively ask to kill the processes with files open for writing. Of course, you could do this without hiding the mount point at all, but the above mimicks umount -l, without any of the dangers.

它将以交互方式要求终止打开文件进行写入的进程。当然,您可以在完全不隐藏挂载点的情况下执行此操作,但是上述模拟方法umount -l没有任何危险。

The -wswitch restricts to writing processes, and the -iis interactive, so after a read-only remount, if you're it a hurry you could then use:

-w开关仅限于写入进程,并且-i是交互式的,因此在只读重新挂载后,如果您很着急,则可以使用:

fuser -vmMk <mountpoint>

to kill all remaining processes with files open under the mountpoint.

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

Hopefully at this point, you can unmount the device. (You'll need to run umounton the mountpoint twice if you've bind mounted a mode 000directory on top.)

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

Or use:

或使用:

fuser -vmMki <mountpoint>

to interactively kill the remaining read-only processes blocking the unmount.

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

Dammit, I still get target is busy!

该死的,我还是明白了target is busy

Open files aren't the only unmount blocker. See hereand herefor other causes and their remedies.

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

Even if you've got some lurking gremlin which is preventing you from fully unmounting the device, you have at least got your filesystem in a consistent state.

即使你有一些潜伏的小精灵阻止你完全卸载设备,你至少让你的文件系统处于一致的状态。

You can then use lsof +f -- /dev/deviceto list all processes with open files on the device containing the filesystem, and then kill them.

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



[1] It is less convoluted to use mount --move, but that requires mount --make-private /parent-mount-pointwhich has implications. Basically, if the mountpoint is mounted under the /filesystem, you'd want to avoid this.

[1] 使用 不那么复杂mount --move,但这需要mount --make-private /parent-mount-point具有含义的。基本上,如果挂载点挂载在/文件系统下,您应该避免这种情况。

回答by Eugene

Someone has mentioned that if you are using terminal and your current directory is inside the path which you want to unmount, you will get the error.
As a complementary, in this case, your lsof | grep path-to-be-unmountedmust have below output:

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

bash ... path-to-be-unmounted

回答by lucidbrot

Niche Answer:

利基答案:

If you have a zfs pool on that device, at least when it's a file-based pool, lsofwill not show the usage. But you can simply run

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

sudo zpool export mypoo

and then unmount.

然后卸载。