如何找出哪些进程阻止卸载设备?

Ste*_*fan 106 process unmounting open-files

有时候,我想卸载USB设备使用umount /run/media/theDrive,但我得到一个drive is busy错误。

如何找出哪些进程或程序正在访问设备?

Pet*_*aut 94

使用lsof | grep /media/whatever找出正在使用安装。

此外,请考虑umount -l(lazy umount) 以防止新进程在清理时使用驱动器。

  • `fuser -mv /path/to/mountpoint` 可能是一种更易读的替代方法,用于使用点点查找进程。 (32认同)
  • [`umount -l` 是危险的](https://unix.stackexchange.com/q/390056/143394)。`mount -o bind` 一个模式为 `000` 的空目录在顶部,并通过 `lsof +f -- /dev/device` 清理。 (2认同)

Gil*_*il' 50

大多数时候,要使用的最佳命令是lsof的(“小号ö˚F尔斯”)。

lsof +f -- /media/usb0
Run Code Online (Sandbox Code Playgroud)

/media/usb0要卸载的 USB 驱动器或其他文件系统的挂载点在哪里。+f --告诉 lsof 将后续参数视为挂载点;它通常(但并非总是)自行管理,因此这lsof /media/usb0也有效。这会找到打开的文件(甚至未链接的文件)、内存映射文件、当前目录和一些更模糊的用途。您需要以 root 身份运行该命令以获取有关其他用户进程的信息(我认为有些 uniceslsof必须以 root 身份运行)。

有些用途是 lsof 找不到的;这些在可移动媒体上并不常见。它们包括:

  • 挂载点:/foo如果/foo/bar是挂载点,则无法卸载。
  • 挂载设备:/foo如果/foo/bar是已挂载的块设备或循环挂载的常规文件,或者它是 Linux 绑定挂载的源,则无法卸载。
  • NFS 导出:lsof 不会检测到内核 NFS 服务器导出的树。

另一个可以在紧要关头使用的命令是 fuser,它只列出设备上打开文件的进程的 PID:

fuser -m /media/usb0
Run Code Online (Sandbox Code Playgroud)


Tom*_*ale 14

打开文件

具有打开文件的进程是通常的罪魁祸首。显示它们:

lsof +f -- <mountpoint or device>
Run Code Online (Sandbox Code Playgroud)

使用/dev/<device>而不是有一个优点 /mountpoint:挂载点将在 之后消失umount -l,或者它可能被覆盖的挂载隐藏。

fuser也可以用,但在我看来lsof有更有用的输出。然而fuser,在杀死导致戏剧的进程时很有用,这样你就可以继续你的生活。

列出文件<mountpoint>(请参阅上面的警告):

fuser -vmM <mountpoint>
Run Code Online (Sandbox Code Playgroud)

仅以交互方式杀死打开文件进行写入的进程:

fuser -vmMkiw <mountpoint>
Run Code Online (Sandbox Code Playgroud)

重新挂载只读 ( mount -o remount,ro <mountpoint>) 后,可以安全地 (r) 终止所有剩余进程:

fuser -vmMk <mountpoint>
Run Code Online (Sandbox Code Playgroud)

挂载点

罪魁祸首可能是内核本身。安装在您尝试安装的文件系统上的另一个文件系统umount将导致悲痛。检查:

mount | grep <mountpoint>/
Run Code Online (Sandbox Code Playgroud)

对于环回挂载(感谢 Stephen Kitt),还要检查以下输出:

losetup -la
Run Code Online (Sandbox Code Playgroud)

匿名 inode (Linux)

匿名 inode可以通过以下方式创建:

  • 临时文件(openO_TMPFILE
  • inotify手表
  • [事件fd]
  • [事件投票]
  • [计时器]

这些是最难以捉摸的口袋妖怪类型,并且出现在lsofTYPE列中a_inode(在lsof手册页中没有记录 )。

它们不会出现在 中lsof +f -- /dev/<device>,因此您需要:

lsof | grep a_inode
Run Code Online (Sandbox Code Playgroud)

要杀死持有匿名 inode 的进程,请参阅:List current inotify watch (pathname, PID)

inotify 手表 (Linux)

这个注释解释了为什么inotify 不应该阻止卸载,但是这个注释描述了它会发生的情况:

卸载可以挂在vx_softcnt_flush()呼叫中。挂起的发生是因为inotify 观察者增加了i_count变量并导致v_os_hold value保持升高,直到 inotify 观察者释放保持。

  • 还有另一个,环回挂载:如果您挂载一个文件系统,然后使用环回挂载在该文件系统上挂载一个文件,您将无法卸载第一个文件系统,但在 `lsof` 中不会显示任何内容。 (3认同)

小智 8

你可以lsof像 Peter 说的那样使用,或者如果你确定你只想杀死所有这些东西并卸载它,你可以这样做:

fuser -Mk /mnt/path
umount /mnt/path
Run Code Online (Sandbox Code Playgroud)

  • `fuser`: `-M, --ismountpoint 请求只有在 NAME 指定一个挂载点时才会被满足。这是一个非常宝贵的安全带,如果 NAME 恰好不是文件系统,它可以防止您杀死机器。` (3认同)

tsh*_*ang 5

如果您使用 GNOME,通过 Nautilus 卸载将显示一条消息,说明哪个进程仍在使用该驱动器,以及它正在使用的文件。

替代文字